Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial values on methods are passed correctly #1390

Merged
merged 78 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
ff773f6
feat: pipeline stages for lowering
ghaith Nov 20, 2024
e1a2759
feat: move pipelines to its own struct to make testing easier (wip)
ghaith Nov 20, 2024
b02bf45
wip - lowering
ghaith Nov 21, 2024
6f99387
fix single threaded linking tests
ghaith Nov 25, 2024
9ae7929
Add initial participant logic - wip
ghaith Nov 26, 2024
ca3fa79
Add codegen participant - wip
ghaith Nov 26, 2024
a595d1f
codegen pipeline done, tests fail
ghaith Nov 28, 2024
d61505a
codegen memory buffer
ghaith Dec 2, 2024
583c4d2
Revert "codegen memory buffer"
ghaith Dec 9, 2024
a1a0f40
Remove multi-target builds
ghaith Dec 9, 2024
deaa4cd
Merge remote-tracking branch 'origin/master' into oop_lowering
ghaith Dec 9, 2024
f25ac36
Remove unused steps, rename codegen to generate
ghaith Dec 9, 2024
fa2a24d
remove todos and dead code
ghaith Dec 10, 2024
4f65d5d
remove example
ghaith Dec 10, 2024
97cb6d0
feat: lowering for function calls
ghaith Dec 10, 2024
3ba29b3
Lower function calls with aggregates (wip)
ghaith Dec 11, 2024
c7e6ac8
wip - lowering
ghaith Dec 12, 2024
9d8f411
Merge remote-tracking branch 'origin/master' into method_returns
ghaith Dec 13, 2024
a94f6ef
add local variable annotation
ghaith Dec 13, 2024
d56e432
Merge remote-tracking branch 'origin/master' into method_returns
ghaith Dec 16, 2024
2274a42
wip: alloca in calls
ghaith Dec 16, 2024
6454b04
alloca in calls and condition-statements
mhasel Dec 16, 2024
3df9eca
Merge remote-tracking branch 'origin/master' into method_returns
ghaith Dec 16, 2024
4ade8b1
Add method tests
ghaith Dec 17, 2024
8a89241
Update cargo, re-enable libs
ghaith Dec 17, 2024
2c3215d
codegen wip
mhasel Dec 17, 2024
3e640ff
downcast annotationmap
mhasel Dec 17, 2024
093222f
codegen with tests, not yet working
ghaith Dec 18, 2024
7b309ed
revert test changes, remove init of aggregate returns
ghaith Dec 18, 2024
5105fc1
Fix the test runners to call lowering
ghaith Dec 19, 2024
c81d3cc
remove debug, accept insta
ghaith Dec 19, 2024
d86a23b
wip : fix generics
ghaith Dec 19, 2024
8185aaf
generics workaround, tests passing
mhasel Dec 20, 2024
25b8273
clippy
mhasel Dec 20, 2024
1a33f1f
Merge master
mhasel Dec 20, 2024
79811d2
add lit tests, add workaround for std test
ghaith Jan 8, 2025
e72b6fa
Merge branch 'master' into method_returns
mhasel Jan 8, 2025
0dc2923
nested calls in condition wip
mhasel Jan 9, 2025
eb43fb3
fix nested calls with complex return in condition
mhasel Jan 9, 2025
6c6ae3d
re-enable printing of ast
mhasel Jan 9, 2025
2fc76b0
fix aggr return calls in while and do while loops
mhasel Jan 9, 2025
c31e343
wip, still broken
ghaith Jan 10, 2025
5b7292e
Merge branch 'master' into method_returns
volsa Jan 10, 2025
3ce8564
Merge remote-tracking branch 'origin/master' into method_returns
ghaith Jan 13, 2025
5361d2a
fix the while/repeat conditions
ghaith Jan 13, 2025
8873278
Merge remote-tracking branch 'origin/master' into method_returns
ghaith Jan 13, 2025
a29ee20
add a codegen test that should fail with generic/string
ghaith Jan 14, 2025
150e2ee
push updated test
ghaith Jan 14, 2025
e975400
fix generic generation
ghaith Jan 14, 2025
d72ad53
fix a hint test
ghaith Jan 15, 2025
124c991
run formatter and cargo fix
ghaith Jan 15, 2025
a52b14e
Remove some commentend out code
ghaith Jan 15, 2025
761e32f
cleanup
mhasel Jan 15, 2025
0793210
fmt
mhasel Jan 15, 2025
bac1e46
remove obsolete code
mhasel Jan 15, 2025
1d9f02e
wip
mhasel Jan 15, 2025
728a055
fix init value, disable obsolete validation
ghaith Jan 16, 2025
4405fff
add failing test for string returns
ghaith Jan 16, 2025
2ff1f03
add codegen tests for the failing situation
ghaith Jan 16, 2025
31e0fa4
add lit command to xtask
mhasel Jan 16, 2025
ebc5395
Merge branch 'method_returns', remote-tracking branch 'origin' into i…
mhasel Jan 16, 2025
b409162
fix: VAR_OUTPUT in methods now behaves like functions
mhasel Jan 16, 2025
029d216
Ignore the array return as failing
ghaith Jan 17, 2025
424fcc1
Merge remote-tracking branch 'origin/method_returns' into initial_values
ghaith Jan 17, 2025
df0d5e9
ignore test due to known issue
ghaith Jan 17, 2025
8f02419
fix: if a method is called with explicit params, make sure the aggreg…
ghaith Jan 17, 2025
f289f86
Merge remote-tracking branch 'origin/method_returns' into initial_values
ghaith Jan 17, 2025
d614268
Merge remote-tracking branch 'origin/master' into method_returns
ghaith Jan 17, 2025
71b249e
fmt
ghaith Jan 17, 2025
16481a9
accept insta tests
ghaith Jan 17, 2025
bedbab0
fix debug test
ghaith Jan 20, 2025
269711a
fix comment, add var_output method lit test
mhasel Jan 20, 2025
aa383ad
Merge branch 'master' into method_returns
mhasel Jan 20, 2025
3f87142
Merge branch 'master' into initial_values
mhasel Jan 20, 2025
245a61e
Merge master
mhasel Jan 24, 2025
ec68f54
Merge remote-tracking branch 'origin/master' into method_returns
ghaith Jan 24, 2025
390be7a
Merge remote-tracking branch 'origin/method_returns' into initial_values
ghaith Jan 24, 2025
c1bd88b
Merge branch 'master' into initial_values
mhasel Jan 27, 2025
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: 1 addition & 1 deletion compiler/plc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ impl PouType {
}

pub fn is_function_or_init(&self) -> bool {
matches!(self, PouType::Function | PouType::Init | PouType::ProjectInit)
matches!(self, PouType::Function | PouType::Init | PouType::ProjectInit | PouType::Method { .. })
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ lazy_static! {
E046, Error, include_str!("./error_codes/E046.md"),
E047, Warning, include_str!("./error_codes/E047.md"), // VLAs are always by reference
E048, Error, include_str!("./error_codes/E048.md"),
E049, Error, include_str!("./error_codes/E049.md"),
E049, Warning, include_str!("./error_codes/E049.md"),
E050, Error, include_str!("./error_codes/E050.md"),
E051, Error, include_str!("./error_codes/E051.md"),
E052, Error, include_str!("./error_codes/E052.md"),
Expand Down
111 changes: 46 additions & 65 deletions src/codegen/generators/expression_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
// after the call we need to copy the values for assigned outputs
// this is only necessary for outputs defined as `rusty::index::ArgumentType::ByVal` (PROGRAM, FUNCTION_BLOCK)
// FUNCTION outputs are defined as `rusty::index::ArgumentType::ByRef` // FIXME(mhasel): for standard-compliance functions also need to support VAR_OUTPUT
if !pou.is_function() {
if !(pou.is_function() || pou.is_method()) {
let parameter_struct = match arguments_list.first() {
Some(v) => v.into_pointer_value(),
None => self.generate_lvalue(operator)?,
Expand Down Expand Up @@ -833,52 +833,54 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
operator: &AstNode,
function_context: &'b FunctionContext<'ink, 'b>,
) -> Result<Vec<BasicMetadataValueEnum<'ink>>, Diagnostic> {
let arguments_list = if matches!(pou, PouIndexEntry::Function { .. }) {
// we're calling a function
let declared_parameters = self.index.get_declared_parameters(implementation.get_type_name());
self.generate_function_arguments(pou, passed_parameters, declared_parameters)?
} else {
// no function
let (class_ptr, call_ptr) = match pou {
PouIndexEntry::Method { .. } => {
let class_ptr = self.generate_lvalue(operator).or_else(|_| {
// this might be a local method
function_context
.function
.get_first_param()
.map(|class_ptr| class_ptr.into_pointer_value())
.ok_or_else(|| Diagnostic::cannot_generate_call_statement(operator))
})?;
let call_ptr =
self.allocate_function_struct_instance(implementation.get_call_name(), operator)?;
(Some(class_ptr), call_ptr)
}
// TODO: find a more reliable way to make sure if this is a call into a local action!!
PouIndexEntry::Action { .. }
if try_from!(operator, ReferenceExpr).is_some_and(|it| it.base.is_none()) =>
{
// special handling for local actions, get the parameter from the function context
match pou {
PouIndexEntry::Function { .. } => {
// we're calling a function
let declared_parameters = self.index.get_declared_parameters(implementation.get_type_name());
self.generate_function_arguments(pou, passed_parameters, declared_parameters)
}
PouIndexEntry::Method { .. } => {
let class_ptr = self.generate_lvalue(operator).or_else(|_| {
// this might be a local method
function_context
.function
.get_first_param()
.map(|call_ptr| (None, call_ptr.into_pointer_value()))
.ok_or_else(|| Diagnostic::cannot_generate_call_statement(operator))?
}
_ => {
let call_ptr = self.generate_lvalue(operator)?;
(None, call_ptr)
}
};

// generate the pou call assignments
self.generate_stateful_pou_arguments(
implementation.get_call_name(),
class_ptr,
call_ptr,
passed_parameters,
)?
};
Ok(arguments_list)
.map(|class_ptr| class_ptr.into_pointer_value())
.ok_or_else(|| Diagnostic::cannot_generate_call_statement(operator))
})?;
let declared_parameters = self.index.get_declared_parameters(implementation.get_type_name());
let mut parameters =
self.generate_function_arguments(pou, passed_parameters, declared_parameters)?;
parameters.insert(0, class_ptr.into());
Ok(parameters)
}
PouIndexEntry::Action { .. }
if try_from!(operator, ReferenceExpr).is_some_and(|it| it.base.is_none()) =>
{
// special handling for local actions, get the parameter from the function context
let call_ptr = function_context
.function
.get_first_param()
.map(|call_ptr| call_ptr.into_pointer_value())
.ok_or_else(|| Diagnostic::cannot_generate_call_statement(operator))?;

self.generate_stateful_pou_arguments(
implementation.get_call_name(),
None,
call_ptr,
passed_parameters,
)
}
_ => {
let call_ptr = self.generate_lvalue(operator)?;
self.generate_stateful_pou_arguments(
implementation.get_call_name(),
None,
call_ptr,
passed_parameters,
)
}
}
}

fn generate_function_arguments(
Expand Down Expand Up @@ -1142,27 +1144,6 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
}
}

// TODO: will be deleted once methods work properly (like functions)
/// generates a new instance of a function called `function_name` and returns a PointerValue to it
///
/// - `function_name` the name of the function as registered in the index
/// - `context` the statement used to report a possible Diagnostic on
fn allocate_function_struct_instance(
&self,
function_name: &str,
context: &AstNode,
) -> Result<PointerValue<'ink>, Diagnostic> {
let instance_name = format!("{function_name}_instance"); // TODO: Naming convention (see plc_util/src/convention.rs)
let function_type = self
.llvm_index
.find_associated_pou_type(function_name) //Using find instead of get to control the compile error
.ok_or_else(|| {
Diagnostic::codegen_error(format!("No type associated with '{instance_name:}'"), context)
})?;

Ok(self.llvm.create_local_variable(&instance_name, &function_type))
}

/// generates the assignments of a pou-call's parameters
/// the call parameters are passed to the pou using a struct-instance with all the parameters
///
Expand Down
41 changes: 27 additions & 14 deletions src/codegen/generators/pou_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,10 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
new_llvm_index: &mut LlvmTypedIndex<'ink>,
) -> Result<FunctionValue<'ink>, Diagnostic> {
let declared_parameters = self.index.get_declared_parameters(implementation.get_call_name());
let parameters = self
.collect_parameters_for_implementation(implementation)?
let mut parameters = self.collect_parameters_for_implementation(implementation)?;
// if we are handling a method, take the first parameter as the instance
let instance = if implementation.is_method() { Some(parameters.remove(0)) } else { None };
let mut parameters = parameters
.iter()
.enumerate()
.map(|(i, p)| {
Expand Down Expand Up @@ -257,6 +259,10 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
}
})
.collect::<Vec<BasicMetadataTypeEnum>>();
// insert the instance as the first parameter
if let Some(instance) = instance {
parameters.insert(0, instance);
}

