mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-22 16:08:24 +00:00
padding
This commit is contained in:
parent
1dfad6e1b6
commit
53f6f9e36d
10
programs/struct.ed
Normal file
10
programs/struct.ed
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
|
||||||
|
struct Hello {
|
||||||
|
y: i16,
|
||||||
|
x: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(x: Hello) {
|
||||||
|
return;
|
||||||
|
}
|
|
@ -9,9 +9,12 @@ use inkwell::{
|
||||||
builder::Builder,
|
builder::Builder,
|
||||||
context::Context,
|
context::Context,
|
||||||
module::Module,
|
module::Module,
|
||||||
|
targets::{
|
||||||
|
CodeModel, InitializationConfig, RelocMode, Target, TargetData, TargetMachine, TargetTriple,
|
||||||
|
},
|
||||||
types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, StructType},
|
types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, StructType},
|
||||||
values::{BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue},
|
values::{BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue},
|
||||||
IntPredicate,
|
IntPredicate, OptimizationLevel,
|
||||||
};
|
};
|
||||||
use itertools::{Either, Itertools};
|
use itertools::{Either, Itertools};
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
@ -43,6 +46,7 @@ pub struct CodeGen<'ctx> {
|
||||||
functions: HashMap<String, Function>,
|
functions: HashMap<String, Function>,
|
||||||
_program: ProgramData,
|
_program: ProgramData,
|
||||||
ast: ast::Program,
|
ast: ast::Program,
|
||||||
|
target_machine: TargetMachine,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -72,6 +76,25 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
ast: ast::Program,
|
ast: ast::Program,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let module = context.create_module(module_name);
|
let module = context.create_module(module_name);
|
||||||
|
Target::initialize_native(&InitializationConfig::default())
|
||||||
|
.expect("Failed to initialize native target");
|
||||||
|
let triple = TargetMachine::get_default_triple();
|
||||||
|
|
||||||
|
// https://thedan64.github.io/inkwell/inkwell/targets/struct.TargetMachine.html#method.write_to_memory_buffer
|
||||||
|
let opt = OptimizationLevel::Default;
|
||||||
|
let reloc = RelocMode::Default;
|
||||||
|
let model = CodeModel::Default;
|
||||||
|
let target = Target::from_name("x86-64").unwrap();
|
||||||
|
let target_machine = target
|
||||||
|
.create_target_machine(
|
||||||
|
&triple,
|
||||||
|
"x86-64",
|
||||||
|
TargetMachine::get_host_cpu_features().to_str()?,
|
||||||
|
opt,
|
||||||
|
reloc,
|
||||||
|
model,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let codegen = CodeGen {
|
let codegen = CodeGen {
|
||||||
context,
|
context,
|
||||||
|
@ -81,6 +104,7 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
ast,
|
ast,
|
||||||
struct_types: HashMap::new(),
|
struct_types: HashMap::new(),
|
||||||
functions: HashMap::new(),
|
functions: HashMap::new(),
|
||||||
|
target_machine,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(codegen)
|
Ok(codegen)
|
||||||
|
@ -93,16 +117,18 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
|
|
||||||
// todo fix the grammar so top level statements are only functions and static vars.
|
// todo fix the grammar so top level statements are only functions and static vars.
|
||||||
|
|
||||||
|
let target_data = self.target_machine.get_target_data();
|
||||||
|
|
||||||
// create types
|
// create types
|
||||||
for statement in &self.ast.statements {
|
for statement in &self.ast.statements {
|
||||||
if let Statement::Struct(s) = &statement.value {
|
if let Statement::Struct(s) = &statement.value {
|
||||||
let mut fields = HashMap::new();
|
let mut fields = HashMap::new();
|
||||||
let mut field_types = vec![];
|
let mut field_types: Vec<(BasicTypeEnum<'_>, Option<usize>)> = vec![];
|
||||||
|
|
||||||
for (i, field) in s.fields.iter().enumerate() {
|
for (i, field) in s.fields.iter().enumerate() {
|
||||||
// todo: this doesnt handle out of order structs well
|
// todo: this doesnt handle out of order structs well
|
||||||
let ty = self.get_llvm_type(&field.field_type.value)?;
|
let ty = self.get_llvm_type(&field.field_type.value)?;
|
||||||
field_types.push(ty);
|
field_types.push((ty, Some(i)));
|
||||||
// todo: ensure alignment and padding here
|
// todo: ensure alignment and padding here
|
||||||
fields.insert(
|
fields.insert(
|
||||||
field.ident.value.clone(),
|
field.ident.value.clone(),
|
||||||
|
@ -110,7 +136,40 @@ impl<'ctx> CodeGen<'ctx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty = self.context.struct_type(&field_types, false);
|
field_types.sort_by(|a, b| {
|
||||||
|
target_data
|
||||||
|
.get_bit_size(&b.0)
|
||||||
|
.cmp(&target_data.get_bit_size(&a.0))
|
||||||
|
});
|
||||||
|
|
||||||
|
let total_byte_size: u32 = field_types
|
||||||
|
.iter()
|
||||||
|
.map(|x| (target_data.get_bit_size(&x.0) + 7) / 8)
|
||||||
|
.sum::<u64>()
|
||||||
|
.try_into()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if !total_byte_size.is_power_of_two() {
|
||||||
|
let next = total_byte_size.next_power_of_two();
|
||||||
|
let diff = next - total_byte_size;
|
||||||
|
let padding = self.context.i8_type().array_type(diff);
|
||||||
|
field_types.push((padding.as_basic_type_enum(), None))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (current_i, ty) in field_types.iter().enumerate() {
|
||||||
|
for field in fields.values_mut() {
|
||||||
|
if let Some(i) = ty.1 {
|
||||||
|
if i == field.0 {
|
||||||
|
field.0 = current_i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ty = self
|
||||||
|
.context
|
||||||
|
.struct_type(&field_types.into_iter().map(|x| x.0).collect_vec(), false);
|
||||||
|
|
||||||
let struct_type = StructTypeInfo { fields, ty };
|
let struct_type = StructTypeInfo { fields, ty };
|
||||||
struct_types.insert(s.name.value.clone(), struct_type);
|
struct_types.insert(s.name.value.clone(), struct_type);
|
||||||
|
|
Loading…
Reference in a new issue