Skip to content

Commit

Permalink
codegen: Propagate errors better when creating section names
Browse files Browse the repository at this point in the history
  • Loading branch information
CohenArthur committed Jun 11, 2024
1 parent 7ad554f commit 735e873
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 16 deletions.
22 changes: 13 additions & 9 deletions src/codegen/generators/pou_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,33 +153,37 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
PouGenerator { llvm, index, annotations, llvm_index }
}

fn mangle_function(&self, implementation: &ImplementationIndexEntry) -> String {
fn mangle_function(&self, implementation: &ImplementationIndexEntry) -> Result<String, Diagnostic> {
let ctx = SectionMangler::function(implementation.get_call_name());

let params = self.index.get_declared_parameters(implementation.get_call_name());

let ctx = params.into_iter().fold(ctx, |ctx, param| {
// FIXME: Can we unwrap here?
let ctx = params.into_iter().try_fold(ctx, |ctx, param| -> Result<SectionMangler, Diagnostic> {
let ty = section_names::mangle_type(
self.index,
self.index.get_effective_type_by_name(&param.data_type_name).unwrap(),
);
self.index.get_effective_type_by_name(&param.data_type_name)?,
)?;
let parameter = match param.argument_type {
// TODO: We need to handle the `VariableType` enum as well - this describes the mode of
// argument passing, e.g. inout
index::ArgumentType::ByVal(_) => FunctionArgument::ByValue(ty),
index::ArgumentType::ByRef(_) => FunctionArgument::ByRef(ty),
};

ctx.with_parameter(parameter)
});
Ok(ctx.with_parameter(parameter))
})?;

let return_ty = self
.index
.find_return_type(implementation.get_type_name())
.map(|ty| section_names::mangle_type(self.index, ty));

ctx.with_return_type(return_ty).mangle()
let ctx = match return_ty {
Some(rty) => ctx.with_return_type(rty?),
None => ctx,
};

Ok(ctx.mangle())
}

/// generates an empty llvm function for the given implementation, including all parameters and the return type
Expand Down Expand Up @@ -281,7 +285,7 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {

let curr_f = module.add_function(implementation.get_call_name(), function_declaration, None);

let section_name = self.mangle_function(implementation);
let section_name = self.mangle_function(implementation)?;
curr_f.set_section(Some(&section_name));

let pou_name = implementation.get_call_name();
Expand Down
11 changes: 7 additions & 4 deletions src/codegen/generators/section_names.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use crate::index::Index;
use crate::typesystem::{self, DataTypeInformation, StringEncoding, TypeSize};
use plc_diagnostics::diagnostics::Diagnostic;
use section_mangler::{StringEncoding as SectionStringEncoding, Type};

pub fn mangle_type(index: &Index, ty: &typesystem::DataType) -> section_mangler::Type {
pub fn mangle_type(index: &Index, ty: &typesystem::DataType) -> Result<section_mangler::Type, Diagnostic> {
// TODO: This is a bit ugly because we keep dereferencing references to Copy types like
// bool, u32, etc, because `DataTypeInformation::Pointer` keeps a `String` which is not
// Copy. the alternative is for section_mangle::Type to keep references everywhere, and
// have a lifetime generic parameter, e.g. `section_mangler::Type<'a>` - which is also
// annoying.
match ty.get_type_information() {
let mangled = match ty.get_type_information() {
DataTypeInformation::Void => Type::Void,
DataTypeInformation::Integer { signed, size, semantic_size, .. } => {
Type::Integer { signed: *signed, size: *size, semantic_size: *semantic_size }
Expand All @@ -23,11 +24,13 @@ pub fn mangle_type(index: &Index, ty: &typesystem::DataType) -> section_mangler:
Type::String { size: *size as usize, encoding }
}
DataTypeInformation::Pointer { inner_type_name, .. } => Type::Pointer {
inner: Box::new(mangle_type(index, index.get_effective_type_by_name(inner_type_name).unwrap())),
inner: Box::new(mangle_type(index, index.get_effective_type_by_name(inner_type_name)?)?),
},
// FIXME: For now, encode all unknown types as "void" since this is not required for
// execution. Not doing so (and doing an `unreachable!()` for example) obviously causes
// failures, because complex types are already implemented in the compiler.
_ => Type::Void,
}
};

Ok(mangled)
}
5 changes: 2 additions & 3 deletions src/codegen/generators/variable_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,10 @@ impl<'ctx, 'b> VariableGenerator<'ctx, 'b> {

let section = section_mangler::SectionMangler::variable(
global_variable.get_name(),
// FIXME: Can we unwrap here?
section_names::mangle_type(
self.global_index,
self.global_index.get_effective_type_by_name(global_variable.get_type_name()).unwrap(),
),
self.global_index.get_effective_type_by_name(global_variable.get_type_name())?,
)?,
)
.mangle();

Expand Down

0 comments on commit 735e873

Please sign in to comment.