mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 21:39:07 +00:00
Merge pull request #5020 from roc-lang/dev-unbox-u32
dev backend: reading and writing 32, 16 and 8-bit values
This commit is contained in:
commit
34340de60c
18 changed files with 1862 additions and 706 deletions
|
@ -447,6 +447,9 @@ trait Backend<'a> {
|
|||
LowLevel::NumAddChecked => {
|
||||
self.build_num_add_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
|
||||
}
|
||||
LowLevel::NumSubChecked => {
|
||||
self.build_num_sub_checked(sym, &args[0], &args[1], &arg_layouts[0], ret_layout)
|
||||
}
|
||||
LowLevel::NumAcos => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::NUM_ACOS[FloatWidth::F64].to_string(),
|
||||
|
@ -551,6 +554,27 @@ trait Backend<'a> {
|
|||
);
|
||||
self.build_num_sub_wrap(sym, &args[0], &args[1], ret_layout)
|
||||
}
|
||||
LowLevel::NumSubSaturated => match self.interner().get(*ret_layout) {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::NUM_SUB_SATURATED_INT[int_width].to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
Layout::Builtin(Builtin::Float(FloatWidth::F32)) => {
|
||||
self.build_num_sub(sym, &args[0], &args[1], ret_layout)
|
||||
}
|
||||
Layout::Builtin(Builtin::Float(FloatWidth::F64)) => {
|
||||
// saturated sub is just normal sub
|
||||
self.build_num_sub(sym, &args[0], &args[1], ret_layout)
|
||||
}
|
||||
Layout::Builtin(Builtin::Decimal) => {
|
||||
// self.load_args_and_call_zig(backend, bitcode::DEC_SUB_SATURATED)
|
||||
todo!()
|
||||
}
|
||||
_ => internal_error!("invalid return type"),
|
||||
},
|
||||
LowLevel::NumBitwiseAnd => {
|
||||
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
|
||||
self.build_int_bitwise_and(sym, &args[0], &args[1], int_width)
|
||||
|
@ -572,6 +596,20 @@ trait Backend<'a> {
|
|||
internal_error!("bitwise xor on a non-integer")
|
||||
}
|
||||
}
|
||||
LowLevel::And => {
|
||||
if let Layout::Builtin(Builtin::Bool) = self.interner().get(*ret_layout) {
|
||||
self.build_int_bitwise_and(sym, &args[0], &args[1], IntWidth::U8)
|
||||
} else {
|
||||
internal_error!("bitwise and on a non-integer")
|
||||
}
|
||||
}
|
||||
LowLevel::Or => {
|
||||
if let Layout::Builtin(Builtin::Bool) = self.interner().get(*ret_layout) {
|
||||
self.build_int_bitwise_or(sym, &args[0], &args[1], IntWidth::U8)
|
||||
} else {
|
||||
internal_error!("bitwise or on a non-integer")
|
||||
}
|
||||
}
|
||||
LowLevel::NumShiftLeftBy => {
|
||||
if let Layout::Builtin(Builtin::Int(int_width)) = self.interner().get(*ret_layout) {
|
||||
self.build_int_shift_left(sym, &args[0], &args[1], int_width)
|
||||
|
@ -819,6 +857,13 @@ trait Backend<'a> {
|
|||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrJoinWith => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_JOIN_WITH.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrSplit => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_SPLIT.to_string(),
|
||||
|
@ -840,6 +885,13 @@ trait Backend<'a> {
|
|||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrAppendScalar => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_APPEND_SCALAR.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrEndsWith => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_ENDS_WITH.to_string(),
|
||||
|
@ -854,6 +906,122 @@ trait Backend<'a> {
|
|||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrSubstringUnsafe => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_SUBSTRING_UNSAFE.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrToUtf8 => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_TO_UTF8.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrCountUtf8Bytes => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_COUNT_UTF8_BYTES.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrFromUtf8Range => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_FROM_UTF8_RANGE.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
// LowLevel::StrToUtf8 => self.build_fn_call(
|
||||
// sym,
|
||||
// bitcode::STR_TO_UTF8.to_string(),
|
||||
// args,
|
||||
// arg_layouts,
|
||||
// ret_layout,
|
||||
// ),
|
||||
LowLevel::StrRepeat => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_REPEAT.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrTrim => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_TRIM.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrTrimLeft => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_TRIM_LEFT.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrTrimRight => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_TRIM_RIGHT.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrReserve => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_RESERVE.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrWithCapacity => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_WITH_CAPACITY.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrToScalars => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_TO_SCALARS.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrGetUnsafe => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_GET_UNSAFE.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrGetScalarUnsafe => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::STR_GET_SCALAR_UNSAFE.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::StrToNum => {
|
||||
let number_layout = match self.interner().get(*ret_layout) {
|
||||
Layout::Struct { field_layouts, .. } => field_layouts[0], // TODO: why is it sometimes a struct?
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// match on the return layout to figure out which zig builtin we need
|
||||
let intrinsic = match self.interner().get(number_layout) {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
|
||||
Layout::Builtin(Builtin::Float(float_width)) => {
|
||||
&bitcode::STR_TO_FLOAT[float_width]
|
||||
}
|
||||
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
self.build_fn_call(sym, intrinsic.to_string(), args, arg_layouts, ret_layout)
|
||||
}
|
||||
LowLevel::PtrCast => {
|
||||
debug_assert_eq!(
|
||||
1,
|
||||
|
@ -920,13 +1088,6 @@ trait Backend<'a> {
|
|||
self.load_literal_symbols(args);
|
||||
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||
}
|
||||
Symbol::NUM_ADD_CHECKED => {
|
||||
let layout_id = LayoutIds::default().get(func_sym, ret_layout);
|
||||
let fn_name = self.symbol_to_string(func_sym, layout_id);
|
||||
// Now that the arguments are needed, load them if they are literals.
|
||||
self.load_literal_symbols(args);
|
||||
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||
}
|
||||
Symbol::BOOL_TRUE => {
|
||||
let bool_layout = Layout::BOOL;
|
||||
self.load_literal(&Symbol::DEV_TMP, &bool_layout, &Literal::Bool(true));
|
||||
|
@ -939,7 +1100,24 @@ trait Backend<'a> {
|
|||
self.return_symbol(&Symbol::DEV_TMP, &bool_layout);
|
||||
self.free_symbol(&Symbol::DEV_TMP)
|
||||
}
|
||||
_ => todo!("the function, {:?}", func_sym),
|
||||
Symbol::STR_IS_VALID_SCALAR => {
|
||||
// just call the function
|
||||
let layout_id = LayoutIds::default().get(func_sym, ret_layout);
|
||||
let fn_name = self.symbol_to_string(func_sym, layout_id);
|
||||
// Now that the arguments are needed, load them if they are literals.
|
||||
self.load_literal_symbols(args);
|
||||
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||
}
|
||||
other => {
|
||||
eprintln!("maybe {other:?} should have a custom implementation?");
|
||||
|
||||
// just call the function
|
||||
let layout_id = LayoutIds::default().get(func_sym, ret_layout);
|
||||
let fn_name = self.symbol_to_string(func_sym, layout_id);
|
||||
// Now that the arguments are needed, load them if they are literals.
|
||||
self.load_literal_symbols(args);
|
||||
self.build_fn_call(sym, fn_name, args, arg_layouts, ret_layout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -970,6 +1148,16 @@ trait Backend<'a> {
|
|||
return_layout: &InLayout<'a>,
|
||||
);
|
||||
|
||||
/// build_num_sub_checked stores the sum of src1 and src2 into dst.
|
||||
fn build_num_sub_checked(
|
||||
&mut self,
|
||||
dst: &Symbol,
|
||||
src1: &Symbol,
|
||||
src2: &Symbol,
|
||||
num_layout: &InLayout<'a>,
|
||||
return_layout: &InLayout<'a>,
|
||||
);
|
||||
|
||||
/// build_num_mul stores `src1 * src2` into dst.
|
||||
fn build_num_mul(&mut self, dst: &Symbol, src1: &Symbol, src2: &Symbol, layout: &InLayout<'a>);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue