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
14 changes: 11 additions & 3 deletions src/codegen/generators/expression_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -962,8 +962,8 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {

_ => {
let assigned_output = self.generate_lvalue(expr)?;
let assigned_output_type =
self.annotations.get_type_or_void(expr, self.index).get_type_information();
let assigned_output_type_main = self.annotations.get_type_or_void(expr, self.index);
let assigned_output_type = assigned_output_type_main.get_type_information();

let pou_type_name = self
.index
Expand All @@ -973,6 +973,8 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
let pointee = self.llvm_index.get_associated_pou_type(pou_type_name).unwrap();
let output = self.build_parameter_struct_gep(pointee, context);

let output_value_type_main =
self.index.get_effective_type_or_void_by_name(parameter.get_type_name());
let output_value_type = self.index.get_type_information_or_void(parameter.get_type_name());

if assigned_output_type.is_aggregate() && output_value_type.is_aggregate() {
Expand All @@ -986,7 +988,13 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
)?;
} else {
let pointee = self.llvm_index.get_associated_type(output_value_type.get_name()).unwrap();
let output_value = builder.build_load(pointee, output, "")?;
let output_value = cast_if_needed!(
self,
assigned_output_type_main,
output_value_type_main,
builder.build_load(pointee, output, "")?,
None
)?;
builder.build_store(assigned_output, output_value)?;
}
}
Expand Down
122 changes: 122 additions & 0 deletions src/codegen/tests/function_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,3 +424,125 @@ fn function_call_with_array_access() {

filtered_assert_snapshot!(result)
}

#[test]
fn function_output_should_be_cast_if_needed() {
let result = codegen(
"
FUNCTION libFunction : INT
VAR_INPUT
inVar1 : INT;
inVar2 : REAL;
END_VAR
VAR_OUTPUT
result : REAL;
END_VAR
END_FUNCTION

PROGRAM mainProg
VAR
i1 : INT;
END_VAR

libFunction(
inVar1 := 0,
inVar2 := 0.0,
result => i1
);
END_PROGRAM
",
);

filtered_assert_snapshot!(result, @r#"
; ModuleID = '<internal>'
source_filename = "<internal>"
target datalayout = "[filtered]"
target triple = "[filtered]"

%mainProg = type { i16 }

@mainProg_instance = global %mainProg zeroinitializer

define i16 @libFunction(i16 %0, float %1, ptr %2) {
entry:
%libFunction = alloca i16, align [filtered]
%inVar1 = alloca i16, align [filtered]
store i16 %0, ptr %inVar1, align [filtered]
%inVar2 = alloca float, align [filtered]
store float %1, ptr %inVar2, align [filtered]
%result = alloca ptr, align [filtered]
store ptr %2, ptr %result, align [filtered]
store i16 0, ptr %libFunction, align [filtered]
%libFunction_ret = load i16, ptr %libFunction, align [filtered]
ret i16 %libFunction_ret
}

define void @mainProg(ptr %0) {
entry:
%i1 = getelementptr inbounds nuw %mainProg, ptr %0, i32 0, i32 0
%__libFunction_result0 = alloca float, align [filtered]
store float 0.000000e+00, ptr %__libFunction_result0, align [filtered]
%call = call i16 @libFunction(i16 0, float 0.000000e+00, ptr %__libFunction_result0)
%load___libFunction_result0 = load float, ptr %__libFunction_result0, align [filtered]
%1 = fptosi float %load___libFunction_result0 to i16
store i16 %1, ptr %i1, align [filtered]
ret void
}
"#)
}

#[test]
fn function_block_output_should_be_cast_if_needed() {
let result = codegen(
"
FUNCTION_BLOCK libFunction_fb
VAR_OUTPUT
result : REAL;
END_VAR
END_FUNCTION_BLOCK

PROGRAM mainProg
VAR
libFunction : libFunction_fb;
i1 : INT;
END_VAR

libFunction(
result => i1
);
END_PROGRAM
",
);

filtered_assert_snapshot!(result, @r#"
; ModuleID = '<internal>'
source_filename = "<internal>"
target datalayout = "[filtered]"
target triple = "[filtered]"

%mainProg = type { %libFunction_fb, i16 }
%libFunction_fb = type { float }

@mainProg_instance = global %mainProg zeroinitializer

define void @libFunction_fb(ptr %0) {
entry:
%this = alloca ptr, align [filtered]
store ptr %0, ptr %this, align [filtered]
%result = getelementptr inbounds nuw %libFunction_fb, ptr %0, i32 0, i32 0
ret void
}

define void @mainProg(ptr %0) {
entry:
%libFunction = getelementptr inbounds nuw %mainProg, ptr %0, i32 0, i32 0
%i1 = getelementptr inbounds nuw %mainProg, ptr %0, i32 0, i32 1
call void @libFunction_fb(ptr %libFunction)
%1 = getelementptr inbounds %libFunction_fb, ptr %libFunction, i32 0, i32 0
%2 = load float, ptr %1, align [filtered]
%3 = fptosi float %2 to i16
store i16 %3, ptr %i1, align [filtered]
ret void
}
"#)
}
Loading
Loading