Skip to content

Commit

Permalink
Fix llvm GEP error
Browse files Browse the repository at this point in the history
  • Loading branch information
jfecher committed Oct 19, 2023
1 parent 7b7ad7c commit 5a866f6
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 35 deletions.
9 changes: 7 additions & 2 deletions src/hir/decision_tree_monomorphisation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl<'c> Context<'c> {
use hir::types::*;
match typ {
Type::Primitive(PrimitiveType::Integer(_)) => value.into(),
Type::Tuple(_) => Self::extract(value.into(), 0),
Type::Tuple(fields) => Self::extract(value.into(), 0, fields[0].clone()),
_ => unreachable!(),
}
}
Expand Down Expand Up @@ -177,11 +177,16 @@ impl<'c> Context<'c> {
fmap(case.fields.iter().enumerate(), |(i, field_aliases)| {
let field_index = start_index + i as u32;
let field_variable_id = self.next_unique_id();
let mut monomorphized_field_type = None;

for field_alias in field_aliases {
let alias_type = self.cache[*field_alias].typ.as_ref().unwrap().as_monotype();
let field_type = self.follow_all_bindings(alias_type);

if monomorphized_field_type.is_none() {
monomorphized_field_type = Some(self.convert_type(&field_type));
}

let monomorphized_field_type = Rc::new(self.convert_type(&field_type));
let field_variable = hir::Variable::new(field_variable_id, monomorphized_field_type);

Expand All @@ -191,7 +196,7 @@ impl<'c> Context<'c> {

hir::Definition {
variable: field_variable_id,
expr: Box::new(Self::extract(variant_variable.clone().into(), field_index)),
expr: Box::new(Self::extract(variant_variable.clone().into(), field_index, monomorphized_field_type.unwrap())),
name: None,
}
})
Expand Down
1 change: 1 addition & 0 deletions src/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ pub struct Assignment {
pub struct MemberAccess {
pub lhs: Box<Ast>,
pub member_index: u32,
pub typ: Type,
}

#[derive(Debug, Clone)]
Expand Down
31 changes: 20 additions & 11 deletions src/hir/monomorphisation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,8 @@ impl<'c> Context<'c> {
for (i, arg_pattern) in call.args.iter().enumerate() {
let arg_type = self.follow_all_bindings(arg_pattern.get_type().unwrap());

let extract = Self::extract(variable.clone().into(), i as u32);
let extract_result_type = self.convert_type(&arg_type);
let extract = Self::extract(variable.clone().into(), i as u32, extract_result_type);

let (definition, id) = self.fresh_definition(extract, None);
definitions.push(definition);
Expand Down Expand Up @@ -1211,16 +1212,17 @@ impl<'c> Context<'c> {
env.clone()
} else {
let param_ast: hir::Ast = env.clone().into();
let extract_var_in_env = Self::extract(param_ast.clone(), 0);
let extract_rest_of_env = Self::extract(param_ast, 1);
env_type = Self::extract_second_type(env_type);

let extract_var_in_env = Self::extract(param_ast.clone(), 0, self.convert_type(&typ));
let extract_rest_of_env = Self::extract(param_ast, 1, env_type.clone());

let (definition, definition_id) = self.fresh_definition(extract_var_in_env, Some(name.clone()));
let (rest_env_def, rest_env_var) = self.fresh_definition(extract_rest_of_env, None);

definitions.push(definition);
definitions.push(rest_env_def);

env_type = Self::extract_second_type(env_type);
env = hir::Variable { definition_id: rest_env_var, definition: None, name: None, typ: Rc::new(env_type.clone()) };

let monomorphized_type = Rc::new(self.convert_type(&typ));
Expand Down Expand Up @@ -1412,6 +1414,11 @@ impl<'c> Context<'c> {

match function_type {
Type::Tuple(mut params) => {
// Expect (function, env)
assert_eq!(params.len(), 2);

let env_type = params.pop().unwrap();

let function_type = match params.swap_remove(0) {
Type::Function(f) => f,
_ => unreachable!(),
Expand All @@ -1420,10 +1427,10 @@ impl<'c> Context<'c> {
// Extract the function from the closure
let (function_definition, id) = self.fresh_definition(function, None);
let typ = Type::Function(function_type.clone());
let function_variable = hir::Ast::Variable(hir::Variable::new(id, Rc::new(typ)));
let function_variable = hir::Ast::Variable(hir::Variable::new(id, Rc::new(typ.clone())));

let function = Box::new(Self::extract(function_variable.clone(), 0));
let environment = Self::extract(function_variable, 1);
let function = Box::new(Self::extract(function_variable.clone(), 0, typ));
let environment = Self::extract(function_variable, 1, env_type);
args.push(environment);

hir::Ast::Sequence(hir::Sequence {
Expand Down Expand Up @@ -1555,6 +1562,8 @@ impl<'c> Context<'c> {
_ => None,
};

let result_type = self.convert_type(member_access.typ.as_ref().unwrap());

// If our collection type is a ref we do a ptr offset instead of a direct access
match (ref_type, member_access.is_offset) {
(Some(elem_type), true) => {
Expand All @@ -1563,11 +1572,11 @@ impl<'c> Context<'c> {
},
(Some(elem_type), false) => {
let lhs = hir::Ast::Builtin(hir::Builtin::Deref(Box::new(lhs), elem_type));
Self::extract(lhs, index)
Self::extract(lhs, index, result_type)
},
_ => {
assert!(!member_access.is_offset);
Self::extract(lhs, index)
Self::extract(lhs, index, result_type)
},
}
}
Expand All @@ -1582,7 +1591,7 @@ impl<'c> Context<'c> {
hir::Ast::Assignment(hir::Assignment { lhs: Box::new(lhs), rhs: Box::new(self.monomorphise(&assignment.rhs)) })
}

pub fn extract(ast: hir::Ast, member_index: u32) -> hir::Ast {
pub fn extract(ast: hir::Ast, member_index: u32, result_type: Type) -> hir::Ast {
use hir::{
Ast,
Builtin::{Deref, Offset},
Expand Down Expand Up @@ -1616,7 +1625,7 @@ impl<'c> Context<'c> {
},
other => {
let lhs = Box::new(other);
Ast::MemberAccess(hir::MemberAccess { lhs, member_index })
Ast::MemberAccess(hir::MemberAccess { lhs, member_index, typ: result_type })
},
}
}
Expand Down
31 changes: 10 additions & 21 deletions src/llvm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ impl<'g> Generator<'g> {

self.builder.build_store(alloca, value).expect("Could not create store during cast");

let target_type = target_type.ptr_type(AddressSpace::default());
let cast = self.builder.build_pointer_cast(alloca, target_type, "cast")
let target_pointer_type = target_type.ptr_type(AddressSpace::default());
let cast = self.builder.build_pointer_cast(alloca, target_pointer_type, "cast")
.expect("Error creating pointer cast");

self.builder.build_load(target_type, cast, "union_cast")
Expand Down Expand Up @@ -451,32 +451,19 @@ impl<'g> Generator<'g> {

/// Creates a GEP instruction and Load which emulate a single Extract instruction but
/// delays the Load as long as possible to make assigning to this as an l-value easier later on.
fn gep_at_index(&mut self, load: BasicValueEnum<'g>, field_index: u32, field_name: &str) -> BasicValueEnum<'g> {
fn gep_at_index(&mut self, load: BasicValueEnum<'g>, field_index: u32, field_type: &hir::Type, field_name: &str) -> BasicValueEnum<'g> {
let instruction = load.as_instruction_value().unwrap();
assert_eq!(instruction.get_opcode(), InstructionOpcode::Load);

let element_type = Self::any_type_to_basic_type(instruction.get_type());
let pointer = instruction.get_operand(0).unwrap().left().unwrap().into_pointer_value();

let gep = self.builder.build_struct_gep(element_type, pointer, field_index, field_name)
.expect("Error creating struct GEP");
let gep = self.builder.build_struct_gep(load.get_type(), pointer, field_index, field_name)
.expect("Error creating GEP");

self.builder.build_load(element_type, gep, field_name)
let field_type = self.convert_type(field_type);
self.builder.build_load(field_type, gep, field_name)
.expect("Error creating load")
}

fn any_type_to_basic_type(typ: inkwell::types::AnyTypeEnum) -> BasicTypeEnum {
match typ {
inkwell::types::AnyTypeEnum::ArrayType(typ) => BasicTypeEnum::ArrayType(typ),
inkwell::types::AnyTypeEnum::FloatType(typ) => BasicTypeEnum::FloatType(typ),
inkwell::types::AnyTypeEnum::IntType(typ) => BasicTypeEnum::IntType(typ),
inkwell::types::AnyTypeEnum::PointerType(typ) => BasicTypeEnum::PointerType(typ),
inkwell::types::AnyTypeEnum::StructType(typ) => BasicTypeEnum::StructType(typ),
inkwell::types::AnyTypeEnum::VectorType(typ) => BasicTypeEnum::VectorType(typ),
inkwell::types::AnyTypeEnum::FunctionType(typ) => panic!("Cannot convert function type {} to basic typ", typ),
inkwell::types::AnyTypeEnum::VoidType(_) => panic!("Cannot convert void type to basic typ"),
}
}
}

trait CodeGen<'g> {
Expand Down Expand Up @@ -691,7 +678,9 @@ impl<'g> CodeGen<'g> for hir::MemberAccess {
// This will delay the load as long as possible which makes this easier to detect
// as a valid l-value in hir::Assignment::codegen.
match lhs.as_instruction_value().map(|instr| instr.get_opcode()) {
Some(InstructionOpcode::Load) => generator.gep_at_index(lhs, index, ""),
Some(InstructionOpcode::Load) => {
generator.gep_at_index(lhs, index, &self.typ, "")
}
_ => {
let collection = lhs.into_struct_value();
generator.builder.build_extract_value(collection, index, "").unwrap()
Expand Down
2 changes: 1 addition & 1 deletion stdlib/prelude.an
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ impl Cast (Int a) String given Div (Int a), Mod (Int a), Cmp (Int a) with
cast i =
abs, sign_off = if i < 0 then (i * -1, 1) else (i, 0)
len = loop abs (cmp = 10) ->
next = cmp * 10 // Here to check for overflow
next = cmp * 10 // Need to check for overflow here
if abs >= cmp and next > cmp
then 1 + recur abs next
else 1
Expand Down

0 comments on commit 5a866f6

Please sign in to comment.