let return_type = self
.index
Expand Down Expand Up @@ -350,15 +356,6 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
) -> Result<Vec<BasicMetadataTypeEnum<'ink>>, Diagnostic> {
if !implementation.implementation_type.is_function_or_init() {
let mut parameters = vec![];
if implementation.get_implementation_type() == &ImplementationType::Method {
let class_name =
implementation.get_associated_class_name().expect("Method needs to have a class-name");
let instance_members_struct_type: StructType =
self.llvm_index.get_associated_type(class_name).map(|it| it.into_struct_type())?;
parameters.push(
instance_members_struct_type.ptr_type(AddressSpace::from(ADDRESS_SPACE_GENERIC)).into(),
);
}
let instance_struct_type: StructType = self
.llvm_index
.get_associated_pou_type(implementation.get_type_name())
Expand All @@ -368,12 +365,24 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
Ok(parameters)
} else {
let declared_params = self.index.get_declared_parameters(implementation.get_call_name());

//find the function's parameters
declared_params
let mut parameters = declared_params
.iter()
.map(|v| self.llvm_index.get_associated_type(v.get_type_name()).map(Into::into))
.collect::<Result<Vec<BasicMetadataTypeEnum>, _>>()
.collect::<Result<Vec<BasicMetadataTypeEnum>, _>>()?;

if implementation.get_implementation_type() == &ImplementationType::Method {
let class_name =
implementation.get_associated_class_name().expect("Method needs to have a class-name");
let instance_members_struct_type: StructType =
self.llvm_index.get_associated_type(class_name).map(|it| it.into_struct_type())?;
parameters.insert(
0,
instance_members_struct_type.ptr_type(AddressSpace::from(ADDRESS_SPACE_GENERIC)).into(),
);
}

Ok(parameters)
}
}

Expand Down Expand Up @@ -551,6 +560,10 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
// cannot use index from members because return and temp variables may not be considered for index in build_struct_gep
// eagerly handle the return-variable
let mut params_iter = function_context.function.get_param_iter();
// if we are in a method, skip the first parameter (the instance)
if matches!(function_context.linking_context.get_implementation_type(), ImplementationType::Method) {
params_iter.next();
}
if let Some(ret_v) = members.iter().find(|it| it.is_return()) {
let return_type = index.get_associated_type(ret_v.get_type_name())?;
let return_variable = self.llvm.create_local_variable(type_name, &return_type);
Expand Down
Loading
Loading