mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
llvm build working
This commit is contained in:
parent
c4ec9aa898
commit
123c963ff1
8 changed files with 237 additions and 162 deletions
|
@ -78,19 +78,24 @@ impl FloatWidth {
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub enum IntWidth {
|
pub enum IntWidth {
|
||||||
U8,
|
U8 = 0,
|
||||||
U16,
|
U16 = 1,
|
||||||
U32,
|
U32 = 2,
|
||||||
U64,
|
U64 = 3,
|
||||||
U128,
|
U128 = 4,
|
||||||
I8,
|
I8 = 5,
|
||||||
I16,
|
I16 = 6,
|
||||||
I32,
|
I32 = 7,
|
||||||
I64,
|
I64 = 8,
|
||||||
I128,
|
I128 = 9,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntWidth {
|
impl IntWidth {
|
||||||
|
pub const fn is_signed(&self) -> bool {
|
||||||
|
use IntWidth::*;
|
||||||
|
|
||||||
|
matches!(self, I8 | I16 | I32 | I64 | I128)
|
||||||
|
}
|
||||||
pub const fn stack_size(&self) -> u32 {
|
pub const fn stack_size(&self) -> u32 {
|
||||||
use IntWidth::*;
|
use IntWidth::*;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ use crate::llvm::build_str::{
|
||||||
};
|
};
|
||||||
use crate::llvm::compare::{generic_eq, generic_neq};
|
use crate::llvm::compare::{generic_eq, generic_neq};
|
||||||
use crate::llvm::convert::{
|
use crate::llvm::convert::{
|
||||||
basic_type_from_builtin, basic_type_from_layout, basic_type_from_layout_1,
|
self, basic_type_from_builtin, basic_type_from_layout, basic_type_from_layout_1,
|
||||||
block_of_memory_slices, ptr_int,
|
block_of_memory_slices, ptr_int,
|
||||||
};
|
};
|
||||||
use crate::llvm::refcounting::{
|
use crate::llvm::refcounting::{
|
||||||
|
@ -703,32 +703,31 @@ fn promote_to_main_function<'a, 'ctx, 'env>(
|
||||||
(main_fn_name, main_fn)
|
(main_fn_name, main_fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn int_with_precision<'a, 'ctx, 'env>(
|
fn int_with_precision<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
value: i128,
|
value: i128,
|
||||||
precision: &Builtin,
|
int_width: IntWidth,
|
||||||
) -> IntValue<'ctx> {
|
) -> IntValue<'ctx> {
|
||||||
match precision {
|
use IntWidth::*;
|
||||||
Builtin::Usize => ptr_int(env.context, env.ptr_bytes).const_int(value as u64, false),
|
|
||||||
Builtin::Int128 => const_i128(env, value),
|
match int_width {
|
||||||
Builtin::Int64 => env.context.i64_type().const_int(value as u64, false),
|
U128 | I128 => const_i128(env, value),
|
||||||
Builtin::Int32 => env.context.i32_type().const_int(value as u64, false),
|
U64 | I64 => env.context.i64_type().const_int(value as u64, false),
|
||||||
Builtin::Int16 => env.context.i16_type().const_int(value as u64, false),
|
U32 | I32 => env.context.i32_type().const_int(value as u64, false),
|
||||||
Builtin::Int8 => env.context.i8_type().const_int(value as u64, false),
|
U16 | I16 => env.context.i16_type().const_int(value as u64, false),
|
||||||
Builtin::Bool => env.context.bool_type().const_int(value as u64, false),
|
U8 | I8 => env.context.i8_type().const_int(value as u64, false),
|
||||||
_ => panic!("Invalid layout for int literal = {:?}", precision),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn float_with_precision<'a, 'ctx, 'env>(
|
fn float_with_precision<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
value: f64,
|
value: f64,
|
||||||
precision: &Builtin,
|
float_width: FloatWidth,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
match precision {
|
match float_width {
|
||||||
Builtin::Float64 => env.context.f64_type().const_float(value).into(),
|
FloatWidth::F64 => env.context.f64_type().const_float(value).into(),
|
||||||
Builtin::Float32 => env.context.f32_type().const_float(value).into(),
|
FloatWidth::F32 => env.context.f32_type().const_float(value).into(),
|
||||||
_ => panic!("Invalid layout for float literal = {:?}", precision),
|
FloatWidth::F128 => todo!("F128 is not implemented"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,12 +740,22 @@ pub fn build_exp_literal<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
match literal {
|
match literal {
|
||||||
Int(int) => match layout {
|
Int(int) => match layout {
|
||||||
Layout::Builtin(builtin) => int_with_precision(env, *int as i128, builtin).into(),
|
Layout::Builtin(Builtin::Bool) => {
|
||||||
|
env.context.bool_type().const_int(*int as u64, false).into()
|
||||||
|
}
|
||||||
|
Layout::Builtin(Builtin::Usize) => ptr_int(env.context, env.ptr_bytes)
|
||||||
|
.const_int(*int as u64, false)
|
||||||
|
.into(),
|
||||||
|
Layout::Builtin(Builtin::Int(int_width)) => {
|
||||||
|
int_with_precision(env, *int as i128, *int_width).into()
|
||||||
|
}
|
||||||
_ => panic!("Invalid layout for int literal = {:?}", layout),
|
_ => panic!("Invalid layout for int literal = {:?}", layout),
|
||||||
},
|
},
|
||||||
|
|
||||||
Float(float) => match layout {
|
Float(float) => match layout {
|
||||||
Layout::Builtin(builtin) => float_with_precision(env, *float, builtin),
|
Layout::Builtin(Builtin::Float(float_width)) => {
|
||||||
|
float_with_precision(env, *float, *float_width)
|
||||||
|
}
|
||||||
_ => panic!("Invalid layout for float literal = {:?}", layout),
|
_ => panic!("Invalid layout for float literal = {:?}", layout),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -3044,20 +3053,18 @@ fn build_switch_ir<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
// Build the condition
|
// Build the condition
|
||||||
let cond = match cond_layout {
|
let cond = match cond_layout {
|
||||||
Layout::Builtin(Builtin::Float64) => {
|
Layout::Builtin(Builtin::Float(float_width)) => {
|
||||||
// float matches are done on the bit pattern
|
// float matches are done on the bit pattern
|
||||||
cond_layout = Layout::Builtin(Builtin::Int64);
|
cond_layout = Layout::float_width(float_width);
|
||||||
|
|
||||||
|
let int_type = match float_width {
|
||||||
|
FloatWidth::F32 => env.context.i32_type(),
|
||||||
|
FloatWidth::F64 => env.context.i64_type(),
|
||||||
|
FloatWidth::F128 => env.context.i128_type(),
|
||||||
|
};
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.build_bitcast(cond_value, env.context.i64_type(), "")
|
.build_bitcast(cond_value, int_type, "")
|
||||||
.into_int_value()
|
|
||||||
}
|
|
||||||
Layout::Builtin(Builtin::Float32) => {
|
|
||||||
// float matches are done on the bit pattern
|
|
||||||
cond_layout = Layout::Builtin(Builtin::Int32);
|
|
||||||
|
|
||||||
builder
|
|
||||||
.build_bitcast(cond_value, env.context.i32_type(), "")
|
|
||||||
.into_int_value()
|
.into_int_value()
|
||||||
}
|
}
|
||||||
Layout::Union(variant) => {
|
Layout::Union(variant) => {
|
||||||
|
@ -3433,7 +3440,7 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx, 'env>(
|
||||||
call_roc_function(
|
call_roc_function(
|
||||||
env,
|
env,
|
||||||
roc_wrapper_function,
|
roc_wrapper_function,
|
||||||
&Layout::Struct(&[Layout::Builtin(Builtin::Int64), return_layout]),
|
&Layout::Struct(&[Layout::u64(), return_layout]),
|
||||||
arguments_for_call,
|
arguments_for_call,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -3811,11 +3818,7 @@ fn make_exception_catcher<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn roc_result_layout<'a>(arena: &'a Bump, return_layout: Layout<'a>) -> Layout<'a> {
|
fn roc_result_layout<'a>(arena: &'a Bump, return_layout: Layout<'a>) -> Layout<'a> {
|
||||||
let elements = [
|
let elements = [Layout::u64(), Layout::usize(), return_layout];
|
||||||
Layout::Builtin(Builtin::Int64),
|
|
||||||
Layout::Builtin(Builtin::Usize),
|
|
||||||
return_layout,
|
|
||||||
];
|
|
||||||
|
|
||||||
Layout::Struct(arena.alloc(elements))
|
Layout::Struct(arena.alloc(elements))
|
||||||
}
|
}
|
||||||
|
@ -5553,17 +5556,13 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
use roc_mono::layout::Builtin::*;
|
use roc_mono::layout::Builtin::*;
|
||||||
|
|
||||||
match arg_builtin {
|
match arg_builtin {
|
||||||
Usize | Int128 | Int64 | Int32 | Int16 | Int8 => {
|
Usize | Int(_) => {
|
||||||
build_int_unary_op(env, arg.into_int_value(), arg_builtin, op)
|
let int_width = intwidth_from_builtin(*arg_builtin, env.ptr_bytes);
|
||||||
|
let int_type = convert::int_type_from_int_width(env, int_width);
|
||||||
|
build_int_unary_op(env, arg.into_int_value(), int_type, op)
|
||||||
}
|
}
|
||||||
Float32 => {
|
Float(float_width) => {
|
||||||
build_float_unary_op(env, arg.into_float_value(), op, FloatWidth::F32)
|
build_float_unary_op(env, arg.into_float_value(), op, *float_width)
|
||||||
}
|
|
||||||
Float64 => {
|
|
||||||
build_float_unary_op(env, arg.into_float_value(), op, FloatWidth::F64)
|
|
||||||
}
|
|
||||||
Float128 => {
|
|
||||||
build_float_unary_op(env, arg.into_float_value(), op, FloatWidth::F128)
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!("Compiler bug: tried to run numeric operation {:?} on invalid builtin layout: ({:?})", op, arg_layout);
|
unreachable!("Compiler bug: tried to run numeric operation {:?} on invalid builtin layout: ({:?})", op, arg_layout);
|
||||||
|
@ -5633,15 +5632,22 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
let tag_lt = env.context.i8_type().const_int(2_u64, false);
|
let tag_lt = env.context.i8_type().const_int(2_u64, false);
|
||||||
|
|
||||||
match lhs_builtin {
|
match lhs_builtin {
|
||||||
Usize | Int128 | Int64 | Int32 | Int16 | Int8 => {
|
Int(int_width) => {
|
||||||
let are_equal = env.builder.build_int_compare(
|
let are_equal = env.builder.build_int_compare(
|
||||||
IntPredicate::EQ,
|
IntPredicate::EQ,
|
||||||
lhs_arg.into_int_value(),
|
lhs_arg.into_int_value(),
|
||||||
rhs_arg.into_int_value(),
|
rhs_arg.into_int_value(),
|
||||||
"int_eq",
|
"int_eq",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let predicate = if int_width.is_signed() {
|
||||||
|
IntPredicate::SLT
|
||||||
|
} else {
|
||||||
|
IntPredicate::ULT
|
||||||
|
};
|
||||||
|
|
||||||
let is_less_than = env.builder.build_int_compare(
|
let is_less_than = env.builder.build_int_compare(
|
||||||
IntPredicate::SLT,
|
predicate,
|
||||||
lhs_arg.into_int_value(),
|
lhs_arg.into_int_value(),
|
||||||
rhs_arg.into_int_value(),
|
rhs_arg.into_int_value(),
|
||||||
"int_compare",
|
"int_compare",
|
||||||
|
@ -5658,7 +5664,32 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
"lt_or_gt",
|
"lt_or_gt",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Float128 | Float64 | Float32 => {
|
Usize => {
|
||||||
|
let are_equal = env.builder.build_int_compare(
|
||||||
|
IntPredicate::EQ,
|
||||||
|
lhs_arg.into_int_value(),
|
||||||
|
rhs_arg.into_int_value(),
|
||||||
|
"int_eq",
|
||||||
|
);
|
||||||
|
let is_less_than = env.builder.build_int_compare(
|
||||||
|
IntPredicate::ULT,
|
||||||
|
lhs_arg.into_int_value(),
|
||||||
|
rhs_arg.into_int_value(),
|
||||||
|
"int_compare",
|
||||||
|
);
|
||||||
|
|
||||||
|
let step1 =
|
||||||
|
env.builder
|
||||||
|
.build_select(is_less_than, tag_lt, tag_gt, "lt_or_gt");
|
||||||
|
|
||||||
|
env.builder.build_select(
|
||||||
|
are_equal,
|
||||||
|
tag_eq,
|
||||||
|
step1.into_int_value(),
|
||||||
|
"lt_or_gt",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Float(_) => {
|
||||||
let are_equal = env.builder.build_float_compare(
|
let are_equal = env.builder.build_float_compare(
|
||||||
FloatPredicate::OEQ,
|
FloatPredicate::OEQ,
|
||||||
lhs_arg.into_float_value(),
|
lhs_arg.into_float_value(),
|
||||||
|
@ -5711,13 +5742,15 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
let (lhs_arg, lhs_layout) = load_symbol_and_layout(scope, &args[0]);
|
let (lhs_arg, lhs_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||||
let (rhs_arg, rhs_layout) = load_symbol_and_layout(scope, &args[1]);
|
let (rhs_arg, rhs_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||||
|
|
||||||
|
debug_assert_eq!(lhs_layout, rhs_layout);
|
||||||
|
let int_width = intwidth_from_layout(*lhs_layout, env.ptr_bytes);
|
||||||
|
|
||||||
build_int_binop(
|
build_int_binop(
|
||||||
env,
|
env,
|
||||||
parent,
|
parent,
|
||||||
|
int_width,
|
||||||
lhs_arg.into_int_value(),
|
lhs_arg.into_int_value(),
|
||||||
lhs_layout,
|
|
||||||
rhs_arg.into_int_value(),
|
rhs_arg.into_int_value(),
|
||||||
rhs_layout,
|
|
||||||
op,
|
op,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -5727,13 +5760,15 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
let (lhs_arg, lhs_layout) = load_symbol_and_layout(scope, &args[0]);
|
let (lhs_arg, lhs_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||||
let (rhs_arg, rhs_layout) = load_symbol_and_layout(scope, &args[1]);
|
let (rhs_arg, rhs_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||||
|
|
||||||
|
debug_assert_eq!(lhs_layout, rhs_layout);
|
||||||
|
let int_width = intwidth_from_layout(*lhs_layout, env.ptr_bytes);
|
||||||
|
|
||||||
build_int_binop(
|
build_int_binop(
|
||||||
env,
|
env,
|
||||||
parent,
|
parent,
|
||||||
|
int_width,
|
||||||
lhs_arg.into_int_value(),
|
lhs_arg.into_int_value(),
|
||||||
lhs_layout,
|
|
||||||
rhs_arg.into_int_value(),
|
rhs_arg.into_int_value(),
|
||||||
rhs_layout,
|
|
||||||
op,
|
op,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -6096,17 +6131,9 @@ fn to_cc_type_builtin<'a, 'ctx, 'env>(
|
||||||
builtin: &Builtin<'a>,
|
builtin: &Builtin<'a>,
|
||||||
) -> BasicTypeEnum<'ctx> {
|
) -> BasicTypeEnum<'ctx> {
|
||||||
match builtin {
|
match builtin {
|
||||||
Builtin::Int128
|
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Usize | Builtin::Decimal => {
|
||||||
| Builtin::Int64
|
basic_type_from_builtin(env, builtin)
|
||||||
| Builtin::Int32
|
}
|
||||||
| Builtin::Int16
|
|
||||||
| Builtin::Int8
|
|
||||||
| Builtin::Bool
|
|
||||||
| Builtin::Usize
|
|
||||||
| Builtin::Decimal
|
|
||||||
| Builtin::Float128
|
|
||||||
| Builtin::Float64
|
|
||||||
| Builtin::Float32 => basic_type_from_builtin(env, builtin),
|
|
||||||
Builtin::Str | Builtin::EmptyStr | Builtin::List(_) | Builtin::EmptyList => {
|
Builtin::Str | Builtin::EmptyStr | Builtin::List(_) | Builtin::EmptyList => {
|
||||||
env.str_list_c_abi().into()
|
env.str_list_c_abi().into()
|
||||||
}
|
}
|
||||||
|
@ -6329,11 +6356,7 @@ pub fn intwidth_from_builtin(builtin: Builtin<'_>, ptr_bytes: u32) -> IntWidth {
|
||||||
use IntWidth::*;
|
use IntWidth::*;
|
||||||
|
|
||||||
match builtin {
|
match builtin {
|
||||||
Builtin::Int128 => I128,
|
Builtin::Int(int_width) => int_width,
|
||||||
Builtin::Int64 => I64,
|
|
||||||
Builtin::Int32 => I32,
|
|
||||||
Builtin::Int16 => I16,
|
|
||||||
Builtin::Int8 => I8,
|
|
||||||
Builtin::Usize => match ptr_bytes {
|
Builtin::Usize => match ptr_bytes {
|
||||||
4 => I32,
|
4 => I32,
|
||||||
8 => I64,
|
8 => I64,
|
||||||
|
@ -6353,10 +6376,9 @@ fn intwidth_from_layout(layout: Layout<'_>, ptr_bytes: u32) -> IntWidth {
|
||||||
fn build_int_binop<'a, 'ctx, 'env>(
|
fn build_int_binop<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
parent: FunctionValue<'ctx>,
|
parent: FunctionValue<'ctx>,
|
||||||
|
int_width: IntWidth,
|
||||||
lhs: IntValue<'ctx>,
|
lhs: IntValue<'ctx>,
|
||||||
lhs_layout: &Layout<'a>,
|
|
||||||
rhs: IntValue<'ctx>,
|
rhs: IntValue<'ctx>,
|
||||||
_rhs_layout: &Layout<'a>,
|
|
||||||
op: LowLevel,
|
op: LowLevel,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
use inkwell::IntPredicate::*;
|
use inkwell::IntPredicate::*;
|
||||||
|
@ -6364,8 +6386,6 @@ fn build_int_binop<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let bd = env.builder;
|
let bd = env.builder;
|
||||||
|
|
||||||
let int_width = intwidth_from_layout(*lhs_layout, env.ptr_bytes);
|
|
||||||
|
|
||||||
match op {
|
match op {
|
||||||
NumAdd => {
|
NumAdd => {
|
||||||
let result = env
|
let result = env
|
||||||
|
@ -6541,27 +6561,35 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
|
||||||
build_float_binop(
|
build_float_binop(
|
||||||
env,
|
env,
|
||||||
parent,
|
parent,
|
||||||
|
float_width,
|
||||||
lhs_arg.into_float_value(),
|
lhs_arg.into_float_value(),
|
||||||
rhs_arg.into_float_value(),
|
rhs_arg.into_float_value(),
|
||||||
float_width,
|
|
||||||
op,
|
op,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
match lhs_builtin {
|
match lhs_builtin {
|
||||||
Usize | Int128 | Int64 | Int32 | Int16 | Int8 => build_int_binop(
|
Usize => {
|
||||||
|
let int_width = intwidth_from_builtin(*lhs_builtin, env.ptr_bytes);
|
||||||
|
build_int_binop(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
int_width,
|
||||||
|
lhs_arg.into_int_value(),
|
||||||
|
rhs_arg.into_int_value(),
|
||||||
|
op,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Int(int_width) => build_int_binop(
|
||||||
env,
|
env,
|
||||||
parent,
|
parent,
|
||||||
|
*int_width,
|
||||||
lhs_arg.into_int_value(),
|
lhs_arg.into_int_value(),
|
||||||
lhs_layout,
|
|
||||||
rhs_arg.into_int_value(),
|
rhs_arg.into_int_value(),
|
||||||
rhs_layout,
|
|
||||||
op,
|
op,
|
||||||
),
|
),
|
||||||
|
|
||||||
Float32 => float_binop(FloatWidth::F32),
|
Float(float_width) => float_binop(*float_width),
|
||||||
Float64 => float_binop(FloatWidth::F64),
|
|
||||||
Float128 => float_binop(FloatWidth::F128),
|
|
||||||
|
|
||||||
Decimal => {
|
Decimal => {
|
||||||
build_dec_binop(env, parent, lhs_arg, lhs_layout, rhs_arg, rhs_layout, op)
|
build_dec_binop(env, parent, lhs_arg, lhs_layout, rhs_arg, rhs_layout, op)
|
||||||
|
@ -6580,9 +6608,9 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
|
||||||
fn build_float_binop<'a, 'ctx, 'env>(
|
fn build_float_binop<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
parent: FunctionValue<'ctx>,
|
parent: FunctionValue<'ctx>,
|
||||||
|
float_width: FloatWidth,
|
||||||
lhs: FloatValue<'ctx>,
|
lhs: FloatValue<'ctx>,
|
||||||
rhs: FloatValue<'ctx>,
|
rhs: FloatValue<'ctx>,
|
||||||
float_width: FloatWidth,
|
|
||||||
op: LowLevel,
|
op: LowLevel,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
use inkwell::FloatPredicate::*;
|
use inkwell::FloatPredicate::*;
|
||||||
|
@ -6843,20 +6871,10 @@ fn int_type_signed_min(int_type: IntType) -> IntValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn builtin_to_int_type<'a, 'ctx, 'env>(
|
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
|
||||||
builtin: &Builtin<'a>,
|
|
||||||
) -> IntType<'ctx> {
|
|
||||||
let result = basic_type_from_builtin(env, builtin);
|
|
||||||
debug_assert!(result.is_int_type());
|
|
||||||
|
|
||||||
result.into_int_type()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_int_unary_op<'a, 'ctx, 'env>(
|
fn build_int_unary_op<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
arg: IntValue<'ctx>,
|
arg: IntValue<'ctx>,
|
||||||
arg_layout: &Builtin<'a>,
|
int_type: IntType<'ctx>,
|
||||||
op: LowLevel,
|
op: LowLevel,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
use roc_module::low_level::LowLevel::*;
|
use roc_module::low_level::LowLevel::*;
|
||||||
|
@ -6866,11 +6884,11 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
||||||
match op {
|
match op {
|
||||||
NumNeg => {
|
NumNeg => {
|
||||||
// integer abs overflows when applied to the minimum value of a signed type
|
// integer abs overflows when applied to the minimum value of a signed type
|
||||||
int_neg_raise_on_overflow(env, arg, arg_layout)
|
int_neg_raise_on_overflow(env, arg, int_type)
|
||||||
}
|
}
|
||||||
NumAbs => {
|
NumAbs => {
|
||||||
// integer abs overflows when applied to the minimum value of a signed type
|
// integer abs overflows when applied to the minimum value of a signed type
|
||||||
int_abs_raise_on_overflow(env, arg, arg_layout)
|
int_abs_raise_on_overflow(env, arg, int_type)
|
||||||
}
|
}
|
||||||
NumToFloat => {
|
NumToFloat => {
|
||||||
// TODO: Handle different sized numbers
|
// TODO: Handle different sized numbers
|
||||||
|
@ -6891,11 +6909,11 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
||||||
fn int_neg_raise_on_overflow<'a, 'ctx, 'env>(
|
fn int_neg_raise_on_overflow<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
arg: IntValue<'ctx>,
|
arg: IntValue<'ctx>,
|
||||||
builtin: &Builtin<'a>,
|
int_type: IntType<'ctx>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
|
|
||||||
let min_val = int_type_signed_min(builtin_to_int_type(env, builtin));
|
let min_val = int_type_signed_min(int_type);
|
||||||
let condition = builder.build_int_compare(IntPredicate::EQ, arg, min_val, "is_min_val");
|
let condition = builder.build_int_compare(IntPredicate::EQ, arg, min_val, "is_min_val");
|
||||||
|
|
||||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||||
|
@ -6921,11 +6939,11 @@ fn int_neg_raise_on_overflow<'a, 'ctx, 'env>(
|
||||||
fn int_abs_raise_on_overflow<'a, 'ctx, 'env>(
|
fn int_abs_raise_on_overflow<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
arg: IntValue<'ctx>,
|
arg: IntValue<'ctx>,
|
||||||
builtin: &Builtin<'a>,
|
int_type: IntType<'ctx>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
|
|
||||||
let min_val = int_type_signed_min(builtin_to_int_type(env, builtin));
|
let min_val = int_type_signed_min(int_type);
|
||||||
let condition = builder.build_int_compare(IntPredicate::EQ, arg, min_val, "is_min_val");
|
let condition = builder.build_int_compare(IntPredicate::EQ, arg, min_val, "is_min_val");
|
||||||
|
|
||||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||||
|
@ -6945,13 +6963,13 @@ fn int_abs_raise_on_overflow<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
builder.position_at_end(else_block);
|
builder.position_at_end(else_block);
|
||||||
|
|
||||||
int_abs_with_overflow(env, arg, builtin)
|
int_abs_with_overflow(env, arg, int_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn int_abs_with_overflow<'a, 'ctx, 'env>(
|
fn int_abs_with_overflow<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
arg: IntValue<'ctx>,
|
arg: IntValue<'ctx>,
|
||||||
arg_layout: &Builtin<'a>,
|
int_type: IntType<'ctx>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
// This is how libc's abs() is implemented - it uses no branching!
|
// This is how libc's abs() is implemented - it uses no branching!
|
||||||
//
|
//
|
||||||
|
@ -6964,10 +6982,10 @@ fn int_abs_with_overflow<'a, 'ctx, 'env>(
|
||||||
let ctx = env.context;
|
let ctx = env.context;
|
||||||
let shifted_name = "abs_shift_right";
|
let shifted_name = "abs_shift_right";
|
||||||
let shifted_alloca = {
|
let shifted_alloca = {
|
||||||
let bits_to_shift = ((arg_layout.stack_size(env.ptr_bytes) as u64) * 8) - 1;
|
let bits_to_shift = int_type.get_bit_width() as u64 - 1;
|
||||||
let shift_val = ctx.i64_type().const_int(bits_to_shift, false);
|
let shift_val = ctx.i64_type().const_int(bits_to_shift, false);
|
||||||
let shifted = bd.build_right_shift(arg, shift_val, true, shifted_name);
|
let shifted = bd.build_right_shift(arg, shift_val, true, shifted_name);
|
||||||
let alloca = bd.build_alloca(basic_type_from_builtin(env, arg_layout), "#int_abs_help");
|
let alloca = bd.build_alloca(int_type, "#int_abs_help");
|
||||||
|
|
||||||
// shifted = arg >>> 63
|
// shifted = arg >>> 63
|
||||||
bd.build_store(alloca, shifted);
|
bd.build_store(alloca, shifted);
|
||||||
|
|
|
@ -123,17 +123,7 @@ fn hash_builtin<'a, 'ctx, 'env>(
|
||||||
let ptr_bytes = env.ptr_bytes;
|
let ptr_bytes = env.ptr_bytes;
|
||||||
|
|
||||||
match builtin {
|
match builtin {
|
||||||
Builtin::Int128
|
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal | Builtin::Usize => {
|
||||||
| Builtin::Int64
|
|
||||||
| Builtin::Int32
|
|
||||||
| Builtin::Int16
|
|
||||||
| Builtin::Int8
|
|
||||||
| Builtin::Bool
|
|
||||||
| Builtin::Float64
|
|
||||||
| Builtin::Float32
|
|
||||||
| Builtin::Float128
|
|
||||||
| Builtin::Decimal
|
|
||||||
| Builtin::Usize => {
|
|
||||||
let hash_bytes = store_and_use_as_u8_ptr(env, val, layout);
|
let hash_bytes = store_and_use_as_u8_ptr(env, val, layout);
|
||||||
hash_bitcode_fn(env, seed, hash_bytes, layout.stack_size(ptr_bytes))
|
hash_bitcode_fn(env, seed, hash_bytes, layout.stack_size(ptr_bytes))
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,7 +183,7 @@ pub fn list_reverse<'a, 'ctx, 'env>(
|
||||||
let element_layout = match *list_layout {
|
let element_layout = match *list_layout {
|
||||||
Layout::Builtin(Builtin::EmptyList) => {
|
Layout::Builtin(Builtin::EmptyList) => {
|
||||||
// this pointer will never actually be dereferenced
|
// this pointer will never actually be dereferenced
|
||||||
Layout::Builtin(Builtin::Int64)
|
Layout::i64()
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout::Builtin(Builtin::List(elem_layout)) => *elem_layout,
|
Layout::Builtin(Builtin::List(elem_layout)) => *elem_layout,
|
||||||
|
|
|
@ -13,7 +13,7 @@ use roc_mono::layout::{Builtin, Layout};
|
||||||
|
|
||||||
use super::build::{intwidth_from_builtin, load_symbol, load_symbol_and_layout};
|
use super::build::{intwidth_from_builtin, load_symbol, load_symbol_and_layout};
|
||||||
|
|
||||||
pub static CHAR_LAYOUT: Layout = Layout::Builtin(Builtin::Int8);
|
pub static CHAR_LAYOUT: Layout = Layout::u8();
|
||||||
|
|
||||||
/// Str.repeat : Str, Nat -> Str
|
/// Str.repeat : Str, Nat -> Str
|
||||||
pub fn str_repeat<'a, 'ctx, 'env>(
|
pub fn str_repeat<'a, 'ctx, 'env>(
|
||||||
|
@ -289,15 +289,11 @@ pub fn str_from_int<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
match int_layout {
|
match int_layout {
|
||||||
Layout::Builtin(builtin) => match builtin {
|
Layout::Builtin(builtin) => match builtin {
|
||||||
Builtin::Usize
|
Builtin::Usize | Builtin::Int(_) => {
|
||||||
| Builtin::Int128
|
|
||||||
| Builtin::Int64
|
|
||||||
| Builtin::Int32
|
|
||||||
| Builtin::Int16
|
|
||||||
| Builtin::Int8 => {
|
|
||||||
let intwidth = intwidth_from_builtin(*builtin, env.ptr_bytes);
|
let intwidth = intwidth_from_builtin(*builtin, env.ptr_bytes);
|
||||||
call_bitcode_fn(env, &[int], &bitcode::STR_FROM_INT[intwidth])
|
call_bitcode_fn(env, &[int], &bitcode::STR_FROM_INT[intwidth])
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
unreachable!(
|
unreachable!(
|
||||||
"Compiler bug: tried to convert numeric on invalid builtin layout: ({:?})",
|
"Compiler bug: tried to convert numeric on invalid builtin layout: ({:?})",
|
||||||
|
|
|
@ -10,6 +10,7 @@ use inkwell::values::{
|
||||||
};
|
};
|
||||||
use inkwell::{AddressSpace, FloatPredicate, IntPredicate};
|
use inkwell::{AddressSpace, FloatPredicate, IntPredicate};
|
||||||
use roc_builtins::bitcode;
|
use roc_builtins::bitcode;
|
||||||
|
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
|
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
|
||||||
|
|
||||||
|
@ -88,19 +89,40 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
||||||
};
|
};
|
||||||
|
|
||||||
match builtin {
|
match builtin {
|
||||||
Builtin::Int128 => int_cmp(IntPredicate::EQ, "eq_i128"),
|
Builtin::Int(int_width) => {
|
||||||
Builtin::Int64 => int_cmp(IntPredicate::EQ, "eq_i64"),
|
use IntWidth::*;
|
||||||
Builtin::Int32 => int_cmp(IntPredicate::EQ, "eq_i32"),
|
|
||||||
Builtin::Int16 => int_cmp(IntPredicate::EQ, "eq_i16"),
|
let name = match int_width {
|
||||||
Builtin::Int8 => int_cmp(IntPredicate::EQ, "eq_i8"),
|
I128 => "eq_i128",
|
||||||
|
I64 => "eq_i64",
|
||||||
|
I32 => "eq_i32",
|
||||||
|
I16 => "eq_i16",
|
||||||
|
I8 => "eq_i8",
|
||||||
|
U128 => "eq_u128",
|
||||||
|
U64 => "eq_u64",
|
||||||
|
U32 => "eq_u32",
|
||||||
|
U16 => "eq_u16",
|
||||||
|
U8 => "eq_u8",
|
||||||
|
};
|
||||||
|
|
||||||
|
int_cmp(IntPredicate::EQ, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
Builtin::Float(float_width) => {
|
||||||
|
use FloatWidth::*;
|
||||||
|
|
||||||
|
let name = match float_width {
|
||||||
|
F128 => "eq_f128",
|
||||||
|
F64 => "eq_f64",
|
||||||
|
F32 => "eq_f32",
|
||||||
|
};
|
||||||
|
|
||||||
|
float_cmp(FloatPredicate::OEQ, name)
|
||||||
|
}
|
||||||
|
|
||||||
Builtin::Bool => int_cmp(IntPredicate::EQ, "eq_i1"),
|
Builtin::Bool => int_cmp(IntPredicate::EQ, "eq_i1"),
|
||||||
|
|
||||||
Builtin::Usize => int_cmp(IntPredicate::EQ, "eq_usize"),
|
Builtin::Usize => int_cmp(IntPredicate::EQ, "eq_usize"),
|
||||||
|
|
||||||
Builtin::Decimal => call_bitcode_fn(env, &[lhs_val, rhs_val], bitcode::DEC_EQ),
|
Builtin::Decimal => call_bitcode_fn(env, &[lhs_val, rhs_val], bitcode::DEC_EQ),
|
||||||
Builtin::Float128 => float_cmp(FloatPredicate::OEQ, "eq_f128"),
|
|
||||||
Builtin::Float64 => float_cmp(FloatPredicate::OEQ, "eq_f64"),
|
|
||||||
Builtin::Float32 => float_cmp(FloatPredicate::OEQ, "eq_f32"),
|
|
||||||
|
|
||||||
Builtin::Str => str_equal(env, lhs_val, rhs_val),
|
Builtin::Str => str_equal(env, lhs_val, rhs_val),
|
||||||
Builtin::List(elem) => build_list_eq(
|
Builtin::List(elem) => build_list_eq(
|
||||||
|
@ -231,19 +253,40 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
||||||
};
|
};
|
||||||
|
|
||||||
match builtin {
|
match builtin {
|
||||||
Builtin::Int128 => int_cmp(IntPredicate::NE, "neq_i128"),
|
Builtin::Int(int_width) => {
|
||||||
Builtin::Int64 => int_cmp(IntPredicate::NE, "neq_i64"),
|
use IntWidth::*;
|
||||||
Builtin::Int32 => int_cmp(IntPredicate::NE, "neq_i32"),
|
|
||||||
Builtin::Int16 => int_cmp(IntPredicate::NE, "neq_i16"),
|
let name = match int_width {
|
||||||
Builtin::Int8 => int_cmp(IntPredicate::NE, "neq_i8"),
|
I128 => "neq_i128",
|
||||||
|
I64 => "neq_i64",
|
||||||
|
I32 => "neq_i32",
|
||||||
|
I16 => "neq_i16",
|
||||||
|
I8 => "neq_i8",
|
||||||
|
U128 => "neq_u128",
|
||||||
|
U64 => "neq_u64",
|
||||||
|
U32 => "neq_u32",
|
||||||
|
U16 => "neq_u16",
|
||||||
|
U8 => "neq_u8",
|
||||||
|
};
|
||||||
|
|
||||||
|
int_cmp(IntPredicate::NE, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
Builtin::Float(float_width) => {
|
||||||
|
use FloatWidth::*;
|
||||||
|
|
||||||
|
let name = match float_width {
|
||||||
|
F128 => "neq_f128",
|
||||||
|
F64 => "neq_f64",
|
||||||
|
F32 => "neq_f32",
|
||||||
|
};
|
||||||
|
|
||||||
|
float_cmp(FloatPredicate::ONE, name)
|
||||||
|
}
|
||||||
|
|
||||||
Builtin::Bool => int_cmp(IntPredicate::NE, "neq_i1"),
|
Builtin::Bool => int_cmp(IntPredicate::NE, "neq_i1"),
|
||||||
|
|
||||||
Builtin::Usize => int_cmp(IntPredicate::NE, "neq_usize"),
|
Builtin::Usize => int_cmp(IntPredicate::NE, "neq_usize"),
|
||||||
|
|
||||||
Builtin::Decimal => call_bitcode_fn(env, &[lhs_val, rhs_val], bitcode::DEC_NEQ),
|
Builtin::Decimal => call_bitcode_fn(env, &[lhs_val, rhs_val], bitcode::DEC_NEQ),
|
||||||
Builtin::Float128 => float_cmp(FloatPredicate::ONE, "neq_f128"),
|
|
||||||
Builtin::Float64 => float_cmp(FloatPredicate::ONE, "neq_f64"),
|
|
||||||
Builtin::Float32 => float_cmp(FloatPredicate::ONE, "neq_f32"),
|
|
||||||
|
|
||||||
Builtin::Str => {
|
Builtin::Str => {
|
||||||
let is_equal = str_equal(env, lhs_val, rhs_val).into_int_value();
|
let is_equal = str_equal(env, lhs_val, rhs_val).into_int_value();
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use inkwell::context::Context;
|
use inkwell::context::Context;
|
||||||
use inkwell::types::{BasicType, BasicTypeEnum, IntType, StructType};
|
use inkwell::types::{BasicType, BasicTypeEnum, FloatType, IntType, StructType};
|
||||||
use inkwell::AddressSpace;
|
use inkwell::AddressSpace;
|
||||||
|
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||||
use roc_mono::layout::{Builtin, Layout, UnionLayout};
|
use roc_mono::layout::{Builtin, Layout, UnionLayout};
|
||||||
|
|
||||||
fn basic_type_from_record<'a, 'ctx, 'env>(
|
fn basic_type_from_record<'a, 'ctx, 'env>(
|
||||||
|
@ -146,17 +147,11 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>(
|
||||||
let ptr_bytes = env.ptr_bytes;
|
let ptr_bytes = env.ptr_bytes;
|
||||||
|
|
||||||
match builtin {
|
match builtin {
|
||||||
Int128 => context.i128_type().as_basic_type_enum(),
|
Int(int_width) => int_type_from_int_width(env, *int_width).as_basic_type_enum(),
|
||||||
Int64 => context.i64_type().as_basic_type_enum(),
|
Float(float_width) => float_type_from_float_width(env, *float_width).as_basic_type_enum(),
|
||||||
Int32 => context.i32_type().as_basic_type_enum(),
|
|
||||||
Int16 => context.i16_type().as_basic_type_enum(),
|
|
||||||
Int8 => context.i8_type().as_basic_type_enum(),
|
|
||||||
Bool => context.bool_type().as_basic_type_enum(),
|
Bool => context.bool_type().as_basic_type_enum(),
|
||||||
Usize => ptr_int(context, ptr_bytes).as_basic_type_enum(),
|
Usize => ptr_int(context, ptr_bytes).as_basic_type_enum(),
|
||||||
Decimal => context.i128_type().as_basic_type_enum(),
|
Decimal => context.i128_type().as_basic_type_enum(),
|
||||||
Float128 => context.f128_type().as_basic_type_enum(),
|
|
||||||
Float64 => context.f64_type().as_basic_type_enum(),
|
|
||||||
Float32 => context.f32_type().as_basic_type_enum(),
|
|
||||||
Dict(_, _) | EmptyDict => zig_dict_type(env).into(),
|
Dict(_, _) | EmptyDict => zig_dict_type(env).into(),
|
||||||
Set(_) | EmptySet => zig_dict_type(env).into(),
|
Set(_) | EmptySet => zig_dict_type(env).into(),
|
||||||
List(_) | EmptyList => zig_list_type(env).into(),
|
List(_) | EmptyList => zig_list_type(env).into(),
|
||||||
|
@ -164,6 +159,34 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn int_type_from_int_width<'a, 'ctx, 'env>(
|
||||||
|
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
|
||||||
|
int_width: IntWidth,
|
||||||
|
) -> IntType<'ctx> {
|
||||||
|
use IntWidth::*;
|
||||||
|
|
||||||
|
match int_width {
|
||||||
|
U128 | I128 => env.context.i128_type(),
|
||||||
|
U64 | I64 => env.context.i64_type(),
|
||||||
|
U32 | I32 => env.context.i32_type(),
|
||||||
|
U16 | I16 => env.context.i16_type(),
|
||||||
|
U8 | I8 => env.context.i8_type(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn float_type_from_float_width<'a, 'ctx, 'env>(
|
||||||
|
env: &crate::llvm::build::Env<'a, 'ctx, 'env>,
|
||||||
|
float_width: FloatWidth,
|
||||||
|
) -> FloatType<'ctx> {
|
||||||
|
use FloatWidth::*;
|
||||||
|
|
||||||
|
match float_width {
|
||||||
|
F128 => todo!("F128 is not implemented"),
|
||||||
|
F64 => env.context.f64_type(),
|
||||||
|
F32 => env.context.f32_type(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn block_of_memory_slices<'ctx>(
|
pub fn block_of_memory_slices<'ctx>(
|
||||||
context: &'ctx Context,
|
context: &'ctx Context,
|
||||||
layouts: &[&[Layout<'_>]],
|
layouts: &[&[Layout<'_>]],
|
||||||
|
|
|
@ -1167,7 +1167,7 @@ impl<'a> Layout<'a> {
|
||||||
Layout::Builtin(Builtin::Bool)
|
Layout::Builtin(Builtin::Bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn u8() -> Layout<'a> {
|
pub const fn u8() -> Layout<'a> {
|
||||||
Layout::Builtin(Builtin::Int(IntWidth::U8))
|
Layout::Builtin(Builtin::Int(IntWidth::U8))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue