Skip to content

Commit

Permalink
Merge pull request #202 from baszalmstra/feature/inkwell_types
Browse files Browse the repository at this point in the history
refactor(codegen): type safe inkwell types
  • Loading branch information
baszalmstra authored Jun 2, 2020
2 parents 0011016 + 305b008 commit 9f4c8d7
Show file tree
Hide file tree
Showing 142 changed files with 2,575 additions and 1,247 deletions.
3 changes: 2 additions & 1 deletion crates/mun_codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ categories = ["Game development", "Mun"]
[dependencies]
abi = { version = "=0.2.0", path = "../mun_abi", package = "mun_abi" }
hir = { version = "=0.2.0", path = "../mun_hir", package = "mun_hir" }
mun_codegen_macros = { path = "../mun_codegen_macros", package = "mun_codegen_macros" }
mun_target = { version = "=0.2.0", path = "../mun_target" }
mun_lld = { version = "=70.2.0", path = "../mun_lld" }
failure = "0.1.7"
Expand All @@ -23,6 +24,7 @@ md5="0.6.1"
array-init="0.1.0"
tempfile = "3"
paste = "0.1.6"
parking_lot = "0.10"

[dependencies.inkwell]
git = "https://github.com/mun-lang/inkwell"
Expand All @@ -31,7 +33,6 @@ features = ["llvm7-0"]

[dev-dependencies]
insta = "0.12.0"
parking_lot = "0.10"

[build-dependencies]
semver = "0.9.0"
Expand Down
102 changes: 17 additions & 85 deletions crates/mun_codegen/src/code_gen.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
use crate::code_gen::linker::LinkerError;
use crate::value::{IrTypeContext, IrValueContext};
use crate::IrDatabase;
use failure::Fail;
use hir::{FileId, RelativePathBuf};
use inkwell::targets::TargetData;
use inkwell::{
module::{Linkage, Module},
module::Module,
passes::{PassManager, PassManagerBuilder},
targets::{CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine},
types::StructType,
values::{BasicValue, GlobalValue, IntValue, PointerValue, UnnamedAddress},
AddressSpace, OptimizationLevel,
OptimizationLevel,
};
use mun_target::spec;
use std::io::{self, Write};
Expand Down Expand Up @@ -152,10 +151,23 @@ impl<'a, D: IrDatabase> ModuleBuilder<'a, D> {
.link_in_module(file.llvm_module.clone())
.map_err(|e| CodeGenerationError::ModuleLinkerError(e.to_string()))?;

let target_data = self.db.target_data();
let type_context = IrTypeContext {
context: &self.assembly_module.get_context(),
target_data: target_data.as_ref(),
struct_types: Default::default(),
};

let value_context = IrValueContext {
type_context: &type_context,
context: type_context.context,
module: &self.assembly_module,
};

// Generate the `get_info` method.
symbols::gen_reflection_ir(
self.db,
&self.assembly_module,
&value_context,
&file.api,
&group_ir.dispatch_table,
&group_ir.type_table,
Expand Down Expand Up @@ -202,86 +214,6 @@ fn optimize_module(module: &Module, optimization_lvl: OptimizationLevel) {
module_pass_manager.run_on(module);
}

/// Intern a string by constructing a global value. Looks something like this:
/// ```c
/// const char[] GLOBAL_ = "str";
/// ```
pub(crate) fn intern_string(module: &Module, string: &str, name: &str) -> PointerValue {
let value = module.get_context().const_string(string, true);
gen_global(module, &value, name).as_pointer_value()
}

/// Construct a global from the specified value
pub(crate) fn gen_global(module: &Module, value: &dyn BasicValue, name: &str) -> GlobalValue {
let global = module.add_global(value.as_basic_value_enum().get_type(), None, name);
global.set_linkage(Linkage::Private);
global.set_constant(true);
global.set_unnamed_address(UnnamedAddress::Global);
global.set_initializer(value);
global
}

/// Generates a global array from the specified list of strings
pub(crate) fn gen_string_array(
module: &Module,
strings: impl Iterator<Item = String>,
name: &str,
) -> PointerValue {
let str_type = module.get_context().i8_type().ptr_type(AddressSpace::Const);

let mut strings = strings.peekable();
if strings.peek().is_none() {
str_type.ptr_type(AddressSpace::Const).const_null()
} else {
let strings = strings
.map(|s| intern_string(module, &s, name))
.collect::<Vec<PointerValue>>();

let strings_ir = str_type.const_array(&strings);
gen_global(module, &strings_ir, "").as_pointer_value()
}
}

/// Generates a global array from the specified list of struct pointers
pub(crate) fn gen_struct_ptr_array(
module: &Module,
ir_type: StructType,
ptrs: &[PointerValue],
name: &str,
) -> PointerValue {
if ptrs.is_empty() {
ir_type
.ptr_type(AddressSpace::Const)
.ptr_type(AddressSpace::Const)
.const_null()
} else {
let ptr_array_ir = ir_type.ptr_type(AddressSpace::Const).const_array(&ptrs);

gen_global(module, &ptr_array_ir, name).as_pointer_value()
}
}

/// Generates a global array from the specified list of integers
pub(crate) fn gen_u16_array(
module: &Module,
integers: impl Iterator<Item = u64>,
name: &str,
) -> PointerValue {
let u16_type = module.get_context().i16_type();

let mut integers = integers.peekable();
if integers.peek().is_none() {
u16_type.ptr_type(AddressSpace::Const).const_null()
} else {
let integers = integers
.map(|i| u16_type.const_int(i, false))
.collect::<Vec<IntValue>>();

let array_ir = u16_type.const_array(&integers);
gen_global(module, &array_ir, name).as_pointer_value()
}
}

/// Create an inkwell TargetData from the target in the database
pub(crate) fn target_data_query(db: &impl IrDatabase) -> Arc<TargetData> {
Arc::new(TargetData::create(&db.target().data_layout))
Expand Down
Loading

0 comments on commit 9f4c8d7

Please sign in to comment.