make uniqueness change codegen

This commit is contained in:
Folkert 2020-08-10 21:13:57 +02:00
parent 9e11526c1d
commit 79ea62b9d4
6 changed files with 52 additions and 37 deletions

View file

@ -362,8 +362,6 @@ pub fn gen(src: &[u8], target: Triple, opt_level: OptLevel) -> Result<(String, S
// Uncomment this to see the module's optimized LLVM instruction output: // Uncomment this to see the module's optimized LLVM instruction output:
// env.module.print_to_stderr(); // env.module.print_to_stderr();
panic!("are we here?");
unsafe { unsafe {
let main: JitFunction< let main: JitFunction<
unsafe extern "C" fn() -> i64, /* TODO have this return Str, and in the generated code make sure to call the appropriate string conversion function on the return val based on its type! */ unsafe extern "C" fn() -> i64, /* TODO have this return Str, and in the generated code make sure to call the appropriate string conversion function on the return val based on its type! */
@ -375,8 +373,6 @@ pub fn gen(src: &[u8], target: Triple, opt_level: OptLevel) -> Result<(String, S
let result = main.call(); let result = main.call();
let output = format!("{}", result); let output = format!("{}", result);
std::mem::forget(result);
Ok((output, expr_type_str)) Ok((output, expr_type_str))
} }
} }

View file

@ -107,6 +107,7 @@ mod cli_run {
let out = run_roc(&[ let out = run_roc(&[
"run", "run",
example_file("quicksort", "Quicksort.roc").to_str().unwrap(), example_file("quicksort", "Quicksort.roc").to_str().unwrap(),
"--optimize",
]); ]);
assert_eq!(&out.stderr, ""); assert_eq!(&out.stderr, "");

View file

@ -224,6 +224,8 @@ pub fn gen(
// Populate Procs further and get the low-level Expr from the canonical Expr // Populate Procs further and get the low-level Expr from the canonical Expr
let main_body = Stmt::new(&mut mono_env, loc_expr.value, &mut procs); let main_body = Stmt::new(&mut mono_env, loc_expr.value, &mut procs);
let main_body =
roc_mono::inc_dec::visit_declaration(mono_env.arena, mono_env.arena.alloc(main_body));
let mut headers = { let mut headers = {
let num_headers = match &procs.pending_specializations { let num_headers = match &procs.pending_specializations {
Some(map) => map.len(), Some(map) => map.len(),

View file

@ -20,7 +20,7 @@ use roc_collections::all::ImMap;
use roc_module::low_level::LowLevel; use roc_module::low_level::LowLevel;
use roc_module::symbol::{Interns, Symbol}; use roc_module::symbol::{Interns, Symbol};
use roc_mono::ir::JoinPointId; use roc_mono::ir::JoinPointId;
use roc_mono::layout::{Builtin, Layout, Ownership}; use roc_mono::layout::{Builtin, Layout, MemoryMode};
use target_lexicon::CallingConvention; use target_lexicon::CallingConvention;
/// This is for Inkwell's FunctionValue::verify - we want to know the verification /// This is for Inkwell's FunctionValue::verify - we want to know the verification
@ -441,7 +441,6 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
debug_assert!(*union_size > 1); debug_assert!(*union_size > 1);
let ptr_size = env.ptr_bytes; let ptr_size = env.ptr_bytes;
let whole_size = tag_layout.stack_size(ptr_size);
let mut filler = tag_layout.stack_size(ptr_size); let mut filler = tag_layout.stack_size(ptr_size);
let ctx = env.context; let ctx = env.context;
@ -800,9 +799,9 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
Inc(symbol, cont) => { Inc(symbol, cont) => {
let (value, layout) = load_symbol_and_layout(env, scope, symbol); let (value, layout) = load_symbol_and_layout(env, scope, symbol);
let layout = layout.clone(); let layout = layout.clone();
// TODO exclude unique lists in the future
match layout { match layout {
Layout::Builtin(Builtin::List(_, _)) => { Layout::Builtin(Builtin::List(MemoryMode::Refcounted, _)) => {
increment_refcount_list(env, value.into_struct_value()); increment_refcount_list(env, value.into_struct_value());
build_exp_stmt(env, layout_ids, scope, parent, cont) build_exp_stmt(env, layout_ids, scope, parent, cont)
} }
@ -813,11 +812,9 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
let (value, layout) = load_symbol_and_layout(env, scope, symbol); let (value, layout) = load_symbol_and_layout(env, scope, symbol);
let layout = layout.clone(); let layout = layout.clone();
/*
if layout.contains_refcounted() { if layout.contains_refcounted() {
decrement_refcount_layout(env, parent, value, &layout); decrement_refcount_layout(env, parent, value, &layout);
} }
*/
build_exp_stmt(env, layout_ids, scope, parent, cont) build_exp_stmt(env, layout_ids, scope, parent, cont)
} }
@ -830,15 +827,13 @@ fn refcount_is_one_comparison<'ctx>(
context: &'ctx Context, context: &'ctx Context,
refcount: IntValue<'ctx>, refcount: IntValue<'ctx>,
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
let refcount_one: IntValue<'ctx> = context let refcount_one: IntValue<'ctx> = context.i64_type().const_int((std::usize::MAX) as _, false);
.i64_type()
.const_int((std::usize::MAX - 1) as _, false);
// Note: Check for refcount < refcount_1 as the "true" condition, // Note: Check for refcount < refcount_1 as the "true" condition,
// to avoid misprediction. (In practice this should usually pass, // to avoid misprediction. (In practice this should usually pass,
// and CPUs generally default to predicting that a forward jump // and CPUs generally default to predicting that a forward jump
// shouldn't be taken; that is, they predict "else" won't be taken.) // shouldn't be taken; that is, they predict "else" won't be taken.)
builder.build_int_compare( builder.build_int_compare(
IntPredicate::ULT, IntPredicate::EQ,
refcount, refcount,
refcount_one, refcount_one,
"refcount_one_check", "refcount_one_check",
@ -867,13 +862,13 @@ fn list_get_refcount_ptr<'a, 'ctx, 'env>(
let refcount_ptr = builder.build_int_sub( let refcount_ptr = builder.build_int_sub(
ptr_as_int, ptr_as_int,
ctx.i64_type().const_int(env.ptr_bytes as u64, false), ctx.i64_type().const_int(env.ptr_bytes as u64, false),
"refcount_ptr", "make_refcount_ptr",
); );
builder.build_int_to_ptr( builder.build_int_to_ptr(
refcount_ptr, refcount_ptr,
int_type.ptr_type(AddressSpace::Generic), int_type.ptr_type(AddressSpace::Generic),
"make ptr", "get_refcount_ptr",
) )
} }
@ -958,13 +953,16 @@ fn decrement_refcount_builtin<'a, 'ctx, 'env>(
use Builtin::*; use Builtin::*;
match builtin { match builtin {
List(_, element_layout) => { List(MemoryMode::Refcounted, element_layout) => {
if element_layout.contains_refcounted() { if element_layout.contains_refcounted() {
// TODO decrement all values // TODO decrement all values
} }
let wrapper_struct = value.into_struct_value(); let wrapper_struct = value.into_struct_value();
decrement_refcount_list(env, parent, wrapper_struct); decrement_refcount_list(env, parent, wrapper_struct);
} }
List(MemoryMode::Unique, _element_layout) => {
// do nothing
}
Set(element_layout) => { Set(element_layout) => {
if element_layout.contains_refcounted() { if element_layout.contains_refcounted() {
// TODO decrement all values // TODO decrement all values
@ -1091,17 +1089,6 @@ fn load_symbol_and_layout<'a, 'ctx, 'env, 'b>(
} }
} }
fn get_symbol_and_layout<'a, 'ctx, 'env, 'b>(
env: &Env<'a, 'ctx, 'env>,
scope: &'b Scope<'a, 'ctx>,
symbol: &Symbol,
) -> (PointerValue<'ctx>, &'b Layout<'a>) {
match scope.get(symbol) {
Some((layout, ptr)) => (*ptr, layout),
None => panic!("There was no entry for {:?} in scope {:?}", symbol, scope),
}
}
/// Cast a struct to another struct of the same (or smaller?) size /// Cast a struct to another struct of the same (or smaller?) size
fn cast_struct_struct<'ctx>( fn cast_struct_struct<'ctx>(
builder: &Builder<'ctx>, builder: &Builder<'ctx>,
@ -1788,7 +1775,7 @@ fn clone_nonempty_list<'a, 'ctx, 'env>(
.const_int(elem_layout.stack_size(env.ptr_bytes) as u64, false); .const_int(elem_layout.stack_size(env.ptr_bytes) as u64, false);
let size = env let size = env
.builder .builder
.build_int_mul(elem_bytes, list_len, "mul_len_by_elem_bytes"); .build_int_mul(elem_bytes, list_len, "clone_mul_len_by_elem_bytes");
// Allocate space for the new array that we'll copy into. // Allocate space for the new array that we'll copy into.
let clone_ptr = allocate_list(env, elem_layout, list_len); let clone_ptr = allocate_list(env, elem_layout, list_len);
@ -1839,6 +1826,7 @@ fn clone_nonempty_list<'a, 'ctx, 'env>(
(answer, clone_ptr) (answer, clone_ptr)
} }
#[derive(Debug)]
enum InPlace { enum InPlace {
InPlace, InPlace,
Clone, Clone,
@ -2043,7 +2031,7 @@ fn list_join<'a, 'ctx, 'env>(
| Layout::Builtin(Builtin::List(_, Layout::Builtin(Builtin::EmptyList))) => empty_list(env), | Layout::Builtin(Builtin::List(_, Layout::Builtin(Builtin::EmptyList))) => empty_list(env),
Layout::Builtin(Builtin::List(_, Layout::Builtin(Builtin::List(_, elem_layout)))) => { Layout::Builtin(Builtin::List(_, Layout::Builtin(Builtin::List(_, elem_layout)))) => {
let inner_list_layout = let inner_list_layout =
Layout::Builtin(Builtin::List(Ownership::Borrowed, elem_layout)); Layout::Builtin(Builtin::List(MemoryMode::Refcounted, elem_layout));
let builder = env.builder; let builder = env.builder;
let ctx = env.context; let ctx = env.context;

View file

@ -749,7 +749,8 @@ mod gen_list {
r#" r#"
quicksort : List (Num a) -> List (Num a) quicksort : List (Num a) -> List (Num a)
quicksort = \list -> quicksort = \list ->
quicksortHelp list 0 (List.len list - 1) n = List.len list
quicksortHelp list 0 (n - 1)
quicksortHelp : List (Num a), Int, Int -> List (Num a) quicksortHelp : List (Num a), Int, Int -> List (Num a)
@ -787,7 +788,7 @@ mod gen_list {
Pair (low - 1) initialList Pair (low - 1) initialList
partitionHelp : Int, Int, List (Num a), Int, Int -> [ Pair Int (List (Num a)) ] partitionHelp : Int, Int, List (Num a), Int, (Num a) -> [ Pair Int (List (Num a)) ]
partitionHelp = \i, j, list, high, pivot -> partitionHelp = \i, j, list, high, pivot ->
if j < high then if j < high then
when List.get list j is when List.get list j is
@ -802,8 +803,6 @@ mod gen_list {
else else
Pair i list Pair i list
quicksort [ 7, 4, 21, 19 ] quicksort [ 7, 4, 21, 19 ]
"# "#
), ),
@ -1016,6 +1015,27 @@ mod gen_list {
); );
} }
#[test]
fn list_pass_to_set() {
assert_evals_to!(
indoc!(
r#"
x : List Int
x = [1,2,3]
id : List Int -> List Int
id = \y -> List.set y 0 0
id x
"#
),
&[0, 2, 3],
&'static [i64],
|x| x,
true
);
}
// fn bad() { // fn bad() {
// assert_evals_to!( // assert_evals_to!(
// indoc!( // indoc!(

View file

@ -104,6 +104,9 @@ pub fn helper_without_uniqueness<'a>(
}; };
let main_body = roc_mono::ir::Stmt::new(&mut mono_env, loc_expr.value, &mut procs); let main_body = roc_mono::ir::Stmt::new(&mut mono_env, loc_expr.value, &mut procs);
let main_body =
roc_mono::inc_dec::visit_declaration(mono_env.arena, mono_env.arena.alloc(main_body));
let mut headers = { let mut headers = {
let num_headers = match &procs.pending_specializations { let num_headers = match &procs.pending_specializations {
Some(map) => map.len(), Some(map) => map.len(),
@ -194,7 +197,7 @@ pub fn helper_without_uniqueness<'a>(
} }
// Uncomment this to see the module's optimized LLVM instruction output: // Uncomment this to see the module's optimized LLVM instruction output:
env.module.print_to_stderr(); // env.module.print_to_stderr();
(main_fn_name, execution_engine.clone()) (main_fn_name, execution_engine.clone())
} }
@ -216,6 +219,7 @@ pub fn helper_with_uniqueness<'a>(
let target = target_lexicon::Triple::host(); let target = target_lexicon::Triple::host();
let ptr_bytes = target.pointer_width().unwrap().bytes() as u32; let ptr_bytes = target.pointer_width().unwrap().bytes() as u32;
let (loc_expr, _output, problems, subs, var, constraint, home, interns) = uniq_expr(src); let (loc_expr, _output, problems, subs, var, constraint, home, interns) = uniq_expr(src);
let errors = problems let errors = problems
.into_iter() .into_iter()
.filter(|problem| { .filter(|problem| {
@ -292,6 +296,8 @@ pub fn helper_with_uniqueness<'a>(
}; };
let main_body = roc_mono::ir::Stmt::new(&mut mono_env, loc_expr.value, &mut procs); let main_body = roc_mono::ir::Stmt::new(&mut mono_env, loc_expr.value, &mut procs);
let main_body =
roc_mono::inc_dec::visit_declaration(mono_env.arena, mono_env.arena.alloc(main_body));
let mut headers = { let mut headers = {
let num_headers = match &procs.pending_specializations { let num_headers = match &procs.pending_specializations {
Some(map) => map.len(), Some(map) => map.len(),
@ -365,6 +371,8 @@ pub fn helper_with_uniqueness<'a>(
builder.build_return(Some(&ret)); builder.build_return(Some(&ret));
// you're in the version with uniqueness!
// Uncomment this to see the module's un-optimized LLVM instruction output: // Uncomment this to see the module's un-optimized LLVM instruction output:
// env.module.print_to_stderr(); // env.module.print_to_stderr();