mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 23:31:12 +00:00
Merge remote-tracking branch 'origin/trunk' into big-nested-pattern-match
This commit is contained in:
commit
e2521c1011
15 changed files with 387 additions and 48 deletions
|
@ -4,7 +4,7 @@ use crate::llvm::build_list::{
|
|||
list_get_unsafe, list_join, list_keep_if, list_len, list_map, list_prepend, list_repeat,
|
||||
list_reverse, list_set, list_single, list_walk_right,
|
||||
};
|
||||
use crate::llvm::build_str::{str_concat, str_count_graphemes, str_len, CHAR_LAYOUT};
|
||||
use crate::llvm::build_str::{str_concat, str_count_graphemes, str_len, str_split, CHAR_LAYOUT};
|
||||
use crate::llvm::compare::{build_eq, build_neq};
|
||||
use crate::llvm::convert::{
|
||||
basic_type_from_layout, block_of_memory, collection, get_fn_type, get_ptr_type, ptr_int,
|
||||
|
@ -24,8 +24,8 @@ use inkwell::passes::{PassManager, PassManagerBuilder};
|
|||
use inkwell::types::{BasicTypeEnum, FunctionType, IntType, StructType};
|
||||
use inkwell::values::BasicValueEnum::{self, *};
|
||||
use inkwell::values::{
|
||||
BasicValue, CallSiteValue, FloatValue, FunctionValue, InstructionOpcode, IntValue,
|
||||
PointerValue, StructValue,
|
||||
BasicValue, CallSiteValue, FloatValue, FunctionValue, InstructionOpcode, InstructionValue,
|
||||
IntValue, PointerValue, StructValue,
|
||||
};
|
||||
use inkwell::OptimizationLevel;
|
||||
use inkwell::{AddressSpace, IntPredicate};
|
||||
|
@ -2229,6 +2229,14 @@ fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
str_concat(env, inplace, scope, parent, args[0], args[1])
|
||||
}
|
||||
StrSplit => {
|
||||
// Str.split : Str, Str -> List Str
|
||||
debug_assert_eq!(args.len(), 2);
|
||||
|
||||
let inplace = get_inplace_from_layout(layout);
|
||||
|
||||
str_split(env, scope, parent, inplace, args[0], args[1])
|
||||
}
|
||||
StrIsEmpty => {
|
||||
// Str.isEmpty : Str -> Str
|
||||
debug_assert_eq!(args.len(), 1);
|
||||
|
@ -2745,12 +2753,7 @@ fn build_int_binop<'a, 'ctx, 'env>(
|
|||
NumLte => bd.build_int_compare(SLE, lhs, rhs, "int_lte").into(),
|
||||
NumRemUnchecked => bd.build_int_signed_rem(lhs, rhs, "rem_int").into(),
|
||||
NumDivUnchecked => bd.build_int_signed_div(lhs, rhs, "div_int").into(),
|
||||
NumPowInt => call_bitcode_fn(
|
||||
NumPowInt,
|
||||
env,
|
||||
&[lhs.into(), rhs.into()],
|
||||
&bitcode::NUM_POW_INT,
|
||||
),
|
||||
NumPowInt => call_bitcode_fn(env, &[lhs.into(), rhs.into()], &bitcode::NUM_POW_INT),
|
||||
_ => {
|
||||
unreachable!("Unrecognized int binary operation: {:?}", op);
|
||||
}
|
||||
|
@ -2758,22 +2761,48 @@ fn build_int_binop<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
pub fn call_bitcode_fn<'a, 'ctx, 'env>(
|
||||
op: LowLevel,
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
args: &[BasicValueEnum<'ctx>],
|
||||
fn_name: &str,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
call_bitcode_fn_help(env, args, fn_name)
|
||||
.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"LLVM error: Did not get return value from bitcode function {:?}",
|
||||
fn_name
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn call_void_bitcode_fn<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
args: &[BasicValueEnum<'ctx>],
|
||||
fn_name: &str,
|
||||
) -> InstructionValue<'ctx> {
|
||||
call_bitcode_fn_help(env, args, fn_name)
|
||||
.try_as_basic_value()
|
||||
.right()
|
||||
.unwrap_or_else(|| panic!("LLVM error: Tried to call void bitcode function, but got return value from bitcode function, {:?}", fn_name))
|
||||
}
|
||||
|
||||
fn call_bitcode_fn_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
args: &[BasicValueEnum<'ctx>],
|
||||
fn_name: &str,
|
||||
) -> CallSiteValue<'ctx> {
|
||||
let fn_val = env
|
||||
.module
|
||||
.get_function(fn_name)
|
||||
.unwrap_or_else(|| panic!("Unrecognized builtin function: {:?} - if you're working on the Roc compiler, do you need to rebuild the bitcode? See compiler/builtins/bitcode/README.md", fn_name));
|
||||
.module
|
||||
.get_function(fn_name)
|
||||
.unwrap_or_else(|| panic!("Unrecognized builtin function: {:?} - if you're working on the Roc compiler, do you need to rebuild the bitcode? See compiler/builtins/bitcode/README.md", fn_name));
|
||||
|
||||
dbg!(fn_val);
|
||||
|
||||
let call = env.builder.build_call(fn_val, args, "call_builtin");
|
||||
|
||||
call.set_call_convention(fn_val.get_call_conventions());
|
||||
|
||||
call.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap_or_else(|| panic!("LLVM error: Invalid call for low-level op {:?}", op))
|
||||
call
|
||||
}
|
||||
|
||||
fn build_float_binop<'a, 'ctx, 'env>(
|
||||
|
@ -2798,8 +2827,7 @@ fn build_float_binop<'a, 'ctx, 'env>(
|
|||
let result = bd.build_float_add(lhs, rhs, "add_float");
|
||||
|
||||
let is_finite =
|
||||
call_bitcode_fn(NumIsFinite, env, &[result.into()], &bitcode::NUM_IS_FINITE)
|
||||
.into_int_value();
|
||||
call_bitcode_fn(env, &[result.into()], &bitcode::NUM_IS_FINITE).into_int_value();
|
||||
|
||||
let then_block = context.append_basic_block(parent, "then_block");
|
||||
let throw_block = context.append_basic_block(parent, "throw_block");
|
||||
|
@ -2820,8 +2848,7 @@ fn build_float_binop<'a, 'ctx, 'env>(
|
|||
let result = bd.build_float_add(lhs, rhs, "add_float");
|
||||
|
||||
let is_finite =
|
||||
call_bitcode_fn(NumIsFinite, env, &[result.into()], &bitcode::NUM_IS_FINITE)
|
||||
.into_int_value();
|
||||
call_bitcode_fn(env, &[result.into()], &bitcode::NUM_IS_FINITE).into_int_value();
|
||||
let is_infinite = bd.build_not(is_finite, "negate");
|
||||
|
||||
let struct_type = context.struct_type(
|
||||
|
@ -2950,10 +2977,10 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
|
|||
env.context.i64_type(),
|
||||
"num_floor",
|
||||
),
|
||||
NumIsFinite => call_bitcode_fn(NumIsFinite, env, &[arg.into()], &bitcode::NUM_IS_FINITE),
|
||||
NumAtan => call_bitcode_fn(NumAtan, env, &[arg.into()], &bitcode::NUM_ATAN),
|
||||
NumAcos => call_bitcode_fn(NumAcos, env, &[arg.into()], &bitcode::NUM_ACOS),
|
||||
NumAsin => call_bitcode_fn(NumAsin, env, &[arg.into()], &bitcode::NUM_ASIN),
|
||||
NumIsFinite => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_IS_FINITE),
|
||||
NumAtan => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_ATAN),
|
||||
NumAcos => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_ACOS),
|
||||
NumAsin => call_bitcode_fn(env, &[arg.into()], &bitcode::NUM_ASIN),
|
||||
_ => {
|
||||
unreachable!("Unrecognized int unary operation: {:?}", op);
|
||||
}
|
||||
|
|
|
@ -1503,17 +1503,12 @@ where
|
|||
|
||||
// This helper simulates a basic for loop, where
|
||||
// and index increments up from 0 to some end value
|
||||
fn incrementing_index_loop<'ctx, LoopFn>(
|
||||
pub fn incrementing_index_loop<'ctx, LoopFn>(
|
||||
builder: &Builder<'ctx>,
|
||||
ctx: &'ctx Context,
|
||||
parent: FunctionValue<'ctx>,
|
||||
end: IntValue<'ctx>,
|
||||
index_name: &str,
|
||||
// allocating memory for an index is costly, so sometimes
|
||||
// we want to reuse an index if multiple loops happen in a
|
||||
// series, such as the case in List.concat. A memory
|
||||
// allocation cab be passed in to be used, and the memory
|
||||
// allocation that _is_ used is the return value.
|
||||
mut loop_fn: LoopFn,
|
||||
) -> PointerValue<'ctx>
|
||||
where
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::llvm::build::{call_bitcode_fn, ptr_from_symbol, Env, InPlace, Scope};
|
||||
use crate::llvm::build::{
|
||||
call_bitcode_fn, call_void_bitcode_fn, ptr_from_symbol, Env, InPlace, Scope,
|
||||
};
|
||||
use crate::llvm::build_list::{
|
||||
allocate_list, build_basic_phi2, empty_list, incrementing_elem_loop, load_list_ptr, store_list,
|
||||
};
|
||||
|
@ -8,12 +10,81 @@ use inkwell::types::BasicTypeEnum;
|
|||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
||||
use inkwell::{AddressSpace, IntPredicate};
|
||||
use roc_builtins::bitcode;
|
||||
use roc_module::low_level::LowLevel;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, Layout};
|
||||
|
||||
pub static CHAR_LAYOUT: Layout = Layout::Builtin(Builtin::Int8);
|
||||
|
||||
/// Str.split : Str, Str -> List Str
|
||||
pub fn str_split<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
scope: &Scope<'a, 'ctx>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
inplace: InPlace,
|
||||
str_symbol: Symbol,
|
||||
delimiter_symbol: Symbol,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let builder = env.builder;
|
||||
let ctx = env.context;
|
||||
|
||||
let str_ptr = ptr_from_symbol(scope, str_symbol);
|
||||
let delimiter_ptr = ptr_from_symbol(scope, delimiter_symbol);
|
||||
|
||||
let str_wrapper_type = BasicTypeEnum::StructType(collection(ctx, env.ptr_bytes));
|
||||
|
||||
load_str(
|
||||
env,
|
||||
parent,
|
||||
*str_ptr,
|
||||
str_wrapper_type,
|
||||
|str_bytes_ptr, str_len, _str_smallness| {
|
||||
load_str(
|
||||
env,
|
||||
parent,
|
||||
*delimiter_ptr,
|
||||
str_wrapper_type,
|
||||
|delimiter_bytes_ptr, delimiter_len, _delimiter_smallness| {
|
||||
let segment_count = call_bitcode_fn(
|
||||
env,
|
||||
&[
|
||||
BasicValueEnum::PointerValue(str_bytes_ptr),
|
||||
BasicValueEnum::IntValue(str_len),
|
||||
BasicValueEnum::PointerValue(delimiter_bytes_ptr),
|
||||
BasicValueEnum::IntValue(delimiter_len),
|
||||
],
|
||||
&bitcode::STR_COUNT_SEGMENTS,
|
||||
)
|
||||
.into_int_value();
|
||||
|
||||
let ret_list_ptr =
|
||||
allocate_list(env, inplace, &Layout::Builtin(Builtin::Str), segment_count);
|
||||
|
||||
let ret_list_ptr_u128s = builder.build_bitcast(
|
||||
ret_list_ptr,
|
||||
ctx.i128_type().ptr_type(AddressSpace::Generic),
|
||||
"ret_u128_list",
|
||||
);
|
||||
|
||||
call_void_bitcode_fn(
|
||||
env,
|
||||
&[
|
||||
ret_list_ptr_u128s,
|
||||
BasicValueEnum::IntValue(segment_count),
|
||||
BasicValueEnum::PointerValue(str_bytes_ptr),
|
||||
BasicValueEnum::IntValue(str_len),
|
||||
BasicValueEnum::PointerValue(delimiter_bytes_ptr),
|
||||
BasicValueEnum::IntValue(delimiter_len),
|
||||
],
|
||||
&bitcode::STR_STR_SPLIT_IN_PLACE,
|
||||
);
|
||||
|
||||
store_list(env, ret_list_ptr, segment_count)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Str.concat : Str, Str -> Str
|
||||
pub fn str_concat<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
|
@ -613,7 +684,6 @@ pub fn str_count_graphemes<'a, 'ctx, 'env>(
|
|||
ret_type,
|
||||
|str_ptr, str_len, _str_smallness| {
|
||||
call_bitcode_fn(
|
||||
LowLevel::StrCountGraphemes,
|
||||
env,
|
||||
&[
|
||||
BasicValueEnum::PointerValue(str_ptr),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue