Skip to content

Commit

Permalink
feat: add VAR_EXTERNAL blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
mhasel committed Oct 2, 2024
1 parent 156ac18 commit aa1993a
Show file tree
Hide file tree
Showing 30 changed files with 656 additions and 10 deletions.
2 changes: 2 additions & 0 deletions compiler/plc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ pub enum VariableBlockType {
Output,
Global,
InOut,
External,
}

impl Display for VariableBlockType {
Expand All @@ -364,6 +365,7 @@ impl Display for VariableBlockType {
VariableBlockType::Output => write!(f, "Output"),
VariableBlockType::Global => write!(f, "Global"),
VariableBlockType::InOut => write!(f, "InOut"),
VariableBlockType::External => write!(f, "External"),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/codegen/generators/data_type_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ impl<'ink, 'b> DataTypeGenerator<'ink, 'b> {
if let DataTypeInformation::Struct { source, members, .. } = information {
let members = members
.iter()
.filter(|it| !it.is_temp() && !it.is_return())
.filter(|it| !it.is_temp() && !(it.is_return() || it.is_var_external()))
.map(|m| self.types_index.get_associated_type(m.get_type_name()))
.collect::<Result<Vec<BasicTypeEnum>, Diagnostic>>()?;

Expand Down
4 changes: 2 additions & 2 deletions src/codegen/generators/pou_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
}

// handle all parameters (without return!)
for m in members.iter().filter(|it| !it.is_return()) {
for m in members.iter().filter(|it| !(it.is_return() || it.is_var_external())) {
let parameter_name = m.get_name();

let (name, variable) = if m.is_parameter() {
Expand Down Expand Up @@ -676,7 +676,7 @@ impl<'ink, 'cg> PouGenerator<'ink, 'cg> {
//Generate reference to parameter
// cannot use index from members because return and temp variables may not be considered for index in build_struct_gep
let mut var_count = 0;
for m in members.iter() {
for m in members.iter().filter(|it| !it.is_var_external()) {
let parameter_name = m.get_name();

let (name, variable) = if m.is_temp() || m.is_return() {
Expand Down
123 changes: 123 additions & 0 deletions src/codegen/tests/code_gen_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3513,3 +3513,126 @@ fn array_of_struct_as_member_of_another_struct_and_variable_declaration_is_initi

insta::assert_snapshot!(res);
}

#[test]
// XXX: this behaviour might change in future, for now `VAR_EXTERNAL` variables are ignored
fn variables_in_var_external_block_are_not_generated() {
let res = codegen(
"
VAR_GLOBAL
arr: ARRAY [0..100] OF INT;
END_VAR
FUNCTION foo
VAR_EXTERNAL
arr : ARRAY [0..100] OF INT;
END_VAR
END_FUNCTION
FUNCTION_BLOCK bar
VAR_EXTERNAL CONSTANT
arr : ARRAY [0..100] OF INT;
END_VAR
END_FUNCTION_BLOCK
PROGRAM baz
VAR_EXTERNAL CONSTANT
arr : ARRAY [0..100] OF INT;
END_VAR
END_PROGRAM
CLASS qux
VAR_EXTERNAL
arr : ARRAY [0..100] OF INT;
END_VAR
END_CLASS
",
);

insta::assert_snapshot!(res, @r###"
; ModuleID = '<internal>'
source_filename = "<internal>"
%bar = type {}
%baz = type {}
%qux = type {}
@arr = global [101 x i16] zeroinitializer
@__bar__init = unnamed_addr constant %bar zeroinitializer
@baz_instance = global %baz zeroinitializer
@__qux__init = unnamed_addr constant %qux zeroinitializer
define void @foo() {
entry:
ret void
}
define void @bar(%bar* %0) {
entry:
ret void
}
define void @baz(%baz* %0) {
entry:
ret void
}
define void @qux(%qux* %0) {
entry:
ret void
}
; ModuleID = '__initializers'
source_filename = "__initializers"
%baz = type {}
%bar = type {}
%qux = type {}
@baz_instance = external global %baz
@__bar__init = external global %bar
@__qux__init = external global %qux
define void @__init_baz(%baz* %0) {
entry:
%self = alloca %baz*, align 8
store %baz* %0, %baz** %self, align 8
ret void
}
declare void @baz(%baz*)
define void @__init_bar(%bar* %0) {
entry:
%self = alloca %bar*, align 8
store %bar* %0, %bar** %self, align 8
ret void
}
declare void @bar(%bar*)
define void @__init_qux(%qux* %0) {
entry:
%self = alloca %qux*, align 8
store %qux* %0, %qux** %self, align 8
ret void
}
declare void @qux(%qux*)
; ModuleID = '__init___testproject'
source_filename = "__init___testproject"
%baz = type {}
@baz_instance = external global %baz
define void @__init___testproject() {
entry:
call void @__init_baz(%baz* @baz_instance)
ret void
}
declare void @__init_baz(%baz*)
declare void @baz(%baz*)
"###);
}
71 changes: 71 additions & 0 deletions src/codegen/tests/initialization_test/complex_initializers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1283,3 +1283,74 @@ fn var_config_aliased_variables_initialized() {
declare void @FB(%FB*)
"###);
}

#[test]
fn var_external_blocks_are_ignored_in_init_functions() {
let res = codegen(
r"
VAR_GLOBAL
s: STRING;
refString AT s : STRING;
END_VAR
FUNCTION_BLOCK foo
VAR_EXTERNAL
refString : STRING;
END_VAR
END_FUNCTION
FUNCTION bar
VAR_EXTERNAL
refString : STRING;
END_VAR
END_FUNCTION
",
);

insta::assert_snapshot!(res, @r###"
; ModuleID = '<internal>'
source_filename = "<internal>"
%foo = type {}
@s = global [81 x i8] zeroinitializer
@refString = global [81 x i8]* null
@__foo__init = unnamed_addr constant %foo zeroinitializer
define void @foo(%foo* %0) {
entry:
ret void
}
define void @bar() {
entry:
ret void
}
; ModuleID = '__initializers'
source_filename = "__initializers"
%foo = type {}
@__foo__init = external global %foo
define void @__init_foo(%foo* %0) {
entry:
%self = alloca %foo*, align 8
store %foo* %0, %foo** %self, align 8
ret void
}
declare void @foo(%foo*)
; ModuleID = '__init___testproject'
source_filename = "__init___testproject"
@s = external global [81 x i8]
@refString = external global [81 x i8]*
define void @__init___testproject() {
entry:
store [81 x i8]* @s, [81 x i8]** @refString, align 8
ret void
}
"###)
}
21 changes: 21 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ pub struct VariableIndexEntry {
pub argument_type: ArgumentType,
/// true if this variable is a compile-time-constant
is_constant: bool,
// true if this variable is in a 'VAR_EXTERNAL' block
is_var_external: bool,
/// the variable's datatype
pub data_type_name: String,
/// the index of the member-variable in it's container (e.g. struct). defautls to 0 (Single variables)
Expand Down Expand Up @@ -130,6 +132,7 @@ pub struct MemberInfo<'b> {
variable_type_name: &'b str,
binding: Option<HardwareBinding>,
is_constant: bool,
is_var_external: bool,
varargs: Option<VarArgs>,
}

Expand All @@ -148,6 +151,7 @@ impl VariableIndexEntry {
initial_value: None,
argument_type,
is_constant: false,
is_var_external: false,
data_type_name: data_type_name.to_string(),
location_in_parent,
linkage: LinkageType::Internal,
Expand All @@ -169,6 +173,7 @@ impl VariableIndexEntry {
initial_value: None,
argument_type: ArgumentType::ByVal(VariableType::Global),
is_constant: false,
is_var_external: false,
data_type_name: data_type_name.to_string(),
location_in_parent: 0,
linkage: LinkageType::Internal,
Expand Down Expand Up @@ -203,6 +208,11 @@ impl VariableIndexEntry {
self
}

pub fn set_var_external(mut self, var_external: bool) -> Self {
self.is_var_external = var_external;
self
}

/// Creates a new VariableIndexEntry from the current entry with a new container and type
/// This is used to create new entries from previously generic entries
pub fn into_typed(&self, container: &str, new_type: &str) -> Self {
Expand Down Expand Up @@ -253,6 +263,14 @@ impl VariableIndexEntry {
self.linkage == LinkageType::External
}

pub fn is_var_external(&self) -> bool {
self.is_var_external
}

pub fn is_var_external_constant(&self) -> bool {
self.is_var_external && self.is_constant
}

pub fn get_declaration_type(&self) -> ArgumentType {
self.argument_type
}
Expand Down Expand Up @@ -350,6 +368,7 @@ pub enum VariableType {
InOut,
Global,
Return,
External,
}

impl VariableType {
Expand All @@ -368,6 +387,7 @@ impl std::fmt::Display for VariableType {
VariableType::InOut => write!(f, "InOut"),
VariableType::Global => write!(f, "Global"),
VariableType::Return => write!(f, "Return"),
VariableType::External => write!(f, "External"),
}
}
}
Expand Down Expand Up @@ -1496,6 +1516,7 @@ impl Index {
.set_initial_value(initial_value)
.set_hardware_binding(member_info.binding)
.set_varargs(member_info.varargs)
.set_var_external(member_info.is_var_external)
}

pub fn register_enum_variant(
Expand Down
Loading

0 comments on commit aa1993a

Please sign in to comment.