mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
final phase
This commit is contained in:
parent
0ed259a80d
commit
c663a35e16
27 changed files with 222 additions and 183 deletions
|
@ -196,15 +196,9 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
|||
pub fn ptr_int(&self) -> IntType<'ctx> {
|
||||
let ctx = self.context;
|
||||
|
||||
match self.target_info {
|
||||
1 => ctx.i8_type(),
|
||||
2 => ctx.i16_type(),
|
||||
4 => ctx.i32_type(),
|
||||
8 => ctx.i64_type(),
|
||||
_ => panic!(
|
||||
"Invalid target: Roc does't support compiling to {}-bit systems.",
|
||||
self.target_info * 8
|
||||
),
|
||||
match self.target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => ctx.i32_type(),
|
||||
roc_target::PtrWidth::Bytes8 => ctx.i64_type(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +211,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
|||
}
|
||||
|
||||
pub fn small_str_bytes(&self) -> u32 {
|
||||
self.target_info * 2
|
||||
self.target_info.ptr_width() as u32 * 2
|
||||
}
|
||||
|
||||
pub fn build_intrinsic_call(
|
||||
|
@ -318,12 +312,9 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
|||
) -> CallSiteValue<'ctx> {
|
||||
let false_val = self.context.bool_type().const_int(0, false);
|
||||
|
||||
let intrinsic_name = match self.target_info {
|
||||
8 => LLVM_MEMSET_I64,
|
||||
4 => LLVM_MEMSET_I32,
|
||||
other => {
|
||||
unreachable!("Unsupported number of ptr_bytes {:?}", other);
|
||||
}
|
||||
let intrinsic_name = match self.target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes8 => LLVM_MEMSET_I64,
|
||||
roc_target::PtrWidth::Bytes4 => LLVM_MEMSET_I32,
|
||||
};
|
||||
|
||||
self.build_intrinsic_call(
|
||||
|
@ -1789,7 +1780,7 @@ fn tag_pointer_set_tag_id<'a, 'ctx, 'env>(
|
|||
pointer: PointerValue<'ctx>,
|
||||
) -> PointerValue<'ctx> {
|
||||
// we only have 3 bits, so can encode only 0..7 (or on 32-bit targets, 2 bits to encode 0..3)
|
||||
debug_assert!((tag_id as u32) < env.target_info);
|
||||
debug_assert!((tag_id as u32) < env.target_info.ptr_width() as u32);
|
||||
|
||||
let ptr_int = env.ptr_int();
|
||||
|
||||
|
@ -1802,11 +1793,10 @@ fn tag_pointer_set_tag_id<'a, 'ctx, 'env>(
|
|||
.build_int_to_ptr(combined, pointer.get_type(), "to_ptr")
|
||||
}
|
||||
|
||||
pub fn tag_pointer_tag_id_bits_and_mask(ptr_bytes: u32) -> (u64, u64) {
|
||||
match ptr_bytes {
|
||||
8 => (3, 0b0000_0111),
|
||||
4 => (2, 0b0000_0011),
|
||||
_ => unreachable!(),
|
||||
pub fn tag_pointer_tag_id_bits_and_mask(target_info: TargetInfo) -> (u64, u64) {
|
||||
match target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes8 => (3, 0b0000_0111),
|
||||
roc_target::PtrWidth::Bytes4 => (2, 0b0000_0011),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2183,8 +2173,9 @@ pub fn allocate_with_refcount_help<'a, 'ctx, 'env>(
|
|||
let builder = env.builder;
|
||||
|
||||
let len_type = env.ptr_int();
|
||||
let ptr_width_u32 = env.target_info.ptr_width() as u32;
|
||||
|
||||
let extra_bytes = alignment_bytes.max(env.target_info);
|
||||
let extra_bytes = alignment_bytes.max(ptr_width_u32);
|
||||
|
||||
let ptr = {
|
||||
// number of bytes we will allocated
|
||||
|
@ -2209,8 +2200,8 @@ pub fn allocate_with_refcount_help<'a, 'ctx, 'env>(
|
|||
.into_pointer_value();
|
||||
|
||||
let index = match extra_bytes {
|
||||
n if n == env.target_info => 1,
|
||||
n if n == 2 * env.target_info => 2,
|
||||
n if n == ptr_width_u32 => 1,
|
||||
n if n == 2 * ptr_width_u32 => 2,
|
||||
_ => unreachable!("invalid extra_bytes, {}", extra_bytes),
|
||||
};
|
||||
|
||||
|
@ -2229,11 +2220,11 @@ pub fn allocate_with_refcount_help<'a, 'ctx, 'env>(
|
|||
};
|
||||
|
||||
let refcount_ptr = match extra_bytes {
|
||||
n if n == env.target_info => {
|
||||
n if n == ptr_width_u32 => {
|
||||
// the allocated pointer is the same as the refcounted pointer
|
||||
unsafe { PointerToRefcount::from_ptr(env, ptr) }
|
||||
}
|
||||
n if n == 2 * env.target_info => {
|
||||
n if n == 2 * ptr_width_u32 => {
|
||||
// the refcount is stored just before the start of the actual data
|
||||
// but in this case (because of alignment) not at the start of the allocated buffer
|
||||
PointerToRefcount::from_ptr_to_data(env, data_ptr)
|
||||
|
@ -2288,10 +2279,11 @@ fn list_literal<'a, 'ctx, 'env>(
|
|||
let size = list_length * element_width as usize;
|
||||
let alignment = element_layout
|
||||
.alignment_bytes(env.target_info)
|
||||
.max(env.target_info);
|
||||
.max(env.target_info.ptr_width() as u32);
|
||||
|
||||
let mut is_all_constant = true;
|
||||
let zero_elements = (env.target_info as f64 / element_width as f64).ceil() as usize;
|
||||
let zero_elements =
|
||||
(env.target_info.ptr_width() as u8 as f64 / element_width as f64).ceil() as usize;
|
||||
|
||||
// runtime-evaluated elements
|
||||
let mut runtime_evaluated_elements = Vec::with_capacity_in(list_length, env.arena);
|
||||
|
@ -3727,7 +3719,10 @@ fn expose_function_to_host_help_c_abi<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
pub fn get_sjlj_buffer<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> PointerValue<'ctx> {
|
||||
let type_ = env.context.i8_type().array_type(5 * env.target_info);
|
||||
let type_ = env
|
||||
.context
|
||||
.i8_type()
|
||||
.array_type(5 * env.target_info.ptr_width() as u32);
|
||||
|
||||
let global = match env.module.get_global("roc_sjlj_buffer") {
|
||||
Some(global) => global,
|
||||
|
@ -3895,8 +3890,12 @@ fn make_exception_catcher<'a, 'ctx, 'env>(
|
|||
function_value
|
||||
}
|
||||
|
||||
fn roc_result_layout<'a>(arena: &'a Bump, return_layout: Layout<'a>, ptr_bytes: u32) -> Layout<'a> {
|
||||
let elements = [Layout::u64(), Layout::usize(ptr_bytes), return_layout];
|
||||
fn roc_result_layout<'a>(
|
||||
arena: &'a Bump,
|
||||
return_layout: Layout<'a>,
|
||||
target_info: TargetInfo,
|
||||
) -> Layout<'a> {
|
||||
let elements = [Layout::u64(), Layout::usize(target_info), return_layout];
|
||||
|
||||
Layout::Struct(arena.alloc(elements))
|
||||
}
|
||||
|
@ -6076,8 +6075,8 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
{
|
||||
bd.position_at_end(throw_block);
|
||||
|
||||
match env.target_info {
|
||||
8 => {
|
||||
match env.target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes8 => {
|
||||
let fn_ptr_type = context
|
||||
.void_type()
|
||||
.fn_type(&[], false)
|
||||
|
@ -6096,11 +6095,10 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
bd.build_unconditional_branch(then_block);
|
||||
}
|
||||
4 => {
|
||||
roc_target::PtrWidth::Bytes4 => {
|
||||
// temporary WASM implementation
|
||||
throw_exception(env, "An expectation failed!");
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6196,7 +6194,7 @@ enum CCReturn {
|
|||
/// According to the C ABI, how should we return a value with the given layout?
|
||||
fn to_cc_return<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) -> CCReturn {
|
||||
let return_size = layout.stack_size(env.target_info);
|
||||
let pass_result_by_pointer = return_size > 2 * env.target_info;
|
||||
let pass_result_by_pointer = return_size > 2 * env.target_info.ptr_width() as u32;
|
||||
|
||||
if return_size == 0 {
|
||||
CCReturn::Void
|
||||
|
@ -7130,7 +7128,9 @@ fn define_global_str_literal_ptr<'a, 'ctx, 'env>(
|
|||
let ptr = unsafe {
|
||||
env.builder.build_in_bounds_gep(
|
||||
ptr,
|
||||
&[env.ptr_int().const_int(env.target_info as u64, false)],
|
||||
&[env
|
||||
.ptr_int()
|
||||
.const_int(env.target_info.ptr_width() as u64, false)],
|
||||
"get_rc_ptr",
|
||||
)
|
||||
};
|
||||
|
@ -7160,11 +7160,11 @@ fn define_global_str_literal<'a, 'ctx, 'env>(
|
|||
Some(current) => current,
|
||||
|
||||
None => {
|
||||
let size = message.bytes().len() + env.target_info as usize;
|
||||
let size = message.bytes().len() + env.target_info.ptr_width() as usize;
|
||||
let mut bytes = Vec::with_capacity_in(size, env.arena);
|
||||
|
||||
// insert NULL bytes for the refcount
|
||||
for _ in 0..env.target_info {
|
||||
for _ in 0..env.target_info.ptr_width() as usize {
|
||||
bytes.push(env.context.i8_type().const_zero());
|
||||
}
|
||||
|
||||
|
@ -7183,7 +7183,7 @@ fn define_global_str_literal<'a, 'ctx, 'env>(
|
|||
// strings are NULL-terminated, which means we can't store the refcount (which is 8
|
||||
// NULL bytes)
|
||||
global.set_constant(true);
|
||||
global.set_alignment(env.target_info);
|
||||
global.set_alignment(env.target_info.ptr_width() as u32);
|
||||
global.set_unnamed_addr(true);
|
||||
global.set_linkage(inkwell::module::Linkage::Private);
|
||||
|
||||
|
|
|
@ -17,14 +17,15 @@ use inkwell::AddressSpace;
|
|||
use roc_builtins::bitcode;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds};
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
#[repr(transparent)]
|
||||
struct Alignment(u8);
|
||||
|
||||
impl Alignment {
|
||||
fn from_key_value_layout(key: &Layout, value: &Layout, ptr_bytes: u32) -> Alignment {
|
||||
let key_align = key.alignment_bytes(ptr_bytes);
|
||||
let value_align = value.alignment_bytes(ptr_bytes);
|
||||
fn from_key_value_layout(key: &Layout, value: &Layout, target_info: TargetInfo) -> Alignment {
|
||||
let key_align = key.alignment_bytes(target_info);
|
||||
let value_align = value.alignment_bytes(target_info);
|
||||
|
||||
let mut bits = key_align.max(value_align) as u8;
|
||||
|
||||
|
@ -454,19 +455,18 @@ fn pass_dict_c_abi<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
dict: BasicValueEnum<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
match env.target_info {
|
||||
4 => {
|
||||
match env.target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => {
|
||||
let target_type = env.context.custom_width_int_type(96).into();
|
||||
|
||||
complex_bitcast(env.builder, dict, target_type, "to_i96")
|
||||
}
|
||||
8 => {
|
||||
roc_target::PtrWidth::Bytes8 => {
|
||||
let dict_ptr = env.builder.build_alloca(zig_dict_type(env), "dict_ptr");
|
||||
env.builder.build_store(dict_ptr, dict);
|
||||
|
||||
dict_ptr.into()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ use morphic_lib::UpdateMode;
|
|||
use roc_builtins::bitcode::{self, IntWidth};
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout};
|
||||
use roc_target::PtrWidth;
|
||||
|
||||
use super::build::load_symbol;
|
||||
|
||||
|
@ -79,10 +80,9 @@ fn str_symbol_to_c_abi<'a, 'ctx, 'env>(
|
|||
) -> IntValue<'ctx> {
|
||||
let string = load_symbol(scope, &symbol);
|
||||
|
||||
let target_type = match env.target_info {
|
||||
8 => env.context.i128_type().into(),
|
||||
4 => env.context.i64_type().into(),
|
||||
_ => unreachable!(),
|
||||
let target_type = match env.target_info.ptr_width() {
|
||||
PtrWidth::Bytes8 => env.context.i128_type().into(),
|
||||
PtrWidth::Bytes4 => env.context.i64_type().into(),
|
||||
};
|
||||
|
||||
complex_bitcast(env.builder, string, target_type, "str_to_c_abi").into_int_value()
|
||||
|
@ -96,10 +96,9 @@ pub fn str_to_c_abi<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.build_store(cell, value);
|
||||
|
||||
let target_type = match env.target_info {
|
||||
8 => env.context.i128_type(),
|
||||
4 => env.context.i64_type(),
|
||||
_ => unreachable!(),
|
||||
let target_type = match env.target_info.ptr_width() {
|
||||
PtrWidth::Bytes8 => env.context.i128_type(),
|
||||
PtrWidth::Bytes4 => env.context.i64_type(),
|
||||
};
|
||||
|
||||
let target_type_ptr = env
|
||||
|
@ -310,20 +309,19 @@ fn decode_from_utf8_result<'a, 'ctx, 'env>(
|
|||
let builder = env.builder;
|
||||
let ctx = env.context;
|
||||
|
||||
let fields = match env.target_info {
|
||||
8 | 4 => [
|
||||
let fields = match env.target_info.ptr_width() {
|
||||
PtrWidth::Bytes4 | PtrWidth::Bytes8 => [
|
||||
env.ptr_int().into(),
|
||||
super::convert::zig_str_type(env).into(),
|
||||
env.context.bool_type().into(),
|
||||
ctx.i8_type().into(),
|
||||
],
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let record_type = env.context.struct_type(&fields, false);
|
||||
|
||||
match env.target_info {
|
||||
8 | 4 => {
|
||||
match env.target_info.ptr_width() {
|
||||
PtrWidth::Bytes4 | PtrWidth::Bytes8 => {
|
||||
let result_ptr_cast = env
|
||||
.builder
|
||||
.build_bitcast(
|
||||
|
@ -337,7 +335,6 @@ fn decode_from_utf8_result<'a, 'ctx, 'env>(
|
|||
.build_load(result_ptr_cast, "load_utf8_validate_bytes_result")
|
||||
.into_struct_value()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ use inkwell::types::{BasicType, BasicTypeEnum, FloatType, IntType, StructType};
|
|||
use inkwell::AddressSpace;
|
||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_mono::layout::{Builtin, Layout, UnionLayout};
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
fn basic_type_from_record<'a, 'ctx, 'env>(
|
||||
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
|
||||
|
@ -190,13 +191,13 @@ pub fn float_type_from_float_width<'a, 'ctx, 'env>(
|
|||
pub fn block_of_memory_slices<'ctx>(
|
||||
context: &'ctx Context,
|
||||
layouts: &[&[Layout<'_>]],
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
let mut union_size = 0;
|
||||
for tag in layouts {
|
||||
let mut total = 0;
|
||||
for layout in tag.iter() {
|
||||
total += layout.stack_size(ptr_bytes as u32);
|
||||
total += layout.stack_size(target_info);
|
||||
}
|
||||
|
||||
union_size = union_size.max(total);
|
||||
|
@ -208,13 +209,13 @@ pub fn block_of_memory_slices<'ctx>(
|
|||
pub fn block_of_memory<'ctx>(
|
||||
context: &'ctx Context,
|
||||
layout: &Layout<'_>,
|
||||
ptr_bytes: u32,
|
||||
target_info: TargetInfo,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
// TODO make this dynamic
|
||||
let mut union_size = layout.stack_size(ptr_bytes as u32);
|
||||
let mut union_size = layout.stack_size(target_info);
|
||||
|
||||
if let Layout::Union(UnionLayout::NonRecursive { .. }) = layout {
|
||||
union_size -= ptr_bytes;
|
||||
union_size -= target_info.ptr_width() as u32;
|
||||
}
|
||||
|
||||
block_of_memory_help(context, union_size)
|
||||
|
@ -253,16 +254,10 @@ fn block_of_memory_help(context: &Context, union_size: u32) -> BasicTypeEnum<'_>
|
|||
}
|
||||
|
||||
/// The int type that the C ABI turns our RocList/RocStr into
|
||||
pub fn str_list_int(ctx: &Context, ptr_bytes: u32) -> IntType<'_> {
|
||||
match ptr_bytes {
|
||||
1 => ctx.i16_type(),
|
||||
2 => ctx.i32_type(),
|
||||
4 => ctx.i64_type(),
|
||||
8 => ctx.i128_type(),
|
||||
_ => panic!(
|
||||
"Invalid target: Roc does't support compiling to {}-bit systems.",
|
||||
ptr_bytes * 8
|
||||
),
|
||||
pub fn str_list_int(ctx: &Context, target_info: TargetInfo) -> IntType<'_> {
|
||||
match target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => ctx.i32_type(),
|
||||
roc_target::PtrWidth::Bytes8 => ctx.i64_type(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -175,7 +175,9 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
|
|||
let buffer = crate::llvm::build::get_sjlj_buffer(env);
|
||||
|
||||
// write our error message pointer
|
||||
let index = env.ptr_int().const_int(3 * env.target_info as u64, false);
|
||||
let index = env
|
||||
.ptr_int()
|
||||
.const_int(3 * env.target_info.ptr_width() as u64, false);
|
||||
let message_buffer_raw =
|
||||
unsafe { builder.build_gep(buffer, &[index], "raw_msg_buffer_ptr") };
|
||||
let message_buffer = builder.build_bitcast(
|
||||
|
|
|
@ -18,21 +18,16 @@ use inkwell::{AddressSpace, IntPredicate};
|
|||
use roc_module::symbol::Interns;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
/// "Infinite" reference count, for static values
|
||||
/// Ref counts are encoded as negative numbers where isize::MIN represents 1
|
||||
pub const REFCOUNT_MAX: usize = 0_usize;
|
||||
|
||||
pub fn refcount_1(ctx: &Context, ptr_bytes: u32) -> IntValue<'_> {
|
||||
match ptr_bytes {
|
||||
1 => ctx.i8_type().const_int(i8::MIN as u64, false),
|
||||
2 => ctx.i16_type().const_int(i16::MIN as u64, false),
|
||||
4 => ctx.i32_type().const_int(i32::MIN as u64, false),
|
||||
8 => ctx.i64_type().const_int(i64::MIN as u64, false),
|
||||
_ => panic!(
|
||||
"Invalid target: Roc does't support compiling to {}-bit systems.",
|
||||
ptr_bytes * 8
|
||||
),
|
||||
pub fn refcount_1(ctx: &Context, target_info: TargetInfo) -> IntValue<'_> {
|
||||
match target_info.ptr_width() {
|
||||
roc_target::PtrWidth::Bytes4 => ctx.i32_type().const_int(i32::MIN as u64, false),
|
||||
roc_target::PtrWidth::Bytes8 => ctx.i64_type().const_int(i64::MIN as u64, false),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +159,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
|||
pub fn decrement<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) {
|
||||
let alignment = layout
|
||||
.allocation_alignment_bytes(env.target_info)
|
||||
.max(env.target_info);
|
||||
.max(env.target_info.ptr_width() as u32);
|
||||
|
||||
let context = env.context;
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue