mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
Merge remote-tracking branch 'origin/trunk' into unit-types
This commit is contained in:
commit
14979ceb41
4 changed files with 196 additions and 132 deletions
|
@ -422,18 +422,19 @@ pub fn build_expr<'a, B: Backend>(
|
||||||
elems_ptr
|
elems_ptr
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store the pointer in slot 0
|
// Store the pointer
|
||||||
builder
|
{
|
||||||
.ins()
|
let offset = Offset32::new((Builtin::WRAPPER_PTR * ptr_bytes) as i32);
|
||||||
.stack_store(elems_ptr, slot, Offset32::new(0));
|
|
||||||
|
|
||||||
// Store the length in slot 1
|
builder.ins().stack_store(elems_ptr, slot, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the length
|
||||||
{
|
{
|
||||||
let length = builder.ins().iconst(env.ptr_sized_int(), elems.len() as i64);
|
let length = builder.ins().iconst(env.ptr_sized_int(), elems.len() as i64);
|
||||||
|
let offset = Offset32::new((Builtin::WRAPPER_LEN * ptr_bytes) as i32);
|
||||||
|
|
||||||
builder
|
builder.ins().stack_store(length, slot, offset);
|
||||||
.ins()
|
|
||||||
.stack_store(length, slot, Offset32::new(ptr_bytes as i32));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the pointer to the wrapper
|
// Return the pointer to the wrapper
|
||||||
|
@ -797,14 +798,13 @@ fn call_by_name<'a, B: Backend>(
|
||||||
debug_assert!(args.len() == 1);
|
debug_assert!(args.len() == 1);
|
||||||
|
|
||||||
let list_ptr = build_arg(&args[0], env, scope, module, builder, procs);
|
let list_ptr = build_arg(&args[0], env, scope, module, builder, procs);
|
||||||
|
let ptr_bytes = env.cfg.pointer_bytes() as u32;
|
||||||
|
let offset = Offset32::new((Builtin::WRAPPER_LEN * ptr_bytes) as i32);
|
||||||
|
|
||||||
// Get the usize list length
|
// Get the usize list length
|
||||||
builder.ins().load(
|
builder
|
||||||
env.ptr_sized_int(),
|
.ins()
|
||||||
MemFlags::new(),
|
.load(env.ptr_sized_int(), MemFlags::new(), list_ptr, offset)
|
||||||
list_ptr,
|
|
||||||
Offset32::new(env.cfg.pointer_bytes() as i32),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Symbol::INT_EQ_I64 | Symbol::INT_EQ_I8 | Symbol::INT_EQ_I1 => {
|
Symbol::INT_EQ_I64 | Symbol::INT_EQ_I8 | Symbol::INT_EQ_I1 => {
|
||||||
debug_assert!(args.len() == 2);
|
debug_assert!(args.len() == 2);
|
||||||
|
@ -853,12 +853,12 @@ fn call_by_name<'a, B: Backend>(
|
||||||
let (_list_expr, list_layout) = &args[0];
|
let (_list_expr, list_layout) = &args[0];
|
||||||
|
|
||||||
// Get the usize list length
|
// Get the usize list length
|
||||||
let _list_len = builder.ins().load(
|
let ptr_bytes = env.cfg.pointer_bytes() as u32;
|
||||||
env.ptr_sized_int(),
|
let offset = Offset32::new((Builtin::WRAPPER_LEN * ptr_bytes) as i32);
|
||||||
MemFlags::new(),
|
let _list_len =
|
||||||
wrapper_ptr,
|
builder
|
||||||
Offset32::new(env.cfg.pointer_bytes() as i32),
|
.ins()
|
||||||
);
|
.load(env.ptr_sized_int(), MemFlags::new(), wrapper_ptr, offset);
|
||||||
|
|
||||||
// TODO compare elem_index to _list_len to do array bounds checking.
|
// TODO compare elem_index to _list_len to do array bounds checking.
|
||||||
|
|
||||||
|
@ -898,6 +898,16 @@ fn call_by_name<'a, B: Backend>(
|
||||||
let wrapper_ptr = build_arg(&args[0], env, scope, module, builder, procs);
|
let wrapper_ptr = build_arg(&args[0], env, scope, module, builder, procs);
|
||||||
let (_list_expr, list_layout) = &args[0];
|
let (_list_expr, list_layout) = &args[0];
|
||||||
|
|
||||||
|
// Get the usize list length
|
||||||
|
let ptr_bytes = env.cfg.pointer_bytes() as u32;
|
||||||
|
let offset = Offset32::new((Builtin::WRAPPER_LEN * ptr_bytes) as i32);
|
||||||
|
let _list_len =
|
||||||
|
builder
|
||||||
|
.ins()
|
||||||
|
.load(env.ptr_sized_int(), MemFlags::new(), wrapper_ptr, offset);
|
||||||
|
|
||||||
|
// TODO do array bounds checking, and early return the original List if out of bounds
|
||||||
|
|
||||||
match list_layout {
|
match list_layout {
|
||||||
Layout::Builtin(Builtin::List(elem_layout)) => {
|
Layout::Builtin(Builtin::List(elem_layout)) => {
|
||||||
let wrapper_ptr = clone_list(env, builder, module, wrapper_ptr, elem_layout);
|
let wrapper_ptr = clone_list(env, builder, module, wrapper_ptr, elem_layout);
|
||||||
|
@ -918,6 +928,17 @@ fn call_by_name<'a, B: Backend>(
|
||||||
// set : List elem, Int, elem -> List elem
|
// set : List elem, Int, elem -> List elem
|
||||||
debug_assert!(args.len() == 3);
|
debug_assert!(args.len() == 3);
|
||||||
|
|
||||||
|
// Get the usize list length
|
||||||
|
let wrapper_ptr = build_arg(&args[0], env, scope, module, builder, procs);
|
||||||
|
let ptr_bytes = env.cfg.pointer_bytes() as u32;
|
||||||
|
let offset = Offset32::new((Builtin::WRAPPER_LEN * ptr_bytes) as i32);
|
||||||
|
let _list_len =
|
||||||
|
builder
|
||||||
|
.ins()
|
||||||
|
.load(env.ptr_sized_int(), MemFlags::new(), wrapper_ptr, offset);
|
||||||
|
|
||||||
|
// TODO do array bounds checking, and early return the original List if out of bounds
|
||||||
|
|
||||||
let (list_expr, list_layout) = &args[0];
|
let (list_expr, list_layout) = &args[0];
|
||||||
let list_val = build_expr(env, scope, module, builder, list_expr, procs);
|
let list_val = build_expr(env, scope, module, builder, list_expr, procs);
|
||||||
|
|
||||||
|
@ -1014,22 +1035,28 @@ fn clone_list<B: Backend>(
|
||||||
elem_layout: &Layout<'_>,
|
elem_layout: &Layout<'_>,
|
||||||
) -> Value {
|
) -> Value {
|
||||||
let cfg = env.cfg;
|
let cfg = env.cfg;
|
||||||
|
let ptr_bytes = env.cfg.pointer_bytes() as u32;
|
||||||
|
|
||||||
// Load the pointer we got to the wrapper struct
|
// Load the pointer we got to the wrapper struct
|
||||||
let elems_ptr = builder.ins().load(
|
let elems_ptr = {
|
||||||
cfg.pointer_type(),
|
let offset = Offset32::new((Builtin::WRAPPER_PTR * ptr_bytes) as i32);
|
||||||
MemFlags::new(),
|
|
||||||
src_wrapper_ptr,
|
builder
|
||||||
Offset32::new(0),
|
.ins()
|
||||||
);
|
.load(cfg.pointer_type(), MemFlags::new(), src_wrapper_ptr, offset)
|
||||||
|
};
|
||||||
|
|
||||||
// Get the usize list length
|
// Get the usize list length
|
||||||
let list_len = builder.ins().load(
|
let list_len = {
|
||||||
env.ptr_sized_int(),
|
let offset = Offset32::new((Builtin::WRAPPER_LEN * ptr_bytes) as i32);
|
||||||
MemFlags::new(),
|
|
||||||
src_wrapper_ptr,
|
builder.ins().load(
|
||||||
Offset32::new(env.cfg.pointer_bytes() as i32),
|
env.ptr_sized_int(),
|
||||||
);
|
MemFlags::new(),
|
||||||
|
src_wrapper_ptr,
|
||||||
|
offset,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
// Calculate the number of bytes we'll need to allocate.
|
// Calculate the number of bytes we'll need to allocate.
|
||||||
let elem_bytes = builder.ins().iconst(
|
let elem_bytes = builder.ins().iconst(
|
||||||
|
|
|
@ -3,13 +3,13 @@ use bumpalo::Bump;
|
||||||
use inkwell::builder::Builder;
|
use inkwell::builder::Builder;
|
||||||
use inkwell::context::Context;
|
use inkwell::context::Context;
|
||||||
use inkwell::module::{Linkage, Module};
|
use inkwell::module::{Linkage, Module};
|
||||||
use inkwell::types::{BasicTypeEnum, StructType};
|
use inkwell::types::{BasicTypeEnum, IntType, StructType};
|
||||||
use inkwell::values::BasicValueEnum::{self, *};
|
use inkwell::values::BasicValueEnum::{self, *};
|
||||||
use inkwell::values::{FunctionValue, IntValue, PointerValue, StructValue};
|
use inkwell::values::{FunctionValue, IntValue, PointerValue, StructValue};
|
||||||
use inkwell::{AddressSpace, FloatPredicate, IntPredicate};
|
use inkwell::{AddressSpace, FloatPredicate, IntPredicate};
|
||||||
|
|
||||||
use crate::llvm::convert::{
|
use crate::llvm::convert::{
|
||||||
basic_type_from_layout, collection_wrapper, get_array_type, get_fn_type,
|
basic_type_from_layout, collection_wrapper, get_array_type, get_fn_type, ptr_int,
|
||||||
};
|
};
|
||||||
use roc_collections::all::ImMap;
|
use roc_collections::all::ImMap;
|
||||||
use roc_module::symbol::{Interns, Symbol};
|
use roc_module::symbol::{Interns, Symbol};
|
||||||
|
@ -32,7 +32,13 @@ pub struct Env<'a, 'ctx, 'env> {
|
||||||
pub builder: &'env Builder<'ctx>,
|
pub builder: &'env Builder<'ctx>,
|
||||||
pub module: &'ctx Module<'ctx>,
|
pub module: &'ctx Module<'ctx>,
|
||||||
pub interns: Interns,
|
pub interns: Interns,
|
||||||
pub pointer_bytes: u32,
|
pub ptr_bytes: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
||||||
|
pub fn ptr_int(&self) -> IntType<'ctx> {
|
||||||
|
ptr_int(self.context, self.ptr_bytes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
|
@ -76,7 +82,8 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
ret_layout,
|
ret_layout,
|
||||||
cond_layout,
|
cond_layout,
|
||||||
} => {
|
} => {
|
||||||
let ret_type = basic_type_from_layout(env.arena, env.context, &ret_layout);
|
let ret_type =
|
||||||
|
basic_type_from_layout(env.arena, env.context, &ret_layout, env.ptr_bytes);
|
||||||
let switch_args = SwitchArgs {
|
let switch_args = SwitchArgs {
|
||||||
cond_layout: cond_layout.clone(),
|
cond_layout: cond_layout.clone(),
|
||||||
cond_expr: cond,
|
cond_expr: cond,
|
||||||
|
@ -93,7 +100,7 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
for (symbol, layout, expr) in stores.iter() {
|
for (symbol, layout, expr) in stores.iter() {
|
||||||
let val = build_expr(env, &scope, parent, &expr, procs);
|
let val = build_expr(env, &scope, parent, &expr, procs);
|
||||||
let expr_bt = basic_type_from_layout(env.arena, context, &layout);
|
let expr_bt = basic_type_from_layout(env.arena, context, &layout, env.ptr_bytes);
|
||||||
let alloca = create_entry_block_alloca(
|
let alloca = create_entry_block_alloca(
|
||||||
env,
|
env,
|
||||||
parent,
|
parent,
|
||||||
|
@ -146,14 +153,14 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
build_basic_phi2(env, parent, comparison, then_val, else_val, ret_type)
|
build_basic_phi2(env, parent, comparison, then_val, else_val, ret_type)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut arg_vals: Vec<BasicValueEnum> =
|
let mut arg_tuples: Vec<(BasicValueEnum, &'a Layout<'a>)> =
|
||||||
Vec::with_capacity_in(args.len(), env.arena);
|
Vec::with_capacity_in(args.len(), env.arena);
|
||||||
|
|
||||||
for (arg, _layout) in args.iter() {
|
for (arg, layout) in args.iter() {
|
||||||
arg_vals.push(build_expr(env, scope, parent, arg, procs));
|
arg_tuples.push((build_expr(env, scope, parent, arg, procs), layout));
|
||||||
}
|
}
|
||||||
|
|
||||||
call_with_args(*symbol, arg_vals.into_bump_slice(), env)
|
call_with_args(*symbol, arg_tuples.into_bump_slice(), env)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FunctionPointer(symbol) => {
|
FunctionPointer(symbol) => {
|
||||||
|
@ -189,7 +196,6 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
.left()
|
.left()
|
||||||
.unwrap_or_else(|| panic!("LLVM error: Invalid call by pointer."))
|
.unwrap_or_else(|| panic!("LLVM error: Invalid call by pointer."))
|
||||||
}
|
}
|
||||||
|
|
||||||
Load(symbol) => match scope.get(symbol) {
|
Load(symbol) => match scope.get(symbol) {
|
||||||
Some((_, ptr)) => env
|
Some((_, ptr)) => env
|
||||||
.builder
|
.builder
|
||||||
|
@ -233,13 +239,13 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
Array { elem_layout, elems } => {
|
Array { elem_layout, elems } => {
|
||||||
let ctx = env.context;
|
let ctx = env.context;
|
||||||
let elem_type = basic_type_from_layout(env.arena, ctx, elem_layout);
|
let elem_type = basic_type_from_layout(env.arena, ctx, elem_layout, env.ptr_bytes);
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
|
|
||||||
if elems.is_empty() {
|
if elems.is_empty() {
|
||||||
let array_type = get_array_type(&elem_type, 0);
|
let array_type = get_array_type(&elem_type, 0);
|
||||||
let ptr_type = array_type.ptr_type(AddressSpace::Generic);
|
let ptr_type = array_type.ptr_type(AddressSpace::Generic);
|
||||||
let struct_type = collection_wrapper(ctx, ptr_type);
|
let struct_type = collection_wrapper(ctx, ptr_type, env.ptr_bytes);
|
||||||
|
|
||||||
// The first field in the struct should be the pointer.
|
// The first field in the struct should be the pointer.
|
||||||
let struct_val = builder
|
let struct_val = builder
|
||||||
|
@ -254,11 +260,12 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
BasicValueEnum::StructValue(struct_val.into_struct_value())
|
BasicValueEnum::StructValue(struct_val.into_struct_value())
|
||||||
} else {
|
} else {
|
||||||
let len_u64 = elems.len() as u64;
|
let len_u64 = elems.len() as u64;
|
||||||
let elem_bytes = elem_layout.stack_size(env.pointer_bytes) as u64;
|
let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64;
|
||||||
|
|
||||||
let ptr = {
|
let ptr = {
|
||||||
let bytes_len = elem_bytes * len_u64;
|
let bytes_len = elem_bytes * len_u64;
|
||||||
let len = ctx.i32_type().const_int(bytes_len, false);
|
let len_type = env.ptr_int();
|
||||||
|
let len = len_type.const_int(bytes_len, false);
|
||||||
|
|
||||||
env.builder
|
env.builder
|
||||||
.build_array_malloc(elem_type, len, "create_list_ptr")
|
.build_array_malloc(elem_type, len, "create_list_ptr")
|
||||||
|
@ -276,8 +283,8 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let ptr_val = BasicValueEnum::PointerValue(ptr);
|
let ptr_val = BasicValueEnum::PointerValue(ptr);
|
||||||
let struct_type = collection_wrapper(ctx, ptr.get_type());
|
let struct_type = collection_wrapper(ctx, ptr.get_type(), env.ptr_bytes);
|
||||||
let len = BasicValueEnum::IntValue(ctx.i32_type().const_int(len_u64, false));
|
let len = BasicValueEnum::IntValue(env.ptr_int().const_int(len_u64, false));
|
||||||
let mut struct_val;
|
let mut struct_val;
|
||||||
|
|
||||||
// Field 0: pointer
|
// Field 0: pointer
|
||||||
|
@ -295,16 +302,6 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
.build_insert_value(struct_val, len, Builtin::WRAPPER_LEN, "insert_len")
|
.build_insert_value(struct_val, len, Builtin::WRAPPER_LEN, "insert_len")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Field 2: capacity (initially set to length)
|
|
||||||
struct_val = builder
|
|
||||||
.build_insert_value(
|
|
||||||
struct_val,
|
|
||||||
len,
|
|
||||||
Builtin::WRAPPER_CAPACITY,
|
|
||||||
"insert_capacity",
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
BasicValueEnum::StructValue(struct_val.into_struct_value())
|
BasicValueEnum::StructValue(struct_val.into_struct_value())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,7 +317,8 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
for (field_expr, field_layout) in sorted_fields.iter() {
|
for (field_expr, field_layout) in sorted_fields.iter() {
|
||||||
let val = build_expr(env, &scope, parent, field_expr, procs);
|
let val = build_expr(env, &scope, parent, field_expr, procs);
|
||||||
let field_type = basic_type_from_layout(env.arena, env.context, &field_layout);
|
let field_type =
|
||||||
|
basic_type_from_layout(env.arena, env.context, &field_layout, env.ptr_bytes);
|
||||||
|
|
||||||
field_types.push(field_type);
|
field_types.push(field_type);
|
||||||
field_vals.push(val);
|
field_vals.push(val);
|
||||||
|
@ -356,7 +354,8 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
for (field_expr, field_layout) in it {
|
for (field_expr, field_layout) in it {
|
||||||
let val = build_expr(env, &scope, parent, field_expr, procs);
|
let val = build_expr(env, &scope, parent, field_expr, procs);
|
||||||
let field_type = basic_type_from_layout(env.arena, env.context, &field_layout);
|
let field_type =
|
||||||
|
basic_type_from_layout(env.arena, env.context, &field_layout, env.ptr_bytes);
|
||||||
|
|
||||||
field_types.push(field_type);
|
field_types.push(field_type);
|
||||||
field_vals.push(val);
|
field_vals.push(val);
|
||||||
|
@ -382,7 +381,7 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
tag_id,
|
tag_id,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let ptr_size = env.pointer_bytes;
|
let ptr_size = env.ptr_bytes;
|
||||||
|
|
||||||
let whole_size = tag_layout.stack_size(ptr_size);
|
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);
|
||||||
|
@ -414,7 +413,8 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
for (field_expr, field_layout) in arguments.iter() {
|
for (field_expr, field_layout) in arguments.iter() {
|
||||||
let val = build_expr(env, &scope, parent, field_expr, procs);
|
let val = build_expr(env, &scope, parent, field_expr, procs);
|
||||||
let field_type = basic_type_from_layout(env.arena, env.context, &field_layout);
|
let field_type =
|
||||||
|
basic_type_from_layout(env.arena, env.context, &field_layout, ptr_size);
|
||||||
|
|
||||||
field_types.push(field_type);
|
field_types.push(field_type);
|
||||||
field_vals.push(val);
|
field_vals.push(val);
|
||||||
|
@ -559,9 +559,11 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
// Determine types, assumes the descriminant is in the field layouts
|
// Determine types, assumes the descriminant is in the field layouts
|
||||||
let num_fields = field_layouts.len();
|
let num_fields = field_layouts.len();
|
||||||
let mut field_types = Vec::with_capacity_in(num_fields, env.arena);
|
let mut field_types = Vec::with_capacity_in(num_fields, env.arena);
|
||||||
|
let ptr_bytes = env.ptr_bytes;
|
||||||
|
|
||||||
for field_layout in field_layouts.iter() {
|
for field_layout in field_layouts.iter() {
|
||||||
let field_type = basic_type_from_layout(env.arena, env.context, &field_layout);
|
let field_type =
|
||||||
|
basic_type_from_layout(env.arena, env.context, &field_layout, ptr_bytes);
|
||||||
field_types.push(field_type);
|
field_types.push(field_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,7 +650,7 @@ fn build_branch2<'a, 'ctx, 'env>(
|
||||||
procs: &Procs<'a>,
|
procs: &Procs<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
let ret_layout = cond.ret_layout;
|
let ret_layout = cond.ret_layout;
|
||||||
let ret_type = basic_type_from_layout(env.arena, env.context, &ret_layout);
|
let ret_type = basic_type_from_layout(env.arena, env.context, &ret_layout, env.ptr_bytes);
|
||||||
|
|
||||||
let cond_expr = build_expr(env, scope, parent, cond.cond, procs);
|
let cond_expr = build_expr(env, scope, parent, cond.cond, procs);
|
||||||
|
|
||||||
|
@ -877,12 +879,12 @@ pub fn build_proc_header<'a, 'ctx, 'env>(
|
||||||
let args = proc.args;
|
let args = proc.args;
|
||||||
let arena = env.arena;
|
let arena = env.arena;
|
||||||
let context = &env.context;
|
let context = &env.context;
|
||||||
let ret_type = basic_type_from_layout(arena, context, &proc.ret_layout);
|
let ret_type = basic_type_from_layout(arena, context, &proc.ret_layout, env.ptr_bytes);
|
||||||
let mut arg_basic_types = Vec::with_capacity_in(args.len(), arena);
|
let mut arg_basic_types = Vec::with_capacity_in(args.len(), arena);
|
||||||
let mut arg_symbols = Vec::new_in(arena);
|
let mut arg_symbols = Vec::new_in(arena);
|
||||||
|
|
||||||
for (layout, arg_symbol) in args.iter() {
|
for (layout, arg_symbol) in args.iter() {
|
||||||
let arg_type = basic_type_from_layout(arena, env.context, &layout);
|
let arg_type = basic_type_from_layout(arena, env.context, &layout, env.ptr_bytes);
|
||||||
|
|
||||||
arg_basic_types.push(arg_type);
|
arg_basic_types.push(arg_type);
|
||||||
arg_symbols.push(arg_symbol);
|
arg_symbols.push(arg_symbol);
|
||||||
|
@ -950,7 +952,7 @@ pub fn verify_fn(fn_val: FunctionValue<'_>) {
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
fn call_with_args<'a, 'ctx, 'env>(
|
fn call_with_args<'a, 'ctx, 'env>(
|
||||||
symbol: Symbol,
|
symbol: Symbol,
|
||||||
args: &[BasicValueEnum<'ctx>],
|
args: &[(BasicValueEnum<'ctx>, &'a Layout<'a>)],
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
match symbol {
|
match symbol {
|
||||||
|
@ -958,8 +960,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
debug_assert!(args.len() == 2);
|
debug_assert!(args.len() == 2);
|
||||||
|
|
||||||
let int_val = env.builder.build_int_add(
|
let int_val = env.builder.build_int_add(
|
||||||
args[0].into_int_value(),
|
args[0].0.into_int_value(),
|
||||||
args[1].into_int_value(),
|
args[1].0.into_int_value(),
|
||||||
"add_i64",
|
"add_i64",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -969,8 +971,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
debug_assert!(args.len() == 2);
|
debug_assert!(args.len() == 2);
|
||||||
|
|
||||||
let float_val = env.builder.build_float_add(
|
let float_val = env.builder.build_float_add(
|
||||||
args[0].into_float_value(),
|
args[0].0.into_float_value(),
|
||||||
args[1].into_float_value(),
|
args[1].0.into_float_value(),
|
||||||
"add_f64",
|
"add_f64",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -980,8 +982,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
debug_assert!(args.len() == 2);
|
debug_assert!(args.len() == 2);
|
||||||
|
|
||||||
let int_val = env.builder.build_int_sub(
|
let int_val = env.builder.build_int_sub(
|
||||||
args[0].into_int_value(),
|
args[0].0.into_int_value(),
|
||||||
args[1].into_int_value(),
|
args[1].0.into_int_value(),
|
||||||
"sub_I64",
|
"sub_I64",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -991,8 +993,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
debug_assert!(args.len() == 2);
|
debug_assert!(args.len() == 2);
|
||||||
|
|
||||||
let float_val = env.builder.build_float_sub(
|
let float_val = env.builder.build_float_sub(
|
||||||
args[0].into_float_value(),
|
args[0].0.into_float_value(),
|
||||||
args[1].into_float_value(),
|
args[1].0.into_float_value(),
|
||||||
"sub_f64",
|
"sub_f64",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1002,8 +1004,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
debug_assert!(args.len() == 2);
|
debug_assert!(args.len() == 2);
|
||||||
|
|
||||||
let int_val = env.builder.build_int_mul(
|
let int_val = env.builder.build_int_mul(
|
||||||
args[0].into_int_value(),
|
args[0].0.into_int_value(),
|
||||||
args[1].into_int_value(),
|
args[1].0.into_int_value(),
|
||||||
"mul_i64",
|
"mul_i64",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1014,29 +1016,26 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let int_val = env
|
let int_val = env
|
||||||
.builder
|
.builder
|
||||||
.build_int_neg(args[0].into_int_value(), "negate_i64");
|
.build_int_neg(args[0].0.into_int_value(), "negate_i64");
|
||||||
|
|
||||||
BasicValueEnum::IntValue(int_val)
|
BasicValueEnum::IntValue(int_val)
|
||||||
}
|
}
|
||||||
Symbol::LIST_LEN => {
|
Symbol::LIST_LEN => {
|
||||||
debug_assert!(args.len() == 1);
|
debug_assert!(args.len() == 1);
|
||||||
|
|
||||||
let wrapper_struct = args[0].into_struct_value();
|
let wrapper_struct = args[0].0.into_struct_value();
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
|
|
||||||
// Get the 32-bit int length
|
// Get the usize int length
|
||||||
let i32_val = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_LEN, "unwrapped_list_len").unwrap().into_int_value();
|
builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_LEN, "unwrapped_list_len").unwrap().into_int_value().into()
|
||||||
|
|
||||||
// cast the 32-bit length to a 64-bit int
|
|
||||||
BasicValueEnum::IntValue(builder.build_int_cast(i32_val, env.context.i64_type(), "i32_to_i64"))
|
|
||||||
}
|
}
|
||||||
Symbol::LIST_IS_EMPTY => {
|
Symbol::LIST_IS_EMPTY => {
|
||||||
debug_assert!(args.len() == 1);
|
debug_assert!(args.len() == 1);
|
||||||
|
|
||||||
let list_struct = args[0].into_struct_value();
|
let list_struct = args[0].0.into_struct_value();
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
let list_len = builder.build_extract_value(list_struct, 1, "unwrapped_list_len").unwrap().into_int_value();
|
let list_len = builder.build_extract_value(list_struct, 1, "unwrapped_list_len").unwrap().into_int_value();
|
||||||
let zero = env.context.i32_type().const_zero();
|
let zero = env.ptr_int().const_zero();
|
||||||
let answer = builder.build_int_compare(IntPredicate::EQ, list_len, zero, "is_zero");
|
let answer = builder.build_int_compare(IntPredicate::EQ, list_len, zero, "is_zero");
|
||||||
|
|
||||||
BasicValueEnum::IntValue(answer)
|
BasicValueEnum::IntValue(answer)
|
||||||
|
@ -1046,8 +1045,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let int_val = env.builder.build_int_compare(
|
let int_val = env.builder.build_int_compare(
|
||||||
IntPredicate::EQ,
|
IntPredicate::EQ,
|
||||||
args[0].into_int_value(),
|
args[0].0.into_int_value(),
|
||||||
args[1].into_int_value(),
|
args[1].0.into_int_value(),
|
||||||
"cmp_i64",
|
"cmp_i64",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1058,8 +1057,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let int_val = env.builder.build_int_compare(
|
let int_val = env.builder.build_int_compare(
|
||||||
IntPredicate::EQ,
|
IntPredicate::EQ,
|
||||||
args[0].into_int_value(),
|
args[0].0.into_int_value(),
|
||||||
args[1].into_int_value(),
|
args[1].0.into_int_value(),
|
||||||
"cmp_i1",
|
"cmp_i1",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1070,8 +1069,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let int_val = env.builder.build_int_compare(
|
let int_val = env.builder.build_int_compare(
|
||||||
IntPredicate::EQ,
|
IntPredicate::EQ,
|
||||||
args[0].into_int_value(),
|
args[0].0.into_int_value(),
|
||||||
args[1].into_int_value(),
|
args[1].0.into_int_value(),
|
||||||
"cmp_i8",
|
"cmp_i8",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1082,8 +1081,8 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let int_val = env.builder.build_float_compare(
|
let int_val = env.builder.build_float_compare(
|
||||||
FloatPredicate::OEQ,
|
FloatPredicate::OEQ,
|
||||||
args[0].into_float_value(),
|
args[0].0.into_float_value(),
|
||||||
args[1].into_float_value(),
|
args[1].0.into_float_value(),
|
||||||
"cmp_f64",
|
"cmp_f64",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1095,36 +1094,45 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
// List.get : List elem, Int -> Result elem [ OutOfBounds ]*
|
// List.get : List elem, Int -> Result elem [ OutOfBounds ]*
|
||||||
debug_assert!(args.len() == 2);
|
debug_assert!(args.len() == 2);
|
||||||
|
|
||||||
let wrapper_struct = args[0].into_struct_value();
|
let (_list_expr, list_layout) = &args[0];
|
||||||
let elem_index = args[1].into_int_value();
|
|
||||||
|
|
||||||
// Slot 1 in the wrapper struct is the length
|
let wrapper_struct = args[0].0.into_struct_value();
|
||||||
|
let elem_index = args[1].0.into_int_value();
|
||||||
|
|
||||||
|
// Get the length from the wrapper struct
|
||||||
let _list_len = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_LEN, "unwrapped_list_len").unwrap().into_int_value();
|
let _list_len = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_LEN, "unwrapped_list_len").unwrap().into_int_value();
|
||||||
|
|
||||||
// TODO here, check to see if the requested index exceeds the length of the array.
|
// TODO here, check to see if the requested index exceeds the length of the array.
|
||||||
|
|
||||||
// Slot 0 in the wrapper struct is the pointer to the array data
|
match list_layout {
|
||||||
let array_data_ptr = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_PTR, "unwrapped_list_ptr").unwrap().into_pointer_value();
|
Layout::Builtin(Builtin::List(elem_layout)) => {
|
||||||
|
// Get the pointer to the array data
|
||||||
|
let array_data_ptr = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_PTR, "unwrapped_list_ptr").unwrap().into_pointer_value();
|
||||||
|
|
||||||
let elem_bytes = 8; // TODO Look this size up instead of hardcoding it!
|
let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64;
|
||||||
let elem_size = env.context.i64_type().const_int(elem_bytes, false);
|
let elem_size = env.context.i64_type().const_int(elem_bytes, false);
|
||||||
|
|
||||||
// Calculate the offset at runtime by multiplying the index by the size of an element.
|
// Calculate the offset at runtime by multiplying the index by the size of an element.
|
||||||
let offset_bytes = builder.build_int_mul(elem_index, elem_size, "mul_offset");
|
let offset_bytes = builder.build_int_mul(elem_index, elem_size, "mul_offset");
|
||||||
|
|
||||||
// We already checked the bounds earlier.
|
// We already checked the bounds earlier.
|
||||||
let elem_ptr = unsafe { builder.build_in_bounds_gep(array_data_ptr, &[offset_bytes], "elem") };
|
let elem_ptr = unsafe { builder.build_in_bounds_gep(array_data_ptr, &[offset_bytes], "elem") };
|
||||||
|
|
||||||
builder.build_load(elem_ptr, "List.get")
|
builder.build_load(elem_ptr, "List.get")
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!("Invalid List layout for List.get: {:?}", list_layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Symbol::LIST_SET /* TODO clone first for LIST_SET! */ | Symbol::LIST_SET_IN_PLACE => {
|
Symbol::LIST_SET /* TODO clone first for LIST_SET! */ | Symbol::LIST_SET_IN_PLACE => {
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
|
|
||||||
debug_assert!(args.len() == 3);
|
debug_assert!(args.len() == 3);
|
||||||
|
|
||||||
let wrapper_struct = args[0].into_struct_value();
|
let wrapper_struct = args[0].0.into_struct_value();
|
||||||
let elem_index = args[1].into_int_value();
|
let elem_index = args[1].0.into_int_value();
|
||||||
let elem = args[2];
|
let (elem, elem_layout) = args[2];
|
||||||
|
|
||||||
// Slot 1 in the wrapper struct is the length
|
// Slot 1 in the wrapper struct is the length
|
||||||
let _list_len = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_LEN, "unwrapped_list_len").unwrap().into_int_value();
|
let _list_len = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_LEN, "unwrapped_list_len").unwrap().into_int_value();
|
||||||
|
@ -1135,7 +1143,7 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
// Slot 0 in the wrapper struct is the pointer to the array data
|
// Slot 0 in the wrapper struct is the pointer to the array data
|
||||||
let array_data_ptr = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_PTR, "unwrapped_list_ptr").unwrap().into_pointer_value();
|
let array_data_ptr = builder.build_extract_value(wrapper_struct, Builtin::WRAPPER_PTR, "unwrapped_list_ptr").unwrap().into_pointer_value();
|
||||||
|
|
||||||
let elem_bytes = 8; // TODO Look this size up instead of hardcoding it!
|
let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64;
|
||||||
let elem_size = env.context.i64_type().const_int(elem_bytes, false);
|
let elem_size = env.context.i64_type().const_int(elem_bytes, false);
|
||||||
|
|
||||||
// Calculate the offset at runtime by multiplying the index by the size of an element.
|
// Calculate the offset at runtime by multiplying the index by the size of an element.
|
||||||
|
@ -1156,7 +1164,13 @@ fn call_with_args<'a, 'ctx, 'env>(
|
||||||
.get_function(symbol.ident_string(&env.interns))
|
.get_function(symbol.ident_string(&env.interns))
|
||||||
.unwrap_or_else(|| panic!("Unrecognized function: {:?}", symbol));
|
.unwrap_or_else(|| panic!("Unrecognized function: {:?}", symbol));
|
||||||
|
|
||||||
let call = env.builder.build_call(fn_val, args, "tmp");
|
let mut arg_vals: Vec<BasicValueEnum> = Vec::with_capacity_in(args.len(), env.arena);
|
||||||
|
|
||||||
|
for (arg, _layout) in args.iter() {
|
||||||
|
arg_vals.push(*arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
let call = env.builder.build_call(fn_val, arg_vals.into_bump_slice(), "call");
|
||||||
|
|
||||||
call.try_as_basic_value()
|
call.try_as_basic_value()
|
||||||
.left()
|
.left()
|
||||||
|
|
|
@ -2,7 +2,7 @@ use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use inkwell::context::Context;
|
use inkwell::context::Context;
|
||||||
use inkwell::types::BasicTypeEnum::{self, *};
|
use inkwell::types::BasicTypeEnum::{self, *};
|
||||||
use inkwell::types::{ArrayType, BasicType, FunctionType, PointerType, StructType};
|
use inkwell::types::{ArrayType, BasicType, FunctionType, IntType, PointerType, StructType};
|
||||||
use inkwell::AddressSpace;
|
use inkwell::AddressSpace;
|
||||||
|
|
||||||
use roc_mono::layout::Layout;
|
use roc_mono::layout::Layout;
|
||||||
|
@ -38,17 +38,20 @@ pub fn basic_type_from_layout<'ctx>(
|
||||||
arena: &Bump,
|
arena: &Bump,
|
||||||
context: &'ctx Context,
|
context: &'ctx Context,
|
||||||
layout: &Layout<'_>,
|
layout: &Layout<'_>,
|
||||||
|
ptr_bytes: u32,
|
||||||
) -> BasicTypeEnum<'ctx> {
|
) -> BasicTypeEnum<'ctx> {
|
||||||
use roc_mono::layout::Builtin::*;
|
use roc_mono::layout::Builtin::*;
|
||||||
use roc_mono::layout::Layout::*;
|
use roc_mono::layout::Layout::*;
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
FunctionPointer(args, ret_layout) => {
|
FunctionPointer(args, ret_layout) => {
|
||||||
let ret_type = basic_type_from_layout(arena, context, &ret_layout);
|
let ret_type = basic_type_from_layout(arena, context, &ret_layout, ptr_bytes);
|
||||||
let mut arg_basic_types = Vec::with_capacity_in(args.len(), arena);
|
let mut arg_basic_types = Vec::with_capacity_in(args.len(), arena);
|
||||||
|
|
||||||
for arg_layout in args.iter() {
|
for arg_layout in args.iter() {
|
||||||
arg_basic_types.push(basic_type_from_layout(arena, context, arg_layout));
|
arg_basic_types.push(basic_type_from_layout(
|
||||||
|
arena, context, arg_layout, ptr_bytes,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let fn_type = get_fn_type(&ret_type, arg_basic_types.into_bump_slice());
|
let fn_type = get_fn_type(&ret_type, arg_basic_types.into_bump_slice());
|
||||||
|
@ -61,7 +64,12 @@ pub fn basic_type_from_layout<'ctx>(
|
||||||
let mut field_types = Vec::with_capacity_in(sorted_fields.len(), arena);
|
let mut field_types = Vec::with_capacity_in(sorted_fields.len(), arena);
|
||||||
|
|
||||||
for (_, field_layout) in sorted_fields.iter() {
|
for (_, field_layout) in sorted_fields.iter() {
|
||||||
field_types.push(basic_type_from_layout(arena, context, field_layout));
|
field_types.push(basic_type_from_layout(
|
||||||
|
arena,
|
||||||
|
context,
|
||||||
|
field_layout,
|
||||||
|
ptr_bytes,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
context
|
context
|
||||||
|
@ -75,7 +83,7 @@ pub fn basic_type_from_layout<'ctx>(
|
||||||
let mut field_types = Vec::with_capacity_in(layouts.len(), arena);
|
let mut field_types = Vec::with_capacity_in(layouts.len(), arena);
|
||||||
|
|
||||||
for layout in layouts.iter() {
|
for layout in layouts.iter() {
|
||||||
field_types.push(basic_type_from_layout(arena, context, layout));
|
field_types.push(basic_type_from_layout(arena, context, layout, ptr_bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
context
|
context
|
||||||
|
@ -107,17 +115,17 @@ pub fn basic_type_from_layout<'ctx>(
|
||||||
Map(_, _) | EmptyMap => panic!("TODO layout_to_basic_type for Builtin::Map"),
|
Map(_, _) | EmptyMap => panic!("TODO layout_to_basic_type for Builtin::Map"),
|
||||||
Set(_) | EmptySet => panic!("TODO layout_to_basic_type for Builtin::Set"),
|
Set(_) | EmptySet => panic!("TODO layout_to_basic_type for Builtin::Set"),
|
||||||
List(elem_layout) => {
|
List(elem_layout) => {
|
||||||
let ptr_type = basic_type_from_layout(arena, context, elem_layout)
|
let ptr_type = basic_type_from_layout(arena, context, elem_layout, ptr_bytes)
|
||||||
.ptr_type(AddressSpace::Generic);
|
.ptr_type(AddressSpace::Generic);
|
||||||
|
|
||||||
collection_wrapper(context, ptr_type).into()
|
collection_wrapper(context, ptr_type, ptr_bytes).into()
|
||||||
}
|
}
|
||||||
EmptyList => {
|
EmptyList => {
|
||||||
let array_type =
|
let array_type =
|
||||||
get_array_type(&context.opaque_struct_type("empty_list_elem").into(), 0);
|
get_array_type(&context.opaque_struct_type("empty_list_elem").into(), 0);
|
||||||
let ptr_type = array_type.ptr_type(AddressSpace::Generic);
|
let ptr_type = array_type.ptr_type(AddressSpace::Generic);
|
||||||
|
|
||||||
collection_wrapper(context, ptr_type).into()
|
collection_wrapper(context, ptr_type, ptr_bytes).into()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -127,9 +135,24 @@ pub fn basic_type_from_layout<'ctx>(
|
||||||
pub fn collection_wrapper<'ctx>(
|
pub fn collection_wrapper<'ctx>(
|
||||||
ctx: &'ctx Context,
|
ctx: &'ctx Context,
|
||||||
ptr_type: PointerType<'ctx>,
|
ptr_type: PointerType<'ctx>,
|
||||||
|
ptr_bytes: u32,
|
||||||
) -> StructType<'ctx> {
|
) -> StructType<'ctx> {
|
||||||
let ptr_type_enum = BasicTypeEnum::PointerType(ptr_type);
|
let ptr_type_enum = BasicTypeEnum::PointerType(ptr_type);
|
||||||
let u32_type = BasicTypeEnum::IntType(ctx.i32_type());
|
let len_type = BasicTypeEnum::IntType(ptr_int(ctx, ptr_bytes));
|
||||||
|
|
||||||
ctx.struct_type(&[ptr_type_enum, u32_type, u32_type], false)
|
ctx.struct_type(&[ptr_type_enum, len_type], false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ptr_int(ctx: &Context, ptr_bytes: u32) -> IntType<'_> {
|
||||||
|
match ptr_bytes {
|
||||||
|
1 => ctx.i8_type(),
|
||||||
|
2 => ctx.i16_type(),
|
||||||
|
4 => ctx.i32_type(),
|
||||||
|
8 => ctx.i64_type(),
|
||||||
|
16 => ctx.i128_type(),
|
||||||
|
_ => panic!(
|
||||||
|
"Invalid target: Roc does't support compiling to {}-bit systems.",
|
||||||
|
ptr_bytes * 8
|
||||||
|
),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,16 +202,16 @@ mod test_gen {
|
||||||
// Compute main_fn_type before moving subs to Env
|
// Compute main_fn_type before moving subs to Env
|
||||||
let layout = Layout::from_content(&arena, content, &subs, POINTER_SIZE)
|
let layout = Layout::from_content(&arena, content, &subs, POINTER_SIZE)
|
||||||
.unwrap_or_else(|err| panic!("Code gen error in test: could not convert to layout. Err was {:?} and Subs were {:?}", err, subs));
|
.unwrap_or_else(|err| panic!("Code gen error in test: could not convert to layout. Err was {:?} and Subs were {:?}", err, subs));
|
||||||
let main_fn_type = basic_type_from_layout(&arena, &context, &layout)
|
|
||||||
.fn_type(&[], false);
|
|
||||||
let main_fn_name = "$Test.main";
|
|
||||||
|
|
||||||
let execution_engine =
|
let execution_engine =
|
||||||
module
|
module
|
||||||
.create_jit_execution_engine(OptimizationLevel::None)
|
.create_jit_execution_engine(OptimizationLevel::None)
|
||||||
.expect("Error creating JIT execution engine for test");
|
.expect("Error creating JIT execution engine for test");
|
||||||
|
|
||||||
let pointer_bytes = execution_engine.get_target_data().get_pointer_byte_size(None);
|
let ptr_bytes = execution_engine.get_target_data().get_pointer_byte_size(None);
|
||||||
|
|
||||||
|
let main_fn_type = basic_type_from_layout(&arena, &context, &layout, ptr_bytes)
|
||||||
|
.fn_type(&[], false);
|
||||||
|
let main_fn_name = "$Test.main";
|
||||||
|
|
||||||
// Compile and add all the Procs before adding main
|
// Compile and add all the Procs before adding main
|
||||||
let mut env = roc_gen::llvm::build::Env {
|
let mut env = roc_gen::llvm::build::Env {
|
||||||
|
@ -220,7 +220,7 @@ mod test_gen {
|
||||||
context: &context,
|
context: &context,
|
||||||
interns,
|
interns,
|
||||||
module: arena.alloc(module),
|
module: arena.alloc(module),
|
||||||
pointer_bytes
|
ptr_bytes
|
||||||
};
|
};
|
||||||
let mut procs = Procs::default();
|
let mut procs = Procs::default();
|
||||||
let mut ident_ids = env.interns.all_ident_ids.remove(&home).unwrap();
|
let mut ident_ids = env.interns.all_ident_ids.remove(&home).unwrap();
|
||||||
|
@ -337,16 +337,16 @@ mod test_gen {
|
||||||
// Compute main_fn_type before moving subs to Env
|
// Compute main_fn_type before moving subs to Env
|
||||||
let layout = Layout::from_content(&arena, content, &subs, POINTER_SIZE)
|
let layout = Layout::from_content(&arena, content, &subs, POINTER_SIZE)
|
||||||
.unwrap_or_else(|err| panic!("Code gen error in test: could not convert to layout. Err was {:?} and Subs were {:?}", err, subs));
|
.unwrap_or_else(|err| panic!("Code gen error in test: could not convert to layout. Err was {:?} and Subs were {:?}", err, subs));
|
||||||
let main_fn_type = basic_type_from_layout(&arena, &context, &layout)
|
|
||||||
.fn_type(&[], false);
|
|
||||||
let main_fn_name = "$Test.main";
|
|
||||||
|
|
||||||
let execution_engine =
|
let execution_engine =
|
||||||
module
|
module
|
||||||
.create_jit_execution_engine(OptimizationLevel::None)
|
.create_jit_execution_engine(OptimizationLevel::None)
|
||||||
.expect("Error creating JIT execution engine for test");
|
.expect("Error creating JIT execution engine for test");
|
||||||
|
|
||||||
let pointer_bytes = execution_engine.get_target_data().get_pointer_byte_size(None);
|
let ptr_bytes = execution_engine.get_target_data().get_pointer_byte_size(None);
|
||||||
|
let main_fn_type = basic_type_from_layout(&arena, &context, &layout, ptr_bytes)
|
||||||
|
.fn_type(&[], false);
|
||||||
|
let main_fn_name = "$Test.main";
|
||||||
|
|
||||||
// Compile and add all the Procs before adding main
|
// Compile and add all the Procs before adding main
|
||||||
let mut env = roc_gen::llvm::build::Env {
|
let mut env = roc_gen::llvm::build::Env {
|
||||||
|
@ -355,7 +355,7 @@ mod test_gen {
|
||||||
context: &context,
|
context: &context,
|
||||||
interns,
|
interns,
|
||||||
module: arena.alloc(module),
|
module: arena.alloc(module),
|
||||||
pointer_bytes
|
ptr_bytes
|
||||||
};
|
};
|
||||||
let mut procs = Procs::default();
|
let mut procs = Procs::default();
|
||||||
let mut ident_ids = env.interns.all_ident_ids.remove(&home).unwrap();
|
let mut ident_ids = env.interns.all_ident_ids.remove(&home).unwrap();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue