mirror of
https://github.com/roc-lang/roc.git
synced 2024-11-13 09:49:11 +03:00
Extract externs helpers into gen
This commit is contained in:
parent
3eb75619ea
commit
e6ece40f76
@ -1,17 +1,15 @@
|
||||
use crate::repl::eval;
|
||||
use bumpalo::Bump;
|
||||
use inkwell::builder::Builder;
|
||||
use inkwell::context::Context;
|
||||
use inkwell::module::{Linkage, Module};
|
||||
use inkwell::AddressSpace;
|
||||
use inkwell::module::Linkage;
|
||||
use roc_build::link::module_to_dylib;
|
||||
use roc_build::program::FunctionIterator;
|
||||
use roc_can::builtins::builtin_defs_map;
|
||||
use roc_collections::all::{MutMap, MutSet};
|
||||
use roc_fmt::annotation::Formattable;
|
||||
use roc_fmt::annotation::{Newlines, Parens};
|
||||
use roc_gen::llvm::build::{build_proc, build_proc_header, set_name, OptLevel, C_CALL_CONV};
|
||||
use roc_gen::llvm::convert::ptr_int;
|
||||
use roc_gen::llvm::build::{build_proc, build_proc_header, OptLevel};
|
||||
use roc_gen::llvm::externs::add_default_roc_externs;
|
||||
use roc_load::file::LoadingProblem;
|
||||
use roc_parse::parser::SyntaxError;
|
||||
use roc_types::pretty_print::{content_to_string, name_all_type_vars};
|
||||
@ -319,188 +317,3 @@ fn promote_expr_to_module(src: &str) -> String {
|
||||
|
||||
buffer
|
||||
}
|
||||
|
||||
/// Define functions for roc_alloc, roc_realloc, and roc_dealloc
|
||||
/// which use libc implementations (malloc, realloc, and free)
|
||||
fn add_default_roc_externs<'ctx>(
|
||||
ctx: &'ctx Context,
|
||||
module: &Module<'ctx>,
|
||||
builder: &Builder<'ctx>,
|
||||
ptr_bytes: u32,
|
||||
) {
|
||||
let usize_type = ptr_int(ctx, ptr_bytes);
|
||||
let i32_type = ctx.i32_type();
|
||||
let i8_ptr_type = ctx.i8_type().ptr_type(AddressSpace::Generic);
|
||||
|
||||
// roc_alloc
|
||||
{
|
||||
let fn_val = module.add_function(
|
||||
"roc_alloc",
|
||||
i8_ptr_type.fn_type(
|
||||
&[
|
||||
// alignment: u32
|
||||
i32_type.into(),
|
||||
// size: usize
|
||||
usize_type.into(),
|
||||
],
|
||||
false,
|
||||
),
|
||||
Some(Linkage::External),
|
||||
);
|
||||
|
||||
fn_val.set_call_conventions(C_CALL_CONV);
|
||||
|
||||
let mut params = fn_val.get_param_iter();
|
||||
let alignment_arg = params.next().unwrap();
|
||||
let size_arg = params.next().unwrap();
|
||||
|
||||
debug_assert!(params.next().is_none());
|
||||
|
||||
set_name(alignment_arg, "alignment");
|
||||
set_name(size_arg, "size");
|
||||
|
||||
// Add a basic block for the entry point
|
||||
let entry = ctx.append_basic_block(fn_val, "entry");
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
// Call libc malloc()
|
||||
let retval = builder
|
||||
.build_array_malloc(ctx.i8_type(), size_arg.into_int_value(), "call_malloc")
|
||||
.unwrap();
|
||||
|
||||
builder.build_return(Some(&retval));
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
roc_gen::llvm::build::verify_fn(fn_val);
|
||||
}
|
||||
}
|
||||
|
||||
// roc_realloc
|
||||
{
|
||||
let libc_realloc_val = {
|
||||
let fn_val = module.add_function(
|
||||
"realloc",
|
||||
i8_ptr_type.fn_type(
|
||||
&[
|
||||
// ptr: *void
|
||||
i8_ptr_type.into(),
|
||||
// size: usize
|
||||
usize_type.into(),
|
||||
],
|
||||
false,
|
||||
),
|
||||
Some(Linkage::External),
|
||||
);
|
||||
|
||||
fn_val.set_call_conventions(C_CALL_CONV);
|
||||
|
||||
let mut params = fn_val.get_param_iter();
|
||||
let ptr_arg = params.next().unwrap();
|
||||
let size_arg = params.next().unwrap();
|
||||
|
||||
debug_assert!(params.next().is_none());
|
||||
|
||||
set_name(ptr_arg, "ptr");
|
||||
set_name(size_arg, "size");
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
roc_gen::llvm::build::verify_fn(fn_val);
|
||||
}
|
||||
|
||||
fn_val
|
||||
};
|
||||
|
||||
let fn_val = module.add_function(
|
||||
"roc_realloc",
|
||||
i8_ptr_type.fn_type(
|
||||
&[
|
||||
// alignment: u32
|
||||
i32_type.into(),
|
||||
// ptr: *void
|
||||
i8_ptr_type.into(),
|
||||
// old_size: usize
|
||||
usize_type.into(),
|
||||
// new_size: usize
|
||||
usize_type.into(),
|
||||
],
|
||||
false,
|
||||
),
|
||||
Some(Linkage::External),
|
||||
);
|
||||
|
||||
fn_val.set_call_conventions(C_CALL_CONV);
|
||||
|
||||
let mut params = fn_val.get_param_iter();
|
||||
let alignment_arg = params.next().unwrap();
|
||||
let ptr_arg = params.next().unwrap();
|
||||
let old_size_arg = params.next().unwrap();
|
||||
let new_size_arg = params.next().unwrap();
|
||||
|
||||
debug_assert!(params.next().is_none());
|
||||
|
||||
set_name(alignment_arg, "alignment");
|
||||
set_name(ptr_arg, "ptr");
|
||||
set_name(old_size_arg, "old_size");
|
||||
set_name(new_size_arg, "new_size");
|
||||
|
||||
// Add a basic block for the entry point
|
||||
let entry = ctx.append_basic_block(fn_val, "entry");
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
// Call libc realloc()
|
||||
let call = builder.build_call(
|
||||
libc_realloc_val,
|
||||
&[ptr_arg, new_size_arg],
|
||||
"call_libc_realloc",
|
||||
);
|
||||
|
||||
call.set_call_convention(C_CALL_CONV);
|
||||
|
||||
let retval = call.try_as_basic_value().left().unwrap();
|
||||
|
||||
builder.build_return(Some(&retval));
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
roc_gen::llvm::build::verify_fn(fn_val);
|
||||
}
|
||||
}
|
||||
|
||||
// roc_dealloc
|
||||
{
|
||||
let fn_val = module.add_function(
|
||||
"roc_dealloc",
|
||||
ctx.void_type().fn_type(
|
||||
&[
|
||||
// alignment: u32
|
||||
i32_type.into(),
|
||||
// ptr: *void
|
||||
i8_ptr_type.into(),
|
||||
],
|
||||
false,
|
||||
),
|
||||
Some(Linkage::External),
|
||||
);
|
||||
|
||||
fn_val.set_call_conventions(C_CALL_CONV);
|
||||
|
||||
let mut params = fn_val.get_param_iter();
|
||||
let alignment_arg = params.next().unwrap();
|
||||
let ptr_arg = params.next().unwrap();
|
||||
|
||||
debug_assert!(params.next().is_none());
|
||||
|
||||
set_name(alignment_arg, "alignment");
|
||||
set_name(ptr_arg, "ptr");
|
||||
|
||||
// Call libc free()
|
||||
builder.build_free(ptr_arg.into_pointer_value());
|
||||
|
||||
builder.build_return(None);
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
roc_gen::llvm::build::verify_fn(fn_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
191
compiler/gen/src/llvm/externs.rs
Normal file
191
compiler/gen/src/llvm/externs.rs
Normal file
@ -0,0 +1,191 @@
|
||||
use crate::llvm::build::{set_name, C_CALL_CONV};
|
||||
use crate::llvm::convert::ptr_int;
|
||||
use inkwell::builder::Builder;
|
||||
use inkwell::context::Context;
|
||||
use inkwell::module::{Linkage, Module};
|
||||
use inkwell::AddressSpace;
|
||||
|
||||
/// Define functions for roc_alloc, roc_realloc, and roc_dealloc
|
||||
/// which use libc implementations (malloc, realloc, and free)
|
||||
pub fn add_default_roc_externs<'ctx>(
|
||||
ctx: &'ctx Context,
|
||||
module: &Module<'ctx>,
|
||||
builder: &Builder<'ctx>,
|
||||
ptr_bytes: u32,
|
||||
) {
|
||||
let usize_type = ptr_int(ctx, ptr_bytes);
|
||||
let i32_type = ctx.i32_type();
|
||||
let i8_ptr_type = ctx.i8_type().ptr_type(AddressSpace::Generic);
|
||||
|
||||
// roc_alloc
|
||||
{
|
||||
let fn_val = module.add_function(
|
||||
"roc_alloc",
|
||||
i8_ptr_type.fn_type(
|
||||
&[
|
||||
// alignment: u32
|
||||
i32_type.into(),
|
||||
// size: usize
|
||||
usize_type.into(),
|
||||
],
|
||||
false,
|
||||
),
|
||||
Some(Linkage::External),
|
||||
);
|
||||
|
||||
fn_val.set_call_conventions(C_CALL_CONV);
|
||||
|
||||
let mut params = fn_val.get_param_iter();
|
||||
let alignment_arg = params.next().unwrap();
|
||||
let size_arg = params.next().unwrap();
|
||||
|
||||
debug_assert!(params.next().is_none());
|
||||
|
||||
set_name(alignment_arg, "alignment");
|
||||
set_name(size_arg, "size");
|
||||
|
||||
// Add a basic block for the entry point
|
||||
let entry = ctx.append_basic_block(fn_val, "entry");
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
// Call libc malloc()
|
||||
let retval = builder
|
||||
.build_array_malloc(ctx.i8_type(), size_arg.into_int_value(), "call_malloc")
|
||||
.unwrap();
|
||||
|
||||
builder.build_return(Some(&retval));
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
crate::llvm::build::verify_fn(fn_val);
|
||||
}
|
||||
}
|
||||
|
||||
// roc_realloc
|
||||
{
|
||||
let libc_realloc_val = {
|
||||
let fn_val = module.add_function(
|
||||
"realloc",
|
||||
i8_ptr_type.fn_type(
|
||||
&[
|
||||
// ptr: *void
|
||||
i8_ptr_type.into(),
|
||||
// size: usize
|
||||
usize_type.into(),
|
||||
],
|
||||
false,
|
||||
),
|
||||
Some(Linkage::External),
|
||||
);
|
||||
|
||||
fn_val.set_call_conventions(C_CALL_CONV);
|
||||
|
||||
let mut params = fn_val.get_param_iter();
|
||||
let ptr_arg = params.next().unwrap();
|
||||
let size_arg = params.next().unwrap();
|
||||
|
||||
debug_assert!(params.next().is_none());
|
||||
|
||||
set_name(ptr_arg, "ptr");
|
||||
set_name(size_arg, "size");
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
crate::llvm::build::verify_fn(fn_val);
|
||||
}
|
||||
|
||||
fn_val
|
||||
};
|
||||
|
||||
let fn_val = module.add_function(
|
||||
"roc_realloc",
|
||||
i8_ptr_type.fn_type(
|
||||
&[
|
||||
// alignment: u32
|
||||
i32_type.into(),
|
||||
// ptr: *void
|
||||
i8_ptr_type.into(),
|
||||
// old_size: usize
|
||||
usize_type.into(),
|
||||
// new_size: usize
|
||||
usize_type.into(),
|
||||
],
|
||||
false,
|
||||
),
|
||||
Some(Linkage::External),
|
||||
);
|
||||
|
||||
fn_val.set_call_conventions(C_CALL_CONV);
|
||||
|
||||
let mut params = fn_val.get_param_iter();
|
||||
let alignment_arg = params.next().unwrap();
|
||||
let ptr_arg = params.next().unwrap();
|
||||
let old_size_arg = params.next().unwrap();
|
||||
let new_size_arg = params.next().unwrap();
|
||||
|
||||
debug_assert!(params.next().is_none());
|
||||
|
||||
set_name(alignment_arg, "alignment");
|
||||
set_name(ptr_arg, "ptr");
|
||||
set_name(old_size_arg, "old_size");
|
||||
set_name(new_size_arg, "new_size");
|
||||
|
||||
// Add a basic block for the entry point
|
||||
let entry = ctx.append_basic_block(fn_val, "entry");
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
// Call libc realloc()
|
||||
let call = builder.build_call(
|
||||
libc_realloc_val,
|
||||
&[ptr_arg, new_size_arg],
|
||||
"call_libc_realloc",
|
||||
);
|
||||
|
||||
call.set_call_convention(C_CALL_CONV);
|
||||
|
||||
let retval = call.try_as_basic_value().left().unwrap();
|
||||
|
||||
builder.build_return(Some(&retval));
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
crate::llvm::build::verify_fn(fn_val);
|
||||
}
|
||||
}
|
||||
|
||||
// roc_dealloc
|
||||
{
|
||||
let fn_val = module.add_function(
|
||||
"roc_dealloc",
|
||||
ctx.void_type().fn_type(
|
||||
&[
|
||||
// alignment: u32
|
||||
i32_type.into(),
|
||||
// ptr: *void
|
||||
i8_ptr_type.into(),
|
||||
],
|
||||
false,
|
||||
),
|
||||
Some(Linkage::External),
|
||||
);
|
||||
|
||||
fn_val.set_call_conventions(C_CALL_CONV);
|
||||
|
||||
let mut params = fn_val.get_param_iter();
|
||||
let alignment_arg = params.next().unwrap();
|
||||
let ptr_arg = params.next().unwrap();
|
||||
|
||||
debug_assert!(params.next().is_none());
|
||||
|
||||
set_name(alignment_arg, "alignment");
|
||||
set_name(ptr_arg, "ptr");
|
||||
|
||||
// Call libc free()
|
||||
builder.build_free(ptr_arg.into_pointer_value());
|
||||
|
||||
builder.build_return(None);
|
||||
|
||||
if cfg!(debug_assertions) {
|
||||
crate::llvm::build::verify_fn(fn_val);
|
||||
}
|
||||
}
|
||||
}
|
@ -6,4 +6,5 @@ pub mod build_list;
|
||||
pub mod build_str;
|
||||
pub mod compare;
|
||||
pub mod convert;
|
||||
pub mod externs;
|
||||
pub mod refcounting;
|
||||
|
@ -4,6 +4,7 @@ use roc_build::program::FunctionIterator;
|
||||
use roc_can::builtins::builtin_defs_map;
|
||||
use roc_can::def::Def;
|
||||
use roc_collections::all::{MutMap, MutSet};
|
||||
use roc_gen::llvm::externs::add_default_roc_externs;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_types::subs::VarStore;
|
||||
|
||||
@ -184,7 +185,6 @@ pub fn helper<'a>(
|
||||
// strip Zig debug stuff
|
||||
module.strip_debug_info();
|
||||
|
||||
let builder = context.create_builder();
|
||||
let opt_level = if cfg!(debug_assertions) {
|
||||
roc_gen::llvm::build::OptLevel::Normal
|
||||
} else {
|
||||
@ -216,6 +216,11 @@ pub fn helper<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
// Add roc_alloc, roc_realloc, and roc_dealloc, since the repl has no
|
||||
// platform to provide them.
|
||||
let builder = context.create_builder();
|
||||
add_default_roc_externs(&context, module, &builder, ptr_bytes);
|
||||
|
||||
// Compile and add all the Procs before adding main
|
||||
let env = roc_gen::llvm::build::Env {
|
||||
arena: &arena,
|
||||
|
Loading…
Reference in New Issue
Block a user