Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions compiler/hash-abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! and to be able to call functions from other languages, but to also provide
//! information to code generation backends about how values are represented.

use hash_ir::ty::ReprTyId;
use hash_repr::{LayoutId, TyInfo};
use hash_storage::{new_store_key, store::statics::StoreId};
use hash_target::{
Expand Down Expand Up @@ -51,6 +52,9 @@ new_store_key!(pub FnAbiId, derives = Debug);
/// them)?
#[derive(Debug, Clone)]
pub struct FnAbi {
/// The ID of the function ABI if any.
pub ty: ReprTyId,

/// All the types of the arguments in order, and how they should
/// be passed to the function (as per convention).
pub args: Box<[ArgAbi]>,
Expand Down
18 changes: 3 additions & 15 deletions compiler/hash-codegen-llvm/src/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ use hash_codegen::{
target::{HasTarget, Target},
traits::{BackendTypes, HasCtxMethods},
};
use hash_ir::{
IrCtx,
ty::{InstanceId, ReprTyId, VariantIdx},
};
use hash_ir::{IrCtx, ty::ReprTyId};
use hash_pipeline::settings::CompilerSettings;
use hash_source::constant::AllocId;
use hash_utils::fxhash::FxHashMap;
Expand All @@ -24,8 +21,6 @@ use llvm::{
values::FunctionValue,
};

use crate::translation::ty::TyMemoryRemap;

/// The [CodeGenCtx] is used a context for converting Hash IR into LLVM IR. It
/// stores references to all of the required information about the IR, as well
/// as several stores in order to reduce the amount of work that is required to
Expand Down Expand Up @@ -59,15 +54,9 @@ pub struct CodeGenCtx<'b, 'm> {
/// of pointers and pointer offsets.
pub size_ty: llvm::types::IntType<'m>,

/// A mapping between [InstanceId]s to [FunctionValue]s in order
/// A mapping between [ReprTyId]s to [FunctionValue]s in order
/// to avoid re-generating declaring instance references.
pub(crate) instances: RefCell<FxHashMap<InstanceId, llvm::values::FunctionValue<'m>>>,

/// A collection of [TyMemoryRemap]s that have occurred for
/// all of the types that have been translated. Additionally, this is used
/// as a cache to avoid re-lowering [ReprTyId]s into the equivalent
/// LLVM types.
pub(crate) ty_remaps: RefCell<FxHashMap<(ReprTyId, Option<VariantIdx>), TyMemoryRemap<'m>>>,
pub(crate) instances: RefCell<FxHashMap<ReprTyId, llvm::values::FunctionValue<'m>>>,

/// A map which stores the created [AnyValueEnum]s for the constant
/// strings [InternedStr] that have been created.
Expand Down Expand Up @@ -111,7 +100,6 @@ impl<'b, 'm> CodeGenCtx<'b, 'm> {
symbol_counter: Cell::new(0),
size_ty,
instances: RefCell::new(FxHashMap::default()),
ty_remaps: RefCell::new(FxHashMap::default()),
str_consts: RefCell::new(FxHashMap::default()),
global_consts: RefCell::new(FxHashMap::default()),
intrinsics: RefCell::new(FxHashMap::default()),
Expand Down
17 changes: 9 additions & 8 deletions compiler/hash-codegen-llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,16 @@ impl<'b, 'm> LLVMBackend<'b> {
}

// Get the instance of the function.
let instance = body.metadata().ty().borrow().as_instance();
let ty = body.metadata().ty();
let instance = ty.borrow().as_instance();

// So, we create the mangled symbol name, and then call `predefine()` which
// should create the function ABI from the instance, with the correct
// attributes and linkage, etc.
let symbol_name = compute_symbol_name(instance);

let abis = self.codegen_storage.abis();
let abi = abis.create_fn_abi_from_instance(ctx, instance);
let abi = abis.create_fn_abi_from_ty(ctx, ty);

abis.map_fast(abi, |abi| {
ctx.predefine_fn(instance, symbol_name.as_str(), abi);
Expand All @@ -252,19 +253,19 @@ impl<'b, 'm> LLVMBackend<'b> {
continue;
}

// Get the instance of the function.
let instance = body.metadata().ty().borrow().as_instance();

// @@ErrorHandling: we should be able to handle the error here
codegen_body::<LLVMBuilder>(instance, body, ctx).unwrap();
codegen_body::<LLVMBuilder>(body, ctx).unwrap();

// Check if we should dump the generated LLVM IR
let ty = body.metadata().ty();
let instance = ty.borrow().as_instance();

if instance.borrow().has_attr(attrs::DUMP_LLVM_IR) {
// @@Messaging
// @@Messaging§
log::info!(
"LLVM IR for function {}\n{}",
body.meta.name(),
ctx.get_fn(instance).print_to_string().to_string()
ctx.get_fn(ty).print_to_string().to_string()
);
}
}
Expand Down
54 changes: 3 additions & 51 deletions compiler/hash-codegen-llvm/src/translation/layouts.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
//! Implements all of the required methods for computing the layouts of types.

use hash_codegen::{
repr::{Layout, LayoutShape, TyInfo, Variants},
repr::{Layout, TyInfo},
target::abi::AbiRepresentation,
traits::layout::LayoutMethods,
};
use hash_ir::ty::ReprTyId;
use hash_storage::store::statics::StoreId;

use super::{LLVMBuilder, ty::TyMemoryRemap};
use super::LLVMBuilder;
use crate::ctx::CodeGenCtx;

impl<'b> LayoutMethods<'b> for CodeGenCtx<'b, '_> {
fn backend_field_index(&self, info: TyInfo, index: usize) -> u64 {
info.layout.map(|layout| layout.llvm_field_index(self, info.ty, index))
}

fn is_backend_immediate(&self, info: TyInfo) -> bool {
info.layout.map(|layout| layout.is_llvm_immediate())
}
Expand All @@ -26,10 +21,6 @@ impl<'b> LayoutMethods<'b> for CodeGenCtx<'b, '_> {
}

impl<'b> LayoutMethods<'b> for LLVMBuilder<'_, 'b, '_> {
fn backend_field_index(&self, info: TyInfo, index: usize) -> u64 {
self.ctx.backend_field_index(info, index)
}

fn is_backend_immediate(&self, ty: TyInfo) -> bool {
self.ctx.is_backend_immediate(ty)
}
Expand All @@ -40,14 +31,11 @@ impl<'b> LayoutMethods<'b> for LLVMBuilder<'_, 'b, '_> {
}

pub trait ExtendedLayoutMethods<'m> {
/// Compute the field index from the backend specific type.
fn llvm_field_index(&self, cx: &CodeGenCtx<'_, 'm>, ty: ReprTyId, index: usize) -> u64;

/// Check if this is type is represented as an immediate value.
fn is_llvm_immediate(&self) -> bool;

/// Returns true if this [Layout] ABI is represented as is a
/// [`AbiRepresentation::Pair(..)`]
/// [`AbiRepresentation::Pair`]
fn is_llvm_scalar_pair(&self) -> bool;
}

Expand All @@ -63,40 +51,4 @@ impl<'m> ExtendedLayoutMethods<'m> for &Layout {
fn is_llvm_scalar_pair(&self) -> bool {
matches!(self.abi, AbiRepresentation::Pair(..))
}

fn llvm_field_index(&self, ctx: &CodeGenCtx<'_, 'm>, ty: ReprTyId, index: usize) -> u64 {
// Field index of scalar and scalar pairs is not applicable since
// it is handled else where.
match self.abi {
AbiRepresentation::Scalar(_) | AbiRepresentation::Pair(..) => {
panic!("cannot get field index of scalar or scalar pair")
}
_ => {}
};

match self.shape {
LayoutShape::Primitive | LayoutShape::Union { .. } => {
panic!("cannot get field index of primitive or union")
}
LayoutShape::Array { .. } => index as u64,

// Here, we have to rely on the re-mapped version of the layout since
// we had to adjust it to account for all of the padding that was added
// to the struct/aggregate.
LayoutShape::Aggregate { .. } => {
let variant_index = match self.variants {
Variants::Single { index } => Some(index),
Variants::Multiple { .. } => None,
};

match ctx.ty_remaps.borrow().get(&(ty, variant_index)) {
Some(TyMemoryRemap { remap: Some(remap), .. }) => remap[index] as u64,
Some(TyMemoryRemap { remap: None, .. }) => {
self.shape.memory_index(index) as u64
}
None => panic!("cannot find remapped layout for `{}`", ty),
}
}
}
}
}
27 changes: 14 additions & 13 deletions compiler/hash-codegen-llvm/src/translation/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use hash_codegen::{
target::HasTarget,
traits::{HasCtxMethods, misc::MiscBuilderMethods, ty::TypeBuilderMethods},
};
use hash_ir::ty::{InstanceHelpers, InstanceId};
use hash_ir::ty::{InstanceHelpers, InstanceId, ReprTyId};
use hash_storage::store::{Store, statics::StoreId};
use inkwell::{
GlobalVisibility,
Expand All @@ -20,19 +20,20 @@ use crate::ctx::CodeGenCtx;

impl<'m> CodeGenCtx<'_, 'm> {
/// Generate code for a reference to a function or method item. The
/// [Instance] specifies the function reference to generate, and any
/// [InstanceId] specifies the function reference to generate, and any
/// attributes that need to be applied to the function. If the function
/// has already been generated, a reference will be returned from the
/// cache.
pub fn get_fn_or_create_ref(&self, instance: InstanceId) -> FunctionValue<'m> {
pub fn get_fn_or_create_ref(&self, ty: ReprTyId) -> FunctionValue<'m> {
// First check if we have already created the function reference...
if let Some(fn_val) = self.instances.borrow().get(&instance) {
if let Some(fn_val) = self.instances.borrow().get(&ty) {
return *fn_val;
}

let instance = ty.borrow().as_instance();
let name = compute_symbol_name(instance);
let abis = self.cg_ctx().abis();
let fn_abi = abis.create_fn_abi_from_instance(self, instance);
let fn_abi = abis.create_fn_abi_from_ty(self, ty);

// See if this item has already been declared in the module
let func = if let Some(func) = self.module.get_function(name.as_str()) {
Expand All @@ -55,25 +56,25 @@ impl<'m> CodeGenCtx<'_, 'm> {

// We insert the function into the cache so that we can
// reference it later on...
self.instances.borrow_mut().insert(instance, func);
self.instances.borrow_mut().insert(ty, func);

func
}
}

impl<'b> MiscBuilderMethods<'b> for CodeGenCtx<'b, '_> {
fn get_fn(&self, instance: InstanceId) -> Self::Function {
self.get_fn_or_create_ref(instance)
fn get_fn(&self, ty: ReprTyId) -> Self::Function {
self.get_fn_or_create_ref(ty)
}

fn get_fn_ptr(&self, instance: InstanceId) -> Self::Value {
self.get_fn_or_create_ref(instance).as_any_value_enum()
fn get_fn_ptr(&self, ty: ReprTyId) -> Self::Value {
self.get_fn_or_create_ref(ty).as_any_value_enum()
}

fn get_fn_addr(&self, instance: InstanceId) -> Self::Value {
fn get_fn_addr(&self, ty: ReprTyId) -> Self::Value {
// @@Inkwell: PointerValue(..).as_any_value_enum() is bugged
AnyValueEnum::PointerValue(
self.get_fn_or_create_ref(instance).as_global_value().as_pointer_value(),
self.get_fn_or_create_ref(ty).as_global_value().as_pointer_value(),
)
}

Expand Down Expand Up @@ -117,6 +118,6 @@ impl<'b> MiscBuilderMethods<'b> for CodeGenCtx<'b, '_> {

// We insert the function into the cache so that we can
// reference it later on...
self.instances.borrow_mut().insert(instance, decl);
self.instances.borrow_mut().insert(fn_abi.ty, decl);
}
}
2 changes: 1 addition & 1 deletion compiler/hash-codegen-llvm/src/translation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub(crate) const EMPTY_NAME: *const c_char = EMPTY_C_STR.as_ptr();
/// A [Builder] is defined as being a context that is used to implement
/// all of the specified builder methods.
pub struct LLVMBuilder<'a, 'b, 'm> {
/// The actual InkWell builder
/// The actual Inkwell builder.
pub(crate) builder: inkwell::builder::Builder<'m>,

/// The context for the builder.
Expand Down
51 changes: 7 additions & 44 deletions compiler/hash-codegen-llvm/src/translation/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,23 +251,6 @@ impl<'b> TypeBuilderMethods<'b> for CodeGenCtx<'b, '_> {
}
}

/// A [TyMemoryRemap] is a type that is used to represent the occurred
/// memory field re-mapping that occurs when lowering a type to LLVM.
/// This re-mapping originates from the fact that "padding" within types
/// now becomes a concrete type, and thus the memory layout of the type
/// changes if padding slots are inserted. If the type had any re-maps,
/// then the [TyMemoryRemap] will contain a `remap` field with the
/// new memory to source field mapping.
pub(crate) struct TyMemoryRemap<'m> {
/// The lowered type.
pub ty: AnyTypeEnum<'m>,

/// If the type was re-mapped, this is a reference
/// to the new memory map which should be used over the
/// one that is stored in the [LayoutShape] of a [Layout].
pub remap: Option<SmallVec<[u32; 4]>>,
}

/// Define a trait that provides additional methods on the [CodeGenCtx]
/// for computing types as LLVM types, and various other related LLVM
/// specific type utilities.
Expand Down Expand Up @@ -296,20 +279,7 @@ pub(crate) trait ExtendedTyBuilderMethods<'m> {

impl<'m> ExtendedTyBuilderMethods<'m> for TyInfo {
fn llvm_ty(&self, ctx: &CodeGenCtx<'_, 'm>) -> llvm::types::AnyTypeEnum<'m> {
let (abi, variant_index) = self.layout.map(|layout| {
let variant_index = match &layout.variants {
Variants::Single { index } => Some(*index),
_ => None,
};

(layout.abi, variant_index)
});

// Check the cache if we have already computed the lowered type
// for this ir-type.
if let Some(ty_remap) = ctx.ty_remaps.borrow().get(&(self.ty, variant_index)) {
return ty_remap.ty;
}
let abi = self.layout.map(|layout| layout.abi);

match abi {
AbiRepresentation::Scalar(scalar) => self.scalar_llvm_type_at(ctx, scalar),
Expand Down Expand Up @@ -386,9 +356,9 @@ impl<'m> ExtendedTyBuilderMethods<'m> for TyInfo {
ctx.type_array(field_ty, elements)
}
LayoutShape::Aggregate { .. } => {
let (ty, field_remapping) = match name {
match name {
Some(ref name) => {
let (fields, packed, new_field_remapping) =
let (fields, packed, _) =
create_and_pad_struct_fields_from_layout(
ctx, *self, layout,
);
Expand All @@ -404,24 +374,17 @@ impl<'m> ExtendedTyBuilderMethods<'m> for TyInfo {
.collect::<Vec<_>>();

ty.set_body(&fields, packed);
(ty.into(), new_field_remapping)
ty.into()
}
None => {
let (fields, packed, new_field_remapping) =
let (fields, packed, _) =
create_and_pad_struct_fields_from_layout(
ctx, *self, layout,
);

(ctx.type_struct(&fields, packed), new_field_remapping)
ctx.type_struct(&fields, packed)
}
};

ctx.ty_remaps.borrow_mut().insert(
(self.ty, variant_index),
TyMemoryRemap { ty, remap: field_remapping },
);

ty
}
}
}
})
Expand Down
Loading