mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 15:21:12 +00:00
Extract externs helpers into gen
This commit is contained in:
parent
3eb75619ea
commit
e6ece40f76
4 changed files with 201 additions and 191 deletions
|
@ -1,17 +1,15 @@
|
||||||
use crate::repl::eval;
|
use crate::repl::eval;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use inkwell::builder::Builder;
|
|
||||||
use inkwell::context::Context;
|
use inkwell::context::Context;
|
||||||
use inkwell::module::{Linkage, Module};
|
use inkwell::module::Linkage;
|
||||||
use inkwell::AddressSpace;
|
|
||||||
use roc_build::link::module_to_dylib;
|
use roc_build::link::module_to_dylib;
|
||||||
use roc_build::program::FunctionIterator;
|
use roc_build::program::FunctionIterator;
|
||||||
use roc_can::builtins::builtin_defs_map;
|
use roc_can::builtins::builtin_defs_map;
|
||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_fmt::annotation::Formattable;
|
use roc_fmt::annotation::Formattable;
|
||||||
use roc_fmt::annotation::{Newlines, Parens};
|
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::build::{build_proc, build_proc_header, OptLevel};
|
||||||
use roc_gen::llvm::convert::ptr_int;
|
use roc_gen::llvm::externs::add_default_roc_externs;
|
||||||
use roc_load::file::LoadingProblem;
|
use roc_load::file::LoadingProblem;
|
||||||
use roc_parse::parser::SyntaxError;
|
use roc_parse::parser::SyntaxError;
|
||||||
use roc_types::pretty_print::{content_to_string, name_all_type_vars};
|
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
|
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 build_str;
|
||||||
pub mod compare;
|
pub mod compare;
|
||||||
pub mod convert;
|
pub mod convert;
|
||||||
|
pub mod externs;
|
||||||
pub mod refcounting;
|
pub mod refcounting;
|
||||||
|
|
|
@ -4,6 +4,7 @@ use roc_build::program::FunctionIterator;
|
||||||
use roc_can::builtins::builtin_defs_map;
|
use roc_can::builtins::builtin_defs_map;
|
||||||
use roc_can::def::Def;
|
use roc_can::def::Def;
|
||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
|
use roc_gen::llvm::externs::add_default_roc_externs;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_types::subs::VarStore;
|
use roc_types::subs::VarStore;
|
||||||
|
|
||||||
|
@ -184,7 +185,6 @@ pub fn helper<'a>(
|
||||||
// strip Zig debug stuff
|
// strip Zig debug stuff
|
||||||
module.strip_debug_info();
|
module.strip_debug_info();
|
||||||
|
|
||||||
let builder = context.create_builder();
|
|
||||||
let opt_level = if cfg!(debug_assertions) {
|
let opt_level = if cfg!(debug_assertions) {
|
||||||
roc_gen::llvm::build::OptLevel::Normal
|
roc_gen::llvm::build::OptLevel::Normal
|
||||||
} else {
|
} 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
|
// Compile and add all the Procs before adding main
|
||||||
let env = roc_gen::llvm::build::Env {
|
let env = roc_gen::llvm::build::Env {
|
||||||
arena: &arena,
|
arena: &arena,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue