From d66cf913a9cd8d7519c106d61a11b5c745bfcb36 Mon Sep 17 00:00:00 2001 From: Chad Stearns Date: Fri, 3 Jul 2020 14:20:34 -0400 Subject: [PATCH] Refactored the phi2 away --- compiler/gen/src/llvm/build.rs | 222 ++++++++++++++--------------- compiler/gen/tests/gen_builtins.rs | 2 + 2 files changed, 107 insertions(+), 117 deletions(-) diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index 5e5f1d5cde..7911290d16 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -1604,138 +1604,126 @@ fn call_with_args<'a, 'ctx, 'env>( let list_len = load_list_len(builder, wrapper_struct); - // list_len > 0 - // We have to do a loop below, continuously adding the `elem` - // to the output list `List elem` until we have reached the - // number of repeats. This `comparison` is used to check - // if we need to do any looping; because if we dont, then we - // dont need to allocate memory for the index or the check - // if list_len == 0 - let comparison = builder.build_int_compare( - IntPredicate::NE, - list_len, - ctx.i64_type().const_int(0, false), - "atleastzero", - ); + match list_layout { + Layout::Builtin(Builtin::List(elem_layout)) => { + // Allocate space for the new array that we'll copy into. + let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64; - let build_then = || { - match list_layout { - Layout::Builtin(Builtin::List(elem_layout)) => { - // Allocate space for the new array that we'll copy into. - let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64; + let elem_type = + basic_type_from_layout(env.arena, ctx, elem_layout, env.ptr_bytes); - let elem_type = - basic_type_from_layout(env.arena, ctx, elem_layout, env.ptr_bytes); + let ptr_type = get_ptr_type(&elem_type, AddressSpace::Generic); - let ptr_type = get_ptr_type(&elem_type, AddressSpace::Generic); + let reversed_list_ptr = { + let len_type = env.ptr_int(); + let len = len_type.const_int(elem_bytes, false); - let list_ptr = load_list_ptr(builder, wrapper_struct, ptr_type); + env.builder + .build_array_malloc(elem_type, len, "create_reversed_list_ptr") + .unwrap() - let reversed_list_ptr = { - let len_type = env.ptr_int(); - let len = len_type.const_int(elem_bytes, false); + // TODO check if malloc returned null; if so, runtime error for OOM! + }; - env.builder - .build_array_malloc(elem_type, len, "create_list_ptr") - .unwrap() + let index_name = "#index"; + let start_alloca = builder.build_alloca(ctx.i64_type(), index_name); - // TODO check if malloc returned null; if so, runtime error for OOM! - }; + builder.build_store(start_alloca, list_len); - let index_name = "#index"; - let start_alloca = builder.build_alloca(ctx.i64_type(), index_name); + let loop_bb = ctx.append_basic_block(parent, "loop"); + builder.build_unconditional_branch(loop_bb); + builder.position_at_end(loop_bb); - builder.build_store(start_alloca, list_len); + // #index = #index - 1 + let curr_index = builder + .build_load(start_alloca, index_name) + .into_int_value(); + let next_index = builder.build_int_sub( + curr_index, + ctx.i64_type().const_int(1, false), + "nextindex", + ); - let loop_bb = ctx.append_basic_block(parent, "loop"); - builder.build_unconditional_branch(loop_bb); - builder.position_at_end(loop_bb); + builder.build_store(start_alloca, next_index); - // #index = #index - 1 - let curr_index = builder - .build_load(start_alloca, index_name) - .into_int_value(); - let next_index = builder.build_int_sub( - curr_index, - ctx.i64_type().const_int(1, false), - "nextindex", - ); + let list_ptr = load_list_ptr(builder, wrapper_struct, ptr_type); + let elem_ptr = unsafe { + builder.build_in_bounds_gep(list_ptr, &[curr_index], "load_index") + }; - builder.build_store(start_alloca, next_index); - - let elem_ptr = unsafe { - builder.build_in_bounds_gep(list_ptr, &[curr_index], "load_index") - }; - - // Mutate the new array in-place to change the element. - // builder.build_store(elem_ptr, builder.build_load(elem_ptr, "List.get")); - builder.build_store(elem_ptr, ctx.i64_type().const_int(1, false)); - - // #index != 0 - let end_cond = builder.build_int_compare( - IntPredicate::NE, - ctx.i64_type().const_int(0, false), - curr_index, - "loopcond", - ); - - let after_bb = ctx.append_basic_block(parent, "afterloop"); - - builder.build_conditional_branch(end_cond, loop_bb, after_bb); - builder.position_at_end(after_bb); - - let ptr_bytes = env.ptr_bytes; - let int_type = ptr_int(ctx, ptr_bytes); - let ptr_as_int = - builder.build_ptr_to_int(reversed_list_ptr, int_type, "list_cast_ptr"); - let struct_type = collection(ctx, ptr_bytes); - - let mut struct_val; - - // Store the pointer - struct_val = builder - .build_insert_value( - struct_type.get_undef(), - ptr_as_int, - Builtin::WRAPPER_PTR, - "insert_ptr", - ) - .unwrap(); - - // Store the length - struct_val = builder - .build_insert_value( - struct_val, + let reverse_elem_ptr = unsafe { + builder.build_in_bounds_gep( + reversed_list_ptr, + &[builder.build_int_sub( list_len, - Builtin::WRAPPER_LEN, - "insert_len", - ) - .unwrap(); - - builder.build_bitcast( - struct_val.into_struct_value(), - collection(ctx, ptr_bytes), - "cast_collection", + builder.build_int_add( + curr_index, + ctx.i64_type().const_int(1, false), + "curr_index_plus_one", + ), + "next_index", + )], + "load_index_reversed_list", ) - } - _ => { - unreachable!("Invalid List layout for List.get: {:?}", list_layout); - } + }; + + let elem = builder.build_load(elem_ptr, "get_elem"); + + // Mutate the new array in-place to change the element. + builder.build_store(reverse_elem_ptr, elem); + + // #index != 0 + let end_cond = builder.build_int_compare( + IntPredicate::NE, + ctx.i64_type().const_int(0, false), + curr_index, + "loopcond", + ); + + let after_bb = ctx.append_basic_block(parent, "afterloop"); + + builder.build_conditional_branch(end_cond, loop_bb, after_bb); + builder.position_at_end(after_bb); + + let ptr_bytes = env.ptr_bytes; + let int_type = ptr_int(ctx, ptr_bytes); + let ptr_as_int = + builder.build_ptr_to_int(reversed_list_ptr, int_type, "list_cast_ptr"); + let struct_type = collection(ctx, ptr_bytes); + + let mut struct_val; + + // Store the pointer + struct_val = builder + .build_insert_value( + struct_type.get_undef(), + ptr_as_int, + Builtin::WRAPPER_PTR, + "insert_ptr", + ) + .unwrap(); + + // Store the length + struct_val = builder + .build_insert_value( + struct_val, + list_len, + Builtin::WRAPPER_LEN, + "insert_len", + ) + .unwrap(); + + builder.build_bitcast( + struct_val.into_struct_value(), + collection(ctx, ptr_bytes), + "cast_collection", + ) } - }; - - let build_else = || empty_list(env); - - let struct_type = collection(ctx, env.ptr_bytes); - - build_basic_phi2( - env, - parent, - comparison, - build_then, - build_else, - BasicTypeEnum::StructType(struct_type), - ) + Layout::Builtin(Builtin::EmptyList) => empty_list(env), + _ => { + unreachable!("Invalid List layout for List.get: {:?}", list_layout); + } + } } Symbol::INT_DIV_UNSAFE => { debug_assert!(args.len() == 2); diff --git a/compiler/gen/tests/gen_builtins.rs b/compiler/gen/tests/gen_builtins.rs index 487fbf95ff..42bb2461c5 100644 --- a/compiler/gen/tests/gen_builtins.rs +++ b/compiler/gen/tests/gen_builtins.rs @@ -518,6 +518,8 @@ mod gen_builtins { #[test] fn list_reverse() { assert_evals_to!("List.reverse [1, 2, 3]", &[3, 2, 1], &'static [i64]); + assert_evals_to!("List.reverse [4]", &[4], &'static [i64]); + assert_evals_to!("List.reverse []", &[], &'static [i64]); } #[test]