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 tail-calls
This commit is contained in:
commit
ad23fc7e4b
6 changed files with 9 additions and 1490 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,52 +0,0 @@
|
|||
use cranelift::prelude::AbiParam;
|
||||
use cranelift_codegen::ir::{types, Signature, Type};
|
||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||
use cranelift_module::{Backend, Module};
|
||||
|
||||
use roc_mono::layout::Layout;
|
||||
|
||||
pub fn type_from_layout(cfg: TargetFrontendConfig, layout: &Layout<'_>) -> Type {
|
||||
use roc_mono::layout::Builtin::*;
|
||||
use roc_mono::layout::Layout::*;
|
||||
|
||||
match layout {
|
||||
FunctionPointer(_, _) | Pointer(_) | Struct(_) | Union(_) => cfg.pointer_type(),
|
||||
Builtin(builtin) => match builtin {
|
||||
Int64 => types::I64,
|
||||
Float64 => types::F64,
|
||||
Bool => types::I8,
|
||||
Byte => types::I8,
|
||||
Str | EmptyStr | Map(_, _) | EmptyMap | Set(_) | EmptySet | List(_) | EmptyList => {
|
||||
cfg.pointer_type()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sig_from_layout<B: Backend>(
|
||||
cfg: TargetFrontendConfig,
|
||||
module: &mut Module<B>,
|
||||
layout: &Layout<'_>,
|
||||
) -> Signature {
|
||||
match layout {
|
||||
Layout::FunctionPointer(args, ret) => {
|
||||
let ret_type = type_from_layout(cfg, &ret);
|
||||
let mut sig = module.make_signature();
|
||||
|
||||
// Add return type to the signature
|
||||
sig.returns.push(AbiParam::new(ret_type));
|
||||
|
||||
// Add params to the signature
|
||||
for layout in args.iter() {
|
||||
let arg_type = type_from_layout(cfg, &layout);
|
||||
|
||||
sig.params.push(AbiParam::new(arg_type));
|
||||
}
|
||||
|
||||
sig
|
||||
}
|
||||
_ => {
|
||||
panic!("Could not make Signature from Layout {:?}", layout);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
use cranelift::prelude::{AbiParam, FunctionBuilder, FunctionBuilderContext};
|
||||
use cranelift_codegen::ir::{ExternalName, Function, InstBuilder, Signature};
|
||||
use cranelift_codegen::isa::CallConv;
|
||||
use cranelift_codegen::Context;
|
||||
use cranelift_module::{Backend, FuncId, Linkage, Module};
|
||||
|
||||
pub fn declare_malloc_header<B: Backend>(module: &mut Module<B>) -> (FuncId, Signature) {
|
||||
let ptr_size_type = module.target_config().pointer_type();
|
||||
let sig = Signature {
|
||||
params: vec![AbiParam::new(ptr_size_type)],
|
||||
returns: vec![AbiParam::new(ptr_size_type)],
|
||||
call_conv: CallConv::SystemV, // TODO is this the calling convention we actually want?
|
||||
};
|
||||
|
||||
// Declare the wrapper around malloc
|
||||
let func_id = module
|
||||
.declare_function("roc_malloc", Linkage::Local, &sig)
|
||||
.unwrap();
|
||||
|
||||
(func_id, sig)
|
||||
}
|
||||
|
||||
pub fn define_malloc_body<B: Backend>(
|
||||
module: &mut Module<B>,
|
||||
ctx: &mut Context,
|
||||
sig: Signature,
|
||||
func_id: FuncId,
|
||||
) {
|
||||
let ptr_size_type = module.target_config().pointer_type();
|
||||
|
||||
ctx.func = Function::with_name_signature(ExternalName::user(0, func_id.as_u32()), sig);
|
||||
|
||||
let mut func_ctx = FunctionBuilderContext::new();
|
||||
|
||||
{
|
||||
let mut builder: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
|
||||
let block = builder.create_block();
|
||||
|
||||
builder.switch_to_block(block);
|
||||
builder.append_block_params_for_function_params(block);
|
||||
|
||||
let mut malloc_sig = module.make_signature();
|
||||
|
||||
malloc_sig.params.push(AbiParam::new(ptr_size_type));
|
||||
malloc_sig.returns.push(AbiParam::new(ptr_size_type));
|
||||
|
||||
let callee = module
|
||||
.declare_function("malloc", Linkage::Import, &malloc_sig)
|
||||
.expect("declare malloc");
|
||||
let malloc = module.declare_func_in_func(callee, &mut builder.func);
|
||||
let size = builder.block_params(block)[0];
|
||||
let call = builder.ins().call(malloc, &[size]);
|
||||
let ptr = builder.inst_results(call)[0];
|
||||
|
||||
builder.ins().return_(&[ptr]);
|
||||
|
||||
// TODO re-enable this once Switch stops making unsealed blocks, e.g.
|
||||
// https://docs.rs/cranelift-frontend/0.59.0/src/cranelift_frontend/switch.rs.html#152
|
||||
// builder.seal_block(block);
|
||||
}
|
||||
|
||||
module.define_function(func_id, ctx).unwrap();
|
||||
}
|
||||
|
||||
pub fn define_malloc<B: Backend>(module: &mut Module<B>, ctx: &mut Context) -> FuncId {
|
||||
// TODO investigate whether we can remove this wrapper function somehow.
|
||||
// It may get inlined away, but it seems like it shouldn't be
|
||||
// necessary, and we should be able to return the FuncId of the imported malloc.
|
||||
let ptr_size_type = module.target_config().pointer_type();
|
||||
let sig = Signature {
|
||||
params: vec![AbiParam::new(ptr_size_type)],
|
||||
returns: vec![AbiParam::new(ptr_size_type)],
|
||||
call_conv: CallConv::SystemV, // TODO is this the calling convention we actually want?
|
||||
};
|
||||
|
||||
// Declare the wrapper around malloc
|
||||
let func_id = module
|
||||
.declare_function("roc_malloc", Linkage::Local, &sig)
|
||||
.unwrap();
|
||||
|
||||
let ptr_size_type = module.target_config().pointer_type();
|
||||
|
||||
ctx.func = Function::with_name_signature(ExternalName::user(0, func_id.as_u32()), sig);
|
||||
|
||||
let mut func_ctx = FunctionBuilderContext::new();
|
||||
|
||||
{
|
||||
let mut builder: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
|
||||
let block = builder.create_block();
|
||||
|
||||
builder.switch_to_block(block);
|
||||
builder.append_block_params_for_function_params(block);
|
||||
|
||||
let mut malloc_sig = module.make_signature();
|
||||
|
||||
malloc_sig.params.push(AbiParam::new(ptr_size_type));
|
||||
malloc_sig.returns.push(AbiParam::new(ptr_size_type));
|
||||
|
||||
let callee = module
|
||||
.declare_function("malloc", Linkage::Import, &malloc_sig)
|
||||
.expect("declare malloc");
|
||||
let malloc = module.declare_func_in_func(callee, &mut builder.func);
|
||||
let size = builder.block_params(block)[0];
|
||||
let call = builder.ins().call(malloc, &[size]);
|
||||
let ptr = builder.inst_results(call)[0];
|
||||
|
||||
builder.ins().return_(&[ptr]);
|
||||
|
||||
builder.seal_block(block);
|
||||
builder.finalize();
|
||||
}
|
||||
|
||||
module.define_function(func_id, ctx).unwrap();
|
||||
module.clear_context(ctx);
|
||||
|
||||
func_id
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
pub mod build;
|
||||
pub mod convert;
|
||||
pub mod imports;
|
|
@ -10,5 +10,5 @@
|
|||
// and encouraging shortcuts here creates bad incentives. I would rather temporarily
|
||||
// re-enable this when working on performance optimizations than have it block PRs.
|
||||
#![allow(clippy::large_enum_variant)]
|
||||
pub mod crane;
|
||||
|
||||
pub mod llvm;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue