Merge remote-tracking branch 'origin/trunk' into remove-parse-def

This commit is contained in:
Folkert 2022-07-10 17:54:48 +02:00
commit a0fdb0b902
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
11 changed files with 307 additions and 296 deletions

View file

@ -1,5 +1,5 @@
use roc_gen_llvm::llvm::build::module_from_builtins;
pub use roc_gen_llvm::llvm::build::FunctionIterator; pub use roc_gen_llvm::llvm::build::FunctionIterator;
use roc_gen_llvm::llvm::build::{module_from_builtins, LlvmBackendMode};
use roc_load::{LoadedModule, MonomorphizedModule}; use roc_load::{LoadedModule, MonomorphizedModule};
use roc_module::symbol::{Interns, ModuleId}; use roc_module::symbol::{Interns, ModuleId};
use roc_mono::ir::OptLevel; use roc_mono::ir::OptLevel;
@ -255,9 +255,7 @@ pub fn gen_from_mono_module_llvm(
interns: loaded.interns, interns: loaded.interns,
module, module,
target_info, target_info,
// in gen_tests, the compiler provides roc_panic mode: LlvmBackendMode::Binary,
// and sets up the setjump/longjump exception handling
is_gen_test: false,
exposed_to_host: loaded.exposed_to_host.values.keys().copied().collect(), exposed_to_host: loaded.exposed_to_host.values.keys().copied().collect(),
}; };

View file

@ -1,8 +1,8 @@
use roc_parse::ast::{Collection, ExtractSpaces}; use roc_parse::ast::{Collection, CommentOrNewline, ExtractSpaces};
use crate::{ use crate::{
annotation::{Formattable, Newlines}, annotation::{Formattable, Newlines},
spaces::{count_leading_newlines, fmt_comments_only, NewlineAt, INDENT}, spaces::{fmt_comments_only, NewlineAt, INDENT},
Buf, Buf,
}; };
@ -41,24 +41,43 @@ pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable>(
buf.push(start); buf.push(start);
for (index, item) in items.iter().enumerate() { for (index, item) in items.iter().enumerate() {
let item = item.extract_spaces();
let is_first_item = index == 0; let is_first_item = index == 0;
let item = item.extract_spaces();
buf.newline();
if !item.before.is_empty() {
let is_only_newlines = item.before.iter().all(|s| s.is_newline()); let is_only_newlines = item.before.iter().all(|s| s.is_newline());
if !is_first_item if item.before.is_empty() || is_only_newlines {
&& !is_only_newlines buf.ensure_ends_in_newline();
&& count_leading_newlines(item.before.iter()) > 1 } else {
if is_first_item {
// The first item in a multiline collection always begins with exactly
// one newline (so the delimiter is at the end of its own line),
// and that newline appears before the first comment (if there is one).
buf.ensure_ends_in_newline();
} else {
if item.before.starts_with(&[CommentOrNewline::Newline]) {
buf.ensure_ends_in_newline();
}
if item
.before
.starts_with(&[CommentOrNewline::Newline, CommentOrNewline::Newline])
{ {
// If there's a comment, and it's not on the first item,
// and it's preceded by at least one blank line, maintain 1 blank line.
// (We already ensured that it ends in a newline, so this will turn that
// into a blank line.)
buf.newline();
}
}
fmt_comments_only(buf, item.before.iter(), NewlineAt::None, item_indent);
if !is_only_newlines {
if item.before.ends_with(&[CommentOrNewline::Newline]) {
buf.newline(); buf.newline();
} }
fmt_comments_only(buf, item.before.iter(), NewlineAt::Bottom, item_indent);
if !is_only_newlines && count_leading_newlines(item.before.iter().rev()) > 0 {
buf.newline(); buf.newline();
} }
} }
@ -68,21 +87,33 @@ pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable>(
buf.push(','); buf.push(',');
if !item.after.is_empty() { if !item.after.is_empty() {
fmt_comments_only(buf, item.after.iter(), NewlineAt::Top, item_indent); if item.after.iter().any(|s| s.is_newline()) {
buf.newline();
}
fmt_comments_only(buf, item.after.iter(), NewlineAt::None, item_indent);
} }
} }
if count_leading_newlines(items.final_comments().iter()) > 1 { if items.final_comments().iter().any(|s| s.is_newline()) {
buf.newline();
}
if items
.final_comments()
.starts_with(&[CommentOrNewline::Newline, CommentOrNewline::Newline])
{
buf.newline(); buf.newline();
} }
fmt_comments_only( fmt_comments_only(
buf, buf,
items.final_comments().iter(), items.final_comments().iter(),
NewlineAt::Top, NewlineAt::None,
item_indent, item_indent,
); );
buf.newline();
buf.ensure_ends_in_newline();
buf.indent(braces_indent); buf.indent(braces_indent);
} else { } else {
// is_multiline == false // is_multiline == false

View file

@ -2347,8 +2347,7 @@ mod test_fmt {
indoc!( indoc!(
r#" r#"
f : { f : {
x : Int *, x : Int *, # comment 1
# comment 1
# comment 2 # comment 2
} }
@ -4588,7 +4587,7 @@ mod test_fmt {
} }
#[test] #[test]
fn multiline_tag_union_annotation() { fn multiline_tag_union_annotation_no_comments() {
expr_formats_same(indoc!( expr_formats_same(indoc!(
r#" r#"
b : [ b : [
@ -4694,8 +4693,7 @@ mod test_fmt {
b : [ b : [
True, True,
# comment 1 # comment 1
False, False, # comment 2
# comment 2
# comment 3 # comment 3
] ]
@ -5082,6 +5080,38 @@ mod test_fmt {
); );
} }
#[test]
fn comments_in_multiline_tag_union_annotation() {
expr_formats_to(
indoc!(
r#"
UnionAnn : [
Foo, # comment 1
Bar, # comment 2
Baz, # comment 3
# comment 4 line 1
# comment 4 line 2
]
0
"#
),
indoc!(
r#"
UnionAnn : [
Foo, # comment 1
Bar, # comment 2
Baz, # comment 3
# comment 4 line 1
# comment 4 line 2
]
0
"#
),
);
}
#[test] #[test]
/// Test that everything under examples/ is formatted correctly /// Test that everything under examples/ is formatted correctly
/// If this test fails on your diff, it probably means you need to re-format the examples. /// If this test fails on your diff, it probably means you need to re-format the examples.

View file

@ -164,6 +164,16 @@ impl<'a, 'ctx> Scope<'a, 'ctx> {
} }
} }
#[derive(Debug, Clone, Copy)]
pub enum LlvmBackendMode {
/// Assumes primitives (roc_alloc, roc_panic, etc) are provided by the host
Binary,
/// Creates a test wrapper around the main roc function to catch and report panics.
/// Provides a testing implementation of primitives (roc_alloc, roc_panic, etc)
GenTest,
WasmGenTest,
}
pub struct Env<'a, 'ctx, 'env> { pub struct Env<'a, 'ctx, 'env> {
pub arena: &'a Bump, pub arena: &'a Bump,
pub context: &'ctx Context, pub context: &'ctx Context,
@ -173,7 +183,7 @@ pub struct Env<'a, 'ctx, 'env> {
pub module: &'ctx Module<'ctx>, pub module: &'ctx Module<'ctx>,
pub interns: Interns, pub interns: Interns,
pub target_info: TargetInfo, pub target_info: TargetInfo,
pub is_gen_test: bool, pub mode: LlvmBackendMode,
pub exposed_to_host: MutSet<Symbol>, pub exposed_to_host: MutSet<Symbol>,
} }
@ -3319,7 +3329,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>(
return_layout: Layout<'a>, return_layout: Layout<'a>,
c_function_name: &str, c_function_name: &str,
) -> FunctionValue<'ctx> { ) -> FunctionValue<'ctx> {
// NOTE we ingore env.is_gen_test here // NOTE we ingore env.mode here
let mut cc_argument_types = Vec::with_capacity_in(arguments.len(), env.arena); let mut cc_argument_types = Vec::with_capacity_in(arguments.len(), env.arena);
for layout in arguments { for layout in arguments {
@ -3411,8 +3421,8 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>(
let arguments_for_call = &arguments_for_call.into_bump_slice(); let arguments_for_call = &arguments_for_call.into_bump_slice();
let call_result = { let call_result = match env.mode {
if env.is_gen_test { LlvmBackendMode::GenTest | LlvmBackendMode::WasmGenTest => {
debug_assert_eq!(args.len(), roc_function.get_params().len()); debug_assert_eq!(args.len(), roc_function.get_params().len());
let roc_wrapper_function = make_exception_catcher(env, roc_function, return_layout); let roc_wrapper_function = make_exception_catcher(env, roc_function, return_layout);
@ -3425,7 +3435,8 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx, 'env>(
let wrapped_layout = roc_result_layout(env.arena, return_layout, env.target_info); let wrapped_layout = roc_result_layout(env.arena, return_layout, env.target_info);
call_roc_function(env, roc_function, &wrapped_layout, arguments_for_call) call_roc_function(env, roc_function, &wrapped_layout, arguments_for_call)
} else { }
LlvmBackendMode::Binary => {
call_roc_function(env, roc_function, &return_layout, arguments_for_call) call_roc_function(env, roc_function, &return_layout, arguments_for_call)
} }
}; };
@ -3695,7 +3706,8 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
return_layout: Layout<'a>, return_layout: Layout<'a>,
c_function_name: &str, c_function_name: &str,
) -> FunctionValue<'ctx> { ) -> FunctionValue<'ctx> {
if env.is_gen_test { match env.mode {
LlvmBackendMode::GenTest | LlvmBackendMode::WasmGenTest => {
return expose_function_to_host_help_c_abi_gen_test( return expose_function_to_host_help_c_abi_gen_test(
env, env,
ident_string, ident_string,
@ -3703,7 +3715,10 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
arguments, arguments,
return_layout, return_layout,
c_function_name, c_function_name,
); )
}
LlvmBackendMode::Binary => {}
} }
// a generic version that writes the result into a passed *u8 pointer // a generic version that writes the result into a passed *u8 pointer
@ -3749,11 +3764,12 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
debug_info_init!(env, size_function); debug_info_init!(env, size_function);
let return_type = if env.is_gen_test { let return_type = match env.mode {
LlvmBackendMode::GenTest | LlvmBackendMode::WasmGenTest => {
roc_result_type(env, roc_function.get_type().get_return_type().unwrap()).into() roc_result_type(env, roc_function.get_type().get_return_type().unwrap()).into()
} else { }
// roc_function.get_type().get_return_type().unwrap()
basic_type_from_layout(env, &return_layout) LlvmBackendMode::Binary => basic_type_from_layout(env, &return_layout),
}; };
let size: BasicValueEnum = return_type.size_of().unwrap().into(); let size: BasicValueEnum = return_type.size_of().unwrap().into();
@ -4494,7 +4510,8 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
} }
} }
if env.is_gen_test { match env.mode {
LlvmBackendMode::GenTest | LlvmBackendMode::WasmGenTest => {
let call_result = set_jump_and_catch_long_jump( let call_result = set_jump_and_catch_long_jump(
env, env,
function_value, function_value,
@ -4504,8 +4521,11 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
); );
builder.build_store(output, call_result); builder.build_store(output, call_result);
} else { }
let call_result = call_roc_function(env, evaluator, return_layout, &evaluator_arguments);
LlvmBackendMode::Binary => {
let call_result =
call_roc_function(env, evaluator, return_layout, &evaluator_arguments);
if return_layout.is_passed_by_reference(env.target_info) { if return_layout.is_passed_by_reference(env.target_info) {
let align_bytes = return_layout.alignment_bytes(env.target_info); let align_bytes = return_layout.alignment_bytes(env.target_info);
@ -4528,6 +4548,7 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
} else { } else {
builder.build_store(output, call_result); builder.build_store(output, call_result);
} }
}
}; };
builder.build_return(None); builder.build_return(None);

View file

@ -7,7 +7,7 @@ use inkwell::values::BasicValue;
use inkwell::AddressSpace; use inkwell::AddressSpace;
use roc_builtins::bitcode; use roc_builtins::bitcode;
use super::build::{get_sjlj_buffer, LLVM_LONGJMP}; use super::build::{get_sjlj_buffer, LlvmBackendMode, LLVM_LONGJMP};
/// Define functions for roc_alloc, roc_realloc, and roc_dealloc /// Define functions for roc_alloc, roc_realloc, and roc_dealloc
/// which use libc implementations (malloc, realloc, and free) /// which use libc implementations (malloc, realloc, and free)
@ -19,6 +19,10 @@ pub fn add_default_roc_externs(env: &Env<'_, '_, '_>) {
let usize_type = env.ptr_int(); let usize_type = env.ptr_int();
let i8_ptr_type = ctx.i8_type().ptr_type(AddressSpace::Generic); let i8_ptr_type = ctx.i8_type().ptr_type(AddressSpace::Generic);
match env.mode {
LlvmBackendMode::Binary => { /* externs are provided by the platform */ }
LlvmBackendMode::WasmGenTest => { /* externs are provided by the wasm test platform */ }
LlvmBackendMode::GenTest => {
// roc_alloc // roc_alloc
{ {
// The type of this function (but not the implementation) should have // The type of this function (but not the implementation) should have
@ -61,7 +65,8 @@ pub fn add_default_roc_externs(env: &Env<'_, '_, '_>) {
usize_type.into(), usize_type.into(),
], ],
); );
let fn_val = add_func(env.context, module, "realloc", fn_spec, Linkage::External); let fn_val =
add_func(env.context, module, "realloc", fn_spec, Linkage::External);
let mut params = fn_val.get_param_iter(); let mut params = fn_val.get_param_iter();
let ptr_arg = params.next().unwrap(); let ptr_arg = params.next().unwrap();
@ -139,9 +144,9 @@ pub fn add_default_roc_externs(env: &Env<'_, '_, '_>) {
} }
} }
if env.is_gen_test {
add_sjlj_roc_panic(env) add_sjlj_roc_panic(env)
} }
}
} }
pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) { pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {

View file

@ -8958,6 +8958,7 @@ where
ToLowLevelCall: Fn(ToLowLevelCallArguments<'a>) -> Call<'a> + Copy, ToLowLevelCall: Fn(ToLowLevelCallArguments<'a>) -> Call<'a> + Copy,
{ {
match lambda_set.runtime_representation() { match lambda_set.runtime_representation() {
Layout::VOID => empty_lambda_set_error(),
Layout::Union(union_layout) => { Layout::Union(union_layout) => {
let closure_tag_id_symbol = env.unique_symbol(); let closure_tag_id_symbol = env.unique_symbol();
@ -9117,6 +9118,11 @@ where
} }
} }
fn empty_lambda_set_error() -> Stmt<'static> {
let msg = "a Lambda Set is empty. Most likely there is a type error in your program.";
Stmt::RuntimeError(msg)
}
/// Use the lambda set to figure out how to make a call-by-name /// Use the lambda set to figure out how to make a call-by-name
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
fn match_on_lambda_set<'a>( fn match_on_lambda_set<'a>(
@ -9131,6 +9137,7 @@ fn match_on_lambda_set<'a>(
hole: &'a Stmt<'a>, hole: &'a Stmt<'a>,
) -> Stmt<'a> { ) -> Stmt<'a> {
match lambda_set.runtime_representation() { match lambda_set.runtime_representation() {
Layout::VOID => empty_lambda_set_error(),
Layout::Union(union_layout) => { Layout::Union(union_layout) => {
let closure_tag_id_symbol = env.unique_symbol(); let closure_tag_id_symbol = env.unique_symbol();
@ -9260,9 +9267,7 @@ fn union_lambda_set_to_switch<'a>(
// there is really nothing we can do here. We generate a runtime error here which allows // there is really nothing we can do here. We generate a runtime error here which allows
// code gen to proceed. We then assume that we hit another (more descriptive) error before // code gen to proceed. We then assume that we hit another (more descriptive) error before
// hitting this one // hitting this one
return empty_lambda_set_error();
let msg = "a Lambda Set is empty. Most likely there is a type error in your program.";
return Stmt::RuntimeError(msg);
} }
let join_point_id = JoinPointId(env.unique_symbol()); let join_point_id = JoinPointId(env.unique_symbol());

View file

@ -6,7 +6,7 @@ pub use helpers::platform_functions::*;
use bumpalo::Bump; use bumpalo::Bump;
use criterion::{black_box, criterion_group, criterion_main, Criterion}; use criterion::{black_box, criterion_group, criterion_main, Criterion};
use roc_gen_llvm::{run_roc::RocCallResult, run_roc_dylib}; use roc_gen_llvm::{llvm::build::LlvmBackendMode, run_roc::RocCallResult, run_roc_dylib};
use roc_mono::ir::OptLevel; use roc_mono::ir::OptLevel;
use roc_std::RocList; use roc_std::RocList;
@ -50,7 +50,7 @@ fn roc_function<'a, 'b>(
source: &str, source: &str,
) -> libloading::Symbol<'a, Main<&'b Input, Output>> { ) -> libloading::Symbol<'a, Main<&'b Input, Output>> {
let config = helpers::llvm::HelperConfig { let config = helpers::llvm::HelperConfig {
is_gen_test: true, mode: LlvmBackendMode::GenTest,
ignore_problems: false, ignore_problems: false,
add_debug_info: true, add_debug_info: true,
opt_level: OptLevel::Optimize, opt_level: OptLevel::Optimize,

View file

@ -240,26 +240,5 @@ macro_rules! assert_evals_to {
}; };
} }
#[allow(unused_macros)]
macro_rules! assert_expect_failed {
($src:expr, $expected:expr, $ty:ty, $failures:expr) => {{
use bumpalo::Bump;
use roc_gen_dev::run_jit_function_raw;
let stdlib = roc_builtins::std::standard_stdlib();
let arena = Bump::new();
let (main_fn_name, errors, lib) =
$crate::helpers::dev::helper(&arena, $src, stdlib, true, true);
let transform = |success| {
let expected = $expected;
assert_eq!(&success, &expected);
};
run_jit_function_raw!(lib, main_fn_name, $ty, transform, errors);
}};
}
#[allow(unused_imports)] #[allow(unused_imports)]
pub(crate) use assert_evals_to; pub(crate) use assert_evals_to;
#[allow(unused_imports)]
pub(crate) use assert_expect_failed;

View file

@ -4,6 +4,7 @@ use libloading::Library;
use roc_build::link::llvm_module_to_dylib; use roc_build::link::llvm_module_to_dylib;
use roc_build::program::FunctionIterator; use roc_build::program::FunctionIterator;
use roc_collections::all::MutSet; use roc_collections::all::MutSet;
use roc_gen_llvm::llvm::build::LlvmBackendMode;
use roc_gen_llvm::llvm::externs::add_default_roc_externs; use roc_gen_llvm::llvm::externs::add_default_roc_externs;
use roc_load::Threading; use roc_load::Threading;
use roc_mono::ir::OptLevel; use roc_mono::ir::OptLevel;
@ -11,6 +12,12 @@ use roc_region::all::LineInfo;
use roc_reporting::report::RenderTarget; use roc_reporting::report::RenderTarget;
use target_lexicon::Triple; use target_lexicon::Triple;
pub const OPT_LEVEL: OptLevel = if cfg!(debug_assertions) {
OptLevel::Normal
} else {
OptLevel::Optimize
};
fn promote_expr_to_module(src: &str) -> String { fn promote_expr_to_module(src: &str) -> String {
let mut buffer = String::from("app \"test\" provides [main] to \"./platform\"\n\nmain =\n"); let mut buffer = String::from("app \"test\" provides [main] to \"./platform\"\n\nmain =\n");
@ -28,11 +35,9 @@ fn promote_expr_to_module(src: &str) -> String {
fn create_llvm_module<'a>( fn create_llvm_module<'a>(
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
src: &str, src: &str,
is_gen_test: bool, config: HelperConfig,
ignore_problems: bool,
context: &'a inkwell::context::Context, context: &'a inkwell::context::Context,
target: &Triple, target: &Triple,
opt_level: OptLevel,
) -> (&'static str, String, &'a Module<'a>) { ) -> (&'static str, String, &'a Module<'a>) {
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -149,7 +154,7 @@ fn create_llvm_module<'a>(
println!("{}", lines.join("\n")); println!("{}", lines.join("\n"));
// only crash at this point if there were no delayed_errors // only crash at this point if there were no delayed_errors
if delayed_errors.is_empty() && !ignore_problems { if delayed_errors.is_empty() && !config.ignore_problems {
assert_eq!(0, 1, "Mistakes were made"); assert_eq!(0, 1, "Mistakes were made");
} }
} }
@ -159,7 +164,7 @@ fn create_llvm_module<'a>(
let module = arena.alloc(module); let module = arena.alloc(module);
let (module_pass, function_pass) = let (module_pass, function_pass) =
roc_gen_llvm::llvm::build::construct_optimization_passes(module, opt_level); roc_gen_llvm::llvm::build::construct_optimization_passes(module, config.opt_level);
let (dibuilder, compile_unit) = roc_gen_llvm::llvm::build::Env::new_debug_info(module); let (dibuilder, compile_unit) = roc_gen_llvm::llvm::build::Env::new_debug_info(module);
@ -200,7 +205,7 @@ fn create_llvm_module<'a>(
interns, interns,
module, module,
target_info, target_info,
is_gen_test, mode: config.mode,
// important! we don't want any procedures to get the C calling convention // important! we don't want any procedures to get the C calling convention
exposed_to_host: MutSet::default(), exposed_to_host: MutSet::default(),
}; };
@ -214,7 +219,7 @@ fn create_llvm_module<'a>(
let (main_fn_name, main_fn) = roc_gen_llvm::llvm::build::build_procedures_return_main( let (main_fn_name, main_fn) = roc_gen_llvm::llvm::build::build_procedures_return_main(
&env, &env,
opt_level, config.opt_level,
procedures, procedures,
entry_point, entry_point,
); );
@ -248,7 +253,7 @@ fn create_llvm_module<'a>(
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct HelperConfig { pub struct HelperConfig {
pub is_gen_test: bool, pub mode: LlvmBackendMode,
pub ignore_problems: bool, pub ignore_problems: bool,
pub add_debug_info: bool, pub add_debug_info: bool,
pub opt_level: OptLevel, pub opt_level: OptLevel,
@ -264,15 +269,8 @@ pub fn helper<'a>(
) -> (&'static str, String, Library) { ) -> (&'static str, String, Library) {
let target = target_lexicon::Triple::host(); let target = target_lexicon::Triple::host();
let (main_fn_name, delayed_errors, module) = create_llvm_module( let (main_fn_name, delayed_errors, module) =
arena, create_llvm_module(arena, src, config, context, &target);
src,
config.is_gen_test,
config.ignore_problems,
context,
&target,
config.opt_level,
);
let res_lib = if config.add_debug_info { let res_lib = if config.add_debug_info {
let module = annotate_with_debug_info(module, context); let module = annotate_with_debug_info(module, context);
@ -338,29 +336,14 @@ fn wasm32_target_tripple() -> Triple {
#[allow(dead_code)] #[allow(dead_code)]
pub fn helper_wasm<'a>( pub fn helper_wasm<'a>(
arena: &'a bumpalo::Bump, arena: &'a bumpalo::Bump,
config: HelperConfig,
src: &str, src: &str,
_is_gen_test: bool,
ignore_problems: bool,
context: &'a inkwell::context::Context, context: &'a inkwell::context::Context,
) -> wasmer::Instance { ) -> wasmer::Instance {
let target = wasm32_target_tripple(); let target = wasm32_target_tripple();
let opt_level = if cfg!(debug_assertions) { let (_main_fn_name, _delayed_errors, llvm_module) =
OptLevel::Normal create_llvm_module(arena, src, config, context, &target);
} else {
OptLevel::Optimize
};
let is_gen_test = false;
let (_main_fn_name, _delayed_errors, llvm_module) = create_llvm_module(
arena,
src,
is_gen_test,
ignore_problems,
context,
&target,
opt_level,
);
use inkwell::targets::{InitializationConfig, Target, TargetTriple}; use inkwell::targets::{InitializationConfig, Target, TargetTriple};
@ -497,10 +480,14 @@ where
let arena = bumpalo::Bump::new(); let arena = bumpalo::Bump::new();
let context = inkwell::context::Context::create(); let context = inkwell::context::Context::create();
let is_gen_test = true; let config = HelperConfig {
let instance = mode: LlvmBackendMode::WasmGenTest,
crate::helpers::llvm::helper_wasm(&arena, src, is_gen_test, ignore_problems, &context); add_debug_info: false,
ignore_problems,
opt_level: OPT_LEVEL,
};
let instance = crate::helpers::llvm::helper_wasm(&arena, config, src, &context);
let memory = instance.exports.get_memory("memory").unwrap(); let memory = instance.exports.get_memory("memory").unwrap();
crate::helpers::llvm::MEMORY.with(|f| { crate::helpers::llvm::MEMORY.with(|f| {
@ -557,23 +544,17 @@ macro_rules! assert_llvm_evals_to {
($src:expr, $expected:expr, $ty:ty, $transform:expr, $ignore_problems:expr) => { ($src:expr, $expected:expr, $ty:ty, $transform:expr, $ignore_problems:expr) => {
use bumpalo::Bump; use bumpalo::Bump;
use inkwell::context::Context; use inkwell::context::Context;
use roc_gen_llvm::llvm::build::LlvmBackendMode;
use roc_gen_llvm::run_jit_function; use roc_gen_llvm::run_jit_function;
use roc_mono::ir::OptLevel;
let arena = Bump::new(); let arena = Bump::new();
let context = Context::create(); let context = Context::create();
let opt_level = if cfg!(debug_assertions) {
OptLevel::Normal
} else {
OptLevel::Optimize
};
let config = $crate::helpers::llvm::HelperConfig { let config = $crate::helpers::llvm::HelperConfig {
is_gen_test: true, mode: LlvmBackendMode::GenTest,
add_debug_info: false, add_debug_info: false,
ignore_problems: $ignore_problems, ignore_problems: $ignore_problems,
opt_level, opt_level: $crate::helpers::llvm::OPT_LEVEL,
}; };
let (main_fn_name, errors, lib) = let (main_fn_name, errors, lib) =
@ -633,43 +614,6 @@ macro_rules! assert_evals_to {
}}; }};
} }
#[allow(unused_macros)]
macro_rules! assert_expect_failed {
($src:expr, $expected:expr, $ty:ty) => {
use bumpalo::Bump;
use inkwell::context::Context;
use roc_gen_llvm::run_jit_function;
let arena = Bump::new();
let context = Context::create();
let is_gen_test = true;
let (main_fn_name, errors, lib) =
$crate::helpers::llvm::helper(&arena, $src, is_gen_test, false, &context);
let transform = |success| {
let expected = $expected;
assert_eq!(&success, &expected, "LLVM test failed");
};
run_jit_function!(lib, main_fn_name, $ty, transform, errors)
};
($src:expr, $expected:expr, $ty:ty) => {
$crate::helpers::llvm::assert_llvm_evals_to!(
$src,
$expected,
$ty,
$crate::helpers::llvm::identity,
false
);
};
($src:expr, $expected:expr, $ty:ty, $transform:expr) => {
$crate::helpers::llvm::assert_llvm_evals_to!($src, $expected, $ty, $transform, false);
};
}
macro_rules! expect_runtime_error_panic { macro_rules! expect_runtime_error_panic {
($src:expr) => {{ ($src:expr) => {{
#[cfg(feature = "wasm-cli-run")] #[cfg(feature = "wasm-cli-run")]
@ -720,8 +664,6 @@ macro_rules! assert_non_opt_evals_to {
#[allow(unused_imports)] #[allow(unused_imports)]
pub(crate) use assert_evals_to; pub(crate) use assert_evals_to;
#[allow(unused_imports)] #[allow(unused_imports)]
pub(crate) use assert_expect_failed;
#[allow(unused_imports)]
pub(crate) use assert_llvm_evals_to; pub(crate) use assert_llvm_evals_to;
#[allow(unused_imports)] #[allow(unused_imports)]
pub(crate) use assert_non_opt_evals_to; pub(crate) use assert_non_opt_evals_to;

View file

@ -5,7 +5,6 @@ procedure List.5 (#Attr.2, #Attr.3):
procedure Test.2 (Test.3): procedure Test.2 (Test.3):
let Test.7 : {} = Struct {}; let Test.7 : {} = Struct {};
let Test.8 : U8 = GetTagId Test.3;
Error a Lambda Set is empty. Most likely there is a type error in your program. Error a Lambda Set is empty. Most likely there is a type error in your program.
procedure Test.0 (): procedure Test.0 ():

View file

@ -2,6 +2,7 @@ use bumpalo::Bump;
use const_format::concatcp; use const_format::concatcp;
use inkwell::context::Context; use inkwell::context::Context;
use libloading::Library; use libloading::Library;
use roc_gen_llvm::llvm::build::LlvmBackendMode;
use roc_types::subs::Subs; use roc_types::subs::Subs;
use rustyline::highlight::{Highlighter, PromptInfo}; use rustyline::highlight::{Highlighter, PromptInfo};
use rustyline::validate::{self, ValidationContext, ValidationResult, Validator}; use rustyline::validate::{self, ValidationContext, ValidationResult, Validator};
@ -228,7 +229,7 @@ pub fn expect_mono_module_to_dylib<'a>(
interns, interns,
module, module,
target_info, target_info,
is_gen_test: true, // so roc_panic is generated mode: LlvmBackendMode::GenTest, // so roc_panic is generated
// important! we don't want any procedures to get the C calling convention // important! we don't want any procedures to get the C calling convention
exposed_to_host: MutSet::default(), exposed_to_host: MutSet::default(),
}; };
@ -306,7 +307,7 @@ pub fn mono_module_to_dylib<'a>(
interns, interns,
module, module,
target_info, target_info,
is_gen_test: true, // so roc_panic is generated mode: LlvmBackendMode::GenTest, // so roc_panic is generated
// important! we don't want any procedures to get the C calling convention // important! we don't want any procedures to get the C calling convention
exposed_to_host: MutSet::default(), exposed_to_host: MutSet::default(),
}; };