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;
use roc_gen_llvm::llvm::build::{module_from_builtins, LlvmBackendMode};
use roc_load::{LoadedModule, MonomorphizedModule};
use roc_module::symbol::{Interns, ModuleId};
use roc_mono::ir::OptLevel;
@ -255,9 +255,7 @@ pub fn gen_from_mono_module_llvm(
interns: loaded.interns,
module,
target_info,
// in gen_tests, the compiler provides roc_panic
// and sets up the setjump/longjump exception handling
is_gen_test: false,
mode: LlvmBackendMode::Binary,
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::{
annotation::{Formattable, Newlines},
spaces::{count_leading_newlines, fmt_comments_only, NewlineAt, INDENT},
spaces::{fmt_comments_only, NewlineAt, INDENT},
Buf,
};
@ -41,24 +41,43 @@ pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable>(
buf.push(start);
for (index, item) in items.iter().enumerate() {
let item = item.extract_spaces();
let is_first_item = index == 0;
let item = item.extract_spaces();
let is_only_newlines = item.before.iter().all(|s| s.is_newline());
buf.newline();
if item.before.is_empty() || is_only_newlines {
buf.ensure_ends_in_newline();
} 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.is_empty() {
let is_only_newlines = item.before.iter().all(|s| s.is_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.)
if !is_first_item
&& !is_only_newlines
&& count_leading_newlines(item.before.iter()) > 1
{
buf.newline();
buf.newline();
}
}
fmt_comments_only(buf, item.before.iter(), NewlineAt::Bottom, item_indent);
fmt_comments_only(buf, item.before.iter(), NewlineAt::None, item_indent);
if !is_only_newlines {
if item.before.ends_with(&[CommentOrNewline::Newline]) {
buf.newline();
}
if !is_only_newlines && count_leading_newlines(item.before.iter().rev()) > 0 {
buf.newline();
}
}
@ -68,21 +87,33 @@ pub fn fmt_collection<'a, 'buf, T: ExtractSpaces<'a> + Formattable>(
buf.push(',');
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();
}
fmt_comments_only(
buf,
items.final_comments().iter(),
NewlineAt::Top,
NewlineAt::None,
item_indent,
);
buf.newline();
buf.ensure_ends_in_newline();
buf.indent(braces_indent);
} else {
// is_multiline == false

View file

@ -2347,8 +2347,7 @@ mod test_fmt {
indoc!(
r#"
f : {
x : Int *,
# comment 1
x : Int *, # comment 1
# comment 2
}
@ -4588,7 +4587,7 @@ mod test_fmt {
}
#[test]
fn multiline_tag_union_annotation() {
fn multiline_tag_union_annotation_no_comments() {
expr_formats_same(indoc!(
r#"
b : [
@ -4694,8 +4693,7 @@ mod test_fmt {
b : [
True,
# comment 1
False,
# comment 2
False, # comment 2
# 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 that everything under examples/ is formatted correctly
/// 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 arena: &'a Bump,
pub context: &'ctx Context,
@ -173,7 +183,7 @@ pub struct Env<'a, 'ctx, 'env> {
pub module: &'ctx Module<'ctx>,
pub interns: Interns,
pub target_info: TargetInfo,
pub is_gen_test: bool,
pub mode: LlvmBackendMode,
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>,
c_function_name: &str,
) -> 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);
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 call_result = {
if env.is_gen_test {
let call_result = match env.mode {
LlvmBackendMode::GenTest | LlvmBackendMode::WasmGenTest => {
debug_assert_eq!(args.len(), roc_function.get_params().len());
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);
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)
}
};
@ -3695,15 +3706,19 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
return_layout: Layout<'a>,
c_function_name: &str,
) -> FunctionValue<'ctx> {
if env.is_gen_test {
return expose_function_to_host_help_c_abi_gen_test(
env,
ident_string,
roc_function,
arguments,
return_layout,
c_function_name,
);
match env.mode {
LlvmBackendMode::GenTest | LlvmBackendMode::WasmGenTest => {
return expose_function_to_host_help_c_abi_gen_test(
env,
ident_string,
roc_function,
arguments,
return_layout,
c_function_name,
)
}
LlvmBackendMode::Binary => {}
}
// 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);
let return_type = if env.is_gen_test {
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)
let return_type = match env.mode {
LlvmBackendMode::GenTest | LlvmBackendMode::WasmGenTest => {
roc_result_type(env, roc_function.get_type().get_return_type().unwrap()).into()
}
LlvmBackendMode::Binary => basic_type_from_layout(env, &return_layout),
};
let size: BasicValueEnum = return_type.size_of().unwrap().into();
@ -4494,40 +4510,45 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
}
}
if env.is_gen_test {
let call_result = set_jump_and_catch_long_jump(
env,
function_value,
evaluator,
&evaluator_arguments,
*return_layout,
);
match env.mode {
LlvmBackendMode::GenTest | LlvmBackendMode::WasmGenTest => {
let call_result = set_jump_and_catch_long_jump(
env,
function_value,
evaluator,
&evaluator_arguments,
*return_layout,
);
builder.build_store(output, call_result);
} else {
let call_result = call_roc_function(env, evaluator, return_layout, &evaluator_arguments);
if return_layout.is_passed_by_reference(env.target_info) {
let align_bytes = return_layout.alignment_bytes(env.target_info);
if align_bytes > 0 {
let size = env
.ptr_int()
.const_int(return_layout.stack_size(env.target_info) as u64, false);
env.builder
.build_memcpy(
output,
align_bytes,
call_result.into_pointer_value(),
align_bytes,
size,
)
.unwrap();
}
} else {
builder.build_store(output, call_result);
}
LlvmBackendMode::Binary => {
let call_result =
call_roc_function(env, evaluator, return_layout, &evaluator_arguments);
if return_layout.is_passed_by_reference(env.target_info) {
let align_bytes = return_layout.alignment_bytes(env.target_info);
if align_bytes > 0 {
let size = env
.ptr_int()
.const_int(return_layout.stack_size(env.target_info) as u64, false);
env.builder
.build_memcpy(
output,
align_bytes,
call_result.into_pointer_value(),
align_bytes,
size,
)
.unwrap();
}
} else {
builder.build_store(output, call_result);
}
}
};
builder.build_return(None);

View file

@ -7,7 +7,7 @@ use inkwell::values::BasicValue;
use inkwell::AddressSpace;
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
/// which use libc implementations (malloc, realloc, and free)
@ -19,129 +19,134 @@ pub fn add_default_roc_externs(env: &Env<'_, '_, '_>) {
let usize_type = env.ptr_int();
let i8_ptr_type = ctx.i8_type().ptr_type(AddressSpace::Generic);
// roc_alloc
{
// The type of this function (but not the implementation) should have
// already been defined by the builtins, which rely on it.
let fn_val = module.get_function("roc_alloc").unwrap();
let mut params = fn_val.get_param_iter();
let size_arg = params.next().unwrap();
let _alignment_arg = params.next().unwrap();
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
{
// The type of this function (but not the implementation) should have
// already been defined by the builtins, which rely on it.
let fn_val = module.get_function("roc_alloc").unwrap();
let mut params = fn_val.get_param_iter();
let size_arg = params.next().unwrap();
let _alignment_arg = params.next().unwrap();
debug_assert!(params.next().is_none());
debug_assert!(params.next().is_none());
// Add a basic block for the entry point
let entry = ctx.append_basic_block(fn_val, "entry");
// Add a basic block for the entry point
let entry = ctx.append_basic_block(fn_val, "entry");
builder.position_at_end(entry);
builder.position_at_end(entry);
// Call libc malloc()
let retval = builder
.build_array_malloc(ctx.i8_type(), size_arg.into_int_value(), "call_malloc")
.unwrap();
// Call libc malloc()
let retval = builder
.build_array_malloc(ctx.i8_type(), size_arg.into_int_value(), "call_malloc")
.unwrap();
builder.build_return(Some(&retval));
builder.build_return(Some(&retval));
if cfg!(debug_assertions) {
crate::llvm::build::verify_fn(fn_val);
}
}
// roc_realloc
{
let libc_realloc_val = {
let fn_spec = FunctionSpec::cconv(
env,
CCReturn::Return,
Some(i8_ptr_type.as_basic_type_enum()),
&[
// ptr: *void
i8_ptr_type.into(),
// size: usize
usize_type.into(),
],
);
let fn_val = add_func(env.context, module, "realloc", fn_spec, Linkage::External);
let mut params = fn_val.get_param_iter();
let ptr_arg = params.next().unwrap();
let size_arg = params.next().unwrap();
debug_assert!(params.next().is_none());
ptr_arg.set_name("ptr");
size_arg.set_name("size");
if cfg!(debug_assertions) {
crate::llvm::build::verify_fn(fn_val);
if cfg!(debug_assertions) {
crate::llvm::build::verify_fn(fn_val);
}
}
fn_val
};
// roc_realloc
{
let libc_realloc_val = {
let fn_spec = FunctionSpec::cconv(
env,
CCReturn::Return,
Some(i8_ptr_type.as_basic_type_enum()),
&[
// ptr: *void
i8_ptr_type.into(),
// size: usize
usize_type.into(),
],
);
let fn_val =
add_func(env.context, module, "realloc", fn_spec, Linkage::External);
// The type of this function (but not the implementation) should have
// already been defined by the builtins, which rely on it.
let fn_val = module.get_function("roc_realloc").unwrap();
let mut params = fn_val.get_param_iter();
let ptr_arg = params.next().unwrap();
let new_size_arg = params.next().unwrap();
let _old_size_arg = params.next().unwrap();
let _alignment_arg = params.next().unwrap();
let mut params = fn_val.get_param_iter();
let ptr_arg = params.next().unwrap();
let size_arg = params.next().unwrap();
debug_assert!(params.next().is_none());
debug_assert!(params.next().is_none());
// Add a basic block for the entry point
let entry = ctx.append_basic_block(fn_val, "entry");
ptr_arg.set_name("ptr");
size_arg.set_name("size");
builder.position_at_end(entry);
if cfg!(debug_assertions) {
crate::llvm::build::verify_fn(fn_val);
}
// Call libc realloc()
let call = builder.build_call(
libc_realloc_val,
&[ptr_arg.into(), new_size_arg.into()],
"call_libc_realloc",
);
fn_val
};
call.set_call_convention(C_CALL_CONV);
// The type of this function (but not the implementation) should have
// already been defined by the builtins, which rely on it.
let fn_val = module.get_function("roc_realloc").unwrap();
let mut params = fn_val.get_param_iter();
let ptr_arg = params.next().unwrap();
let new_size_arg = params.next().unwrap();
let _old_size_arg = params.next().unwrap();
let _alignment_arg = params.next().unwrap();
let retval = call.try_as_basic_value().left().unwrap();
debug_assert!(params.next().is_none());
builder.build_return(Some(&retval));
// Add a basic block for the entry point
let entry = ctx.append_basic_block(fn_val, "entry");
if cfg!(debug_assertions) {
crate::llvm::build::verify_fn(fn_val);
builder.position_at_end(entry);
// Call libc realloc()
let call = builder.build_call(
libc_realloc_val,
&[ptr_arg.into(), new_size_arg.into()],
"call_libc_realloc",
);
call.set_call_convention(C_CALL_CONV);
let retval = call.try_as_basic_value().left().unwrap();
builder.build_return(Some(&retval));
if cfg!(debug_assertions) {
crate::llvm::build::verify_fn(fn_val);
}
}
// roc_dealloc
{
// The type of this function (but not the implementation) should have
// already been defined by the builtins, which rely on it.
let fn_val = module.get_function("roc_dealloc").unwrap();
let mut params = fn_val.get_param_iter();
let ptr_arg = params.next().unwrap();
let _alignment_arg = params.next().unwrap();
debug_assert!(params.next().is_none());
// Add a basic block for the entry point
let entry = ctx.append_basic_block(fn_val, "entry");
builder.position_at_end(entry);
// Call libc free()
builder.build_free(ptr_arg.into_pointer_value());
builder.build_return(None);
if cfg!(debug_assertions) {
crate::llvm::build::verify_fn(fn_val);
}
}
add_sjlj_roc_panic(env)
}
}
// roc_dealloc
{
// The type of this function (but not the implementation) should have
// already been defined by the builtins, which rely on it.
let fn_val = module.get_function("roc_dealloc").unwrap();
let mut params = fn_val.get_param_iter();
let ptr_arg = params.next().unwrap();
let _alignment_arg = params.next().unwrap();
debug_assert!(params.next().is_none());
// Add a basic block for the entry point
let entry = ctx.append_basic_block(fn_val, "entry");
builder.position_at_end(entry);
// Call libc free()
builder.build_free(ptr_arg.into_pointer_value());
builder.build_return(None);
if cfg!(debug_assertions) {
crate::llvm::build::verify_fn(fn_val);
}
}
if env.is_gen_test {
add_sjlj_roc_panic(env)
}
}
pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {

View file

@ -8958,6 +8958,7 @@ where
ToLowLevelCall: Fn(ToLowLevelCallArguments<'a>) -> Call<'a> + Copy,
{
match lambda_set.runtime_representation() {
Layout::VOID => empty_lambda_set_error(),
Layout::Union(union_layout) => {
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
#[allow(clippy::too_many_arguments)]
fn match_on_lambda_set<'a>(
@ -9131,6 +9137,7 @@ fn match_on_lambda_set<'a>(
hole: &'a Stmt<'a>,
) -> Stmt<'a> {
match lambda_set.runtime_representation() {
Layout::VOID => empty_lambda_set_error(),
Layout::Union(union_layout) => {
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
// code gen to proceed. We then assume that we hit another (more descriptive) error before
// hitting this one
let msg = "a Lambda Set is empty. Most likely there is a type error in your program.";
return Stmt::RuntimeError(msg);
return empty_lambda_set_error();
}
let join_point_id = JoinPointId(env.unique_symbol());

View file

@ -6,7 +6,7 @@ pub use helpers::platform_functions::*;
use bumpalo::Bump;
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_std::RocList;
@ -50,7 +50,7 @@ fn roc_function<'a, 'b>(
source: &str,
) -> libloading::Symbol<'a, Main<&'b Input, Output>> {
let config = helpers::llvm::HelperConfig {
is_gen_test: true,
mode: LlvmBackendMode::GenTest,
ignore_problems: false,
add_debug_info: true,
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)]
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::program::FunctionIterator;
use roc_collections::all::MutSet;
use roc_gen_llvm::llvm::build::LlvmBackendMode;
use roc_gen_llvm::llvm::externs::add_default_roc_externs;
use roc_load::Threading;
use roc_mono::ir::OptLevel;
@ -11,6 +12,12 @@ use roc_region::all::LineInfo;
use roc_reporting::report::RenderTarget;
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 {
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>(
arena: &'a bumpalo::Bump,
src: &str,
is_gen_test: bool,
ignore_problems: bool,
config: HelperConfig,
context: &'a inkwell::context::Context,
target: &Triple,
opt_level: OptLevel,
) -> (&'static str, String, &'a Module<'a>) {
use std::path::{Path, PathBuf};
@ -149,7 +154,7 @@ fn create_llvm_module<'a>(
println!("{}", lines.join("\n"));
// 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");
}
}
@ -159,7 +164,7 @@ fn create_llvm_module<'a>(
let module = arena.alloc(module);
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);
@ -200,7 +205,7 @@ fn create_llvm_module<'a>(
interns,
module,
target_info,
is_gen_test,
mode: config.mode,
// important! we don't want any procedures to get the C calling convention
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(
&env,
opt_level,
config.opt_level,
procedures,
entry_point,
);
@ -248,7 +253,7 @@ fn create_llvm_module<'a>(
#[derive(Debug, Clone, Copy)]
pub struct HelperConfig {
pub is_gen_test: bool,
pub mode: LlvmBackendMode,
pub ignore_problems: bool,
pub add_debug_info: bool,
pub opt_level: OptLevel,
@ -264,15 +269,8 @@ pub fn helper<'a>(
) -> (&'static str, String, Library) {
let target = target_lexicon::Triple::host();
let (main_fn_name, delayed_errors, module) = create_llvm_module(
arena,
src,
config.is_gen_test,
config.ignore_problems,
context,
&target,
config.opt_level,
);
let (main_fn_name, delayed_errors, module) =
create_llvm_module(arena, src, config, context, &target);
let res_lib = if config.add_debug_info {
let module = annotate_with_debug_info(module, context);
@ -338,29 +336,14 @@ fn wasm32_target_tripple() -> Triple {
#[allow(dead_code)]
pub fn helper_wasm<'a>(
arena: &'a bumpalo::Bump,
config: HelperConfig,
src: &str,
_is_gen_test: bool,
ignore_problems: bool,
context: &'a inkwell::context::Context,
) -> wasmer::Instance {
let target = wasm32_target_tripple();
let opt_level = if cfg!(debug_assertions) {
OptLevel::Normal
} 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,
);
let (_main_fn_name, _delayed_errors, llvm_module) =
create_llvm_module(arena, src, config, context, &target);
use inkwell::targets::{InitializationConfig, Target, TargetTriple};
@ -497,10 +480,14 @@ where
let arena = bumpalo::Bump::new();
let context = inkwell::context::Context::create();
let is_gen_test = true;
let instance =
crate::helpers::llvm::helper_wasm(&arena, src, is_gen_test, ignore_problems, &context);
let config = HelperConfig {
mode: LlvmBackendMode::WasmGenTest,
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();
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) => {
use bumpalo::Bump;
use inkwell::context::Context;
use roc_gen_llvm::llvm::build::LlvmBackendMode;
use roc_gen_llvm::run_jit_function;
use roc_mono::ir::OptLevel;
let arena = Bump::new();
let context = Context::create();
let opt_level = if cfg!(debug_assertions) {
OptLevel::Normal
} else {
OptLevel::Optimize
};
let config = $crate::helpers::llvm::HelperConfig {
is_gen_test: true,
mode: LlvmBackendMode::GenTest,
add_debug_info: false,
ignore_problems: $ignore_problems,
opt_level,
opt_level: $crate::helpers::llvm::OPT_LEVEL,
};
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 {
($src:expr) => {{
#[cfg(feature = "wasm-cli-run")]
@ -720,8 +664,6 @@ macro_rules! assert_non_opt_evals_to {
#[allow(unused_imports)]
pub(crate) use assert_evals_to;
#[allow(unused_imports)]
pub(crate) use assert_expect_failed;
#[allow(unused_imports)]
pub(crate) use assert_llvm_evals_to;
#[allow(unused_imports)]
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):
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.
procedure Test.0 ():