diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index bb69434428..30dcc86ba9 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -692,7 +692,9 @@ pub fn build_exp_call<'a, 'ctx, 'env>( ) } - CallType::ByPointer { name, .. } => { + CallType::ByPointer { + name, full_layout, .. + } => { let sub_expr = load_symbol(scope, name); let mut arg_vals: Vec = @@ -702,10 +704,25 @@ pub fn build_exp_call<'a, 'ctx, 'env>( arg_vals.push(load_symbol(scope, arg)); } - let call = match sub_expr { - BasicValueEnum::PointerValue(ptr) => { + let call = match (full_layout, sub_expr) { + (_, BasicValueEnum::PointerValue(ptr)) => { env.builder.build_call(ptr, arg_vals.as_slice(), "tmp") } + (Layout::Closure(_, _, _), BasicValueEnum::StructValue(closure_struct)) => { + let fpointer = env + .builder + .build_extract_value(closure_struct, 0, "fpointer") + .unwrap() + .into_pointer_value(); + + let closure_data = env + .builder + .build_extract_value(closure_struct, 1, "closure_data") + .unwrap(); + + arg_vals.push(closure_data); + env.builder.build_call(fpointer, arg_vals.as_slice(), "tmp") + } non_ptr => { panic!( "Tried to call by pointer, but encountered a non-pointer: {:?}", diff --git a/compiler/gen/tests/gen_primitives.rs b/compiler/gen/tests/gen_primitives.rs index 59b5760dda..3a247fad7e 100644 --- a/compiler/gen/tests/gen_primitives.rs +++ b/compiler/gen/tests/gen_primitives.rs @@ -1952,7 +1952,7 @@ mod gen_primitives { main = x : Tree F64 x = singleton 3 - when x is + when x is Tree 3.0 _ -> True _ -> False "# @@ -2215,4 +2215,23 @@ mod gen_primitives { i64 ); } + + #[test] + fn build_then_apply_closure() { + assert_evals_to!( + indoc!( + r#" + app "test" provides [ main ] to "./platform" + + main : Str + main = + x = "long string that is malloced" + + (\_ -> x) {} + "# + ), + "long string that is malloced", + &'static str + ); + } }