Merge remote-tracking branch 'origin/trunk' into tail-calls

This commit is contained in:
Folkert 2020-03-26 14:57:28 +01:00
commit ad23fc7e4b
6 changed files with 9 additions and 1490 deletions

File diff suppressed because it is too large Load diff

View file

@ -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);
}
}
}

View file

@ -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
}

View file

@ -1,3 +0,0 @@
pub mod build;
pub mod convert;
pub mod imports;

View file

@ -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;