Skip to content

Commit c2b7712

Browse files
authored
feat: Add support for hardware references in code (#1293)
* feat: allow hardware address to be used in the code A hardware address used in the body is now resolved to the appropriate global variable. ONly resolving is done so far, codegen will follow * Add codgen support for hardware addresses Hardware references are now generated as a reference to the global variable * Add a lit test, not yet executed * Update lit test to use checks * add init function and fix test for lit * Removed all codegen snaps and regenerated them
1 parent 801c98f commit c2b7712

File tree

34 files changed

+328
-250
lines changed

34 files changed

+328
-250
lines changed

compiler/plc_ast/src/ast.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,3 +1707,27 @@ pub struct JumpStatement {
17071707
pub struct LabelStatement {
17081708
pub name: String,
17091709
}
1710+
1711+
impl HardwareAccess {
1712+
pub fn get_mangled_variable_name(&self) -> String {
1713+
let HardwareAccess { direction, address, .. } = self;
1714+
let direction = match direction {
1715+
HardwareAccessType::Input | HardwareAccessType::Output => "PI",
1716+
HardwareAccessType::Memory => "M",
1717+
HardwareAccessType::Global => "G",
1718+
};
1719+
format!(
1720+
"__{direction}_{}",
1721+
address
1722+
.iter()
1723+
.flat_map(|node| node.get_literal_integer_value())
1724+
.map(|val| val.to_string())
1725+
.collect::<Vec<_>>()
1726+
.join("_")
1727+
)
1728+
}
1729+
1730+
pub fn is_template(&self) -> bool {
1731+
matches!(self.access, DirectAccessType::Template)
1732+
}
1733+
}

compiler/plc_ast/src/pre_processor.rs

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ use plc_util::convention::internal_type_name;
77
use crate::{
88
ast::{
99
flatten_expression_list, Assignment, AstFactory, AstNode, AstStatement, CompilationUnit, DataType,
10-
DataTypeDeclaration, DirectAccessType, HardwareAccess, HardwareAccessType, Operator, Pou,
11-
UserTypeDeclaration, Variable, VariableBlock, VariableBlockType,
10+
DataTypeDeclaration, Operator, Pou, UserTypeDeclaration, Variable, VariableBlock, VariableBlockType,
1211
},
1312
literals::AstLiteral,
1413
provider::IdProvider,
@@ -155,24 +154,11 @@ fn process_global_variables(unit: &mut CompilationUnit, id_provider: &mut IdProv
155154

156155
// In any case, we have to inject initializers into aliased hardware access variables
157156
if let Some(ref node) = global_var.address {
158-
if let AstStatement::HardwareAccess(HardwareAccess { direction, access, address }) = &node.stmt {
159-
let direction = match direction {
160-
HardwareAccessType::Input | HardwareAccessType::Output => "PI",
161-
HardwareAccessType::Memory => "M",
162-
HardwareAccessType::Global => "G",
163-
};
164-
let name = format!(
165-
"__{direction}_{}",
166-
address
167-
.iter()
168-
.flat_map(|node| node.get_literal_integer_value())
169-
.map(|val| val.to_string())
170-
.collect::<Vec<_>>()
171-
.join("_")
172-
);
157+
if let AstStatement::HardwareAccess(hardware) = &node.stmt {
158+
let name = hardware.get_mangled_variable_name();
173159

174160
// %I*: DWORD; should not be declared at this stage, it is just skipped
175-
if matches!(access, DirectAccessType::Template) {
161+
if hardware.is_template() {
176162
continue;
177163
}
178164

src/codegen/generators/expression_generator.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
236236
};
237237
Ok(val)
238238
}
239+
AstStatement::HardwareAccess(..) => self
240+
.create_llvm_pointer_value_for_reference(None, "address", expression)
241+
.map(ExpressionValue::LValue),
239242
AstStatement::BinaryExpression(data) => self
240243
.generate_binary_expression(&data.left, &data.right, &data.operator, expression)
241244
.map(ExpressionValue::RValue),
@@ -245,10 +248,6 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
245248
AstStatement::UnaryExpression(data) => {
246249
self.generate_unary_expression(&data.operator, &data.value).map(ExpressionValue::RValue)
247250
}
248-
// TODO: Hardware access needs to be evaluated, see #648
249-
AstStatement::HardwareAccess { .. } => {
250-
Ok(ExpressionValue::RValue(self.llvm.i32_type().const_zero().into()))
251-
}
252251
AstStatement::ParenExpression(expr) => self.generate_expression_value(expr),
253252
//fallback
254253
_ => self.generate_literal(expression),

src/codegen/generators/statement_generator.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,10 +286,6 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
286286
return self.generate_ref_assignment(left_statement, right_statement);
287287
};
288288

289-
//TODO: Also hacky but for now we cannot generate assignments for hardware access
290-
if matches!(left_statement.get_stmt(), AstStatement::HardwareAccess { .. }) {
291-
return Ok(());
292-
}
293289
let exp_gen = self.create_expr_generator();
294290
let left: PointerValue = exp_gen.generate_expression_value(left_statement).and_then(|it| {
295291
it.get_basic_value_enum().try_into().map_err(|err| {

src/codegen/tests/address_tests.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,80 @@ fn address_variable_used_with_symbolic_name() {
139139
declare void @mainProg(%mainProg*) section "fn-$RUSTY$mainProg:v"
140140
"###);
141141
}
142+
143+
#[test]
144+
fn address_used_in_body() {
145+
let res = codegen(
146+
r"
147+
VAR_GLOBAL
148+
foo AT %IX1.2.3.4 : BOOL;
149+
baz AT %QX1.2.3.5 : BOOL;
150+
x : BOOL := TRUE;
151+
END_VAR
152+
153+
PROGRAM mainProg
154+
%IX1.2.3.4 := TRUE;
155+
x := %QX1.2.3.5;
156+
END_PROGRAM
157+
",
158+
);
159+
160+
assert_snapshot!(res, @r###"
161+
; ModuleID = '<internal>'
162+
source_filename = "<internal>"
163+
164+
%mainProg = type {}
165+
166+
@foo = global i8* null, section "var-$RUSTY$foo:pu8"
167+
@__PI_1_2_3_4 = global i8 0, section "var-$RUSTY$__PI_1_2_3_4:u8"
168+
@baz = global i8* null, section "var-$RUSTY$baz:pu8"
169+
@__PI_1_2_3_5 = global i8 0, section "var-$RUSTY$__PI_1_2_3_5:u8"
170+
@x = global i8 1, section "var-$RUSTY$x:u8"
171+
@mainProg_instance = global %mainProg zeroinitializer, section "var-$RUSTY$mainProg_instance:r0"
172+
173+
define void @mainProg(%mainProg* %0) section "fn-$RUSTY$mainProg:v" {
174+
entry:
175+
store i8 1, i8* @__PI_1_2_3_4, align 1
176+
%1 = load i8, i8* @__PI_1_2_3_5, align 1
177+
store i8 %1, i8* @x, align 1
178+
ret void
179+
}
180+
; ModuleID = '__initializers'
181+
source_filename = "__initializers"
182+
183+
%mainProg = type {}
184+
185+
@mainProg_instance = external global %mainProg, section "var-$RUSTY$mainProg_instance:r0"
186+
187+
define void @__init_mainprog(%mainProg* %0) section "fn-$RUSTY$__init_mainprog:v[pr0]" {
188+
entry:
189+
%self = alloca %mainProg*, align 8
190+
store %mainProg* %0, %mainProg** %self, align 8
191+
ret void
192+
}
193+
194+
declare void @mainProg(%mainProg*) section "fn-$RUSTY$mainProg:v"
195+
; ModuleID = '__init___testproject'
196+
source_filename = "__init___testproject"
197+
198+
%mainProg = type {}
199+
200+
@__PI_1_2_3_4 = external global i8, section "var-$RUSTY$__PI_1_2_3_4:u8"
201+
@foo = external global i8*, section "var-$RUSTY$foo:pu8"
202+
@__PI_1_2_3_5 = external global i8, section "var-$RUSTY$__PI_1_2_3_5:u8"
203+
@baz = external global i8*, section "var-$RUSTY$baz:pu8"
204+
@mainProg_instance = external global %mainProg, section "var-$RUSTY$mainProg_instance:r0"
205+
206+
define void @__init___testproject() section "fn-$RUSTY$__init___testproject:v" {
207+
entry:
208+
store i8* @__PI_1_2_3_4, i8** @foo, align 8
209+
store i8* @__PI_1_2_3_5, i8** @baz, align 8
210+
call void @__init_mainprog(%mainProg* @mainProg_instance)
211+
ret void
212+
}
213+
214+
declare void @__init_mainprog(%mainProg*) section "fn-$RUSTY$__init_mainprog:v[pr0]"
215+
216+
declare void @mainProg(%mainProg*) section "fn-$RUSTY$mainProg:v"
217+
"###);
218+
}

src/codegen/tests/expression_tests.rs

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -518,48 +518,6 @@ fn compare_date_time_literals() {
518518
insta::assert_snapshot!(result);
519519
}
520520

521-
#[test]
522-
fn hardware_access_codegen() {
523-
let result = codegen(
524-
"
525-
PROGRAM prg
526-
VAR
527-
x,y,z : BYTE;
528-
END_VAR
529-
x := %IB1.2;
530-
y := %MB1.2;
531-
z := %GB1.2;
532-
x := %IX1.2;
533-
y := %MD1.2;
534-
z := %GW1.2;
535-
END_PROGRAM
536-
",
537-
);
538-
539-
insta::assert_snapshot!(result);
540-
}
541-
542-
#[test]
543-
fn hardware_access_assign_codegen() {
544-
let result = codegen(
545-
"
546-
PROGRAM prg
547-
VAR
548-
x,y,z : BYTE;
549-
END_VAR
550-
%IB1.2 := 1;
551-
%MB1.2 := 1;
552-
%GB1.2 := 1;
553-
%IX1.2 := 1;
554-
%MD1.2 := 1;
555-
%GW1.2 := 1;
556-
END_PROGRAM
557-
",
558-
);
559-
560-
insta::assert_snapshot!(result);
561-
}
562-
563521
#[test]
564522
fn allowed_assignable_types() {
565523
let result = codegen(

src/codegen/tests/snapshots/rusty__codegen__tests__code_gen_tests__date_invalid_declaration.snap

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/codegen/tests/snapshots/rusty__codegen__tests__codegen_error_messages_tests__assigning_empty_string_literal_to_char_results_in_error.snap

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,3 @@ error[E071]: Cannot generate CHAR from empty literal
77
88
6 │ x := '';
99
│ ^^ Cannot generate CHAR from empty literal
10-
11-

src/codegen/tests/snapshots/rusty__codegen__tests__codegen_error_messages_tests__assigning_empty_string_literal_to_wide_char_results_in_error.snap

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,3 @@ error[E071]: Cannot generate WCHAR from empty literal
77
88
6 │ x := "";
99
│ ^^ Cannot generate WCHAR from empty literal
10-
11-

src/codegen/tests/snapshots/rusty__codegen__tests__codegen_error_messages_tests__assigning_string_literal_to_int_variable_results_in_casting_error.snap

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,3 @@ error[E074]: Cannot generate String-Literal for type INT
77
88
6x := 'A';
99
^^^ Cannot generate String-Literal for type INT
10-
11-

0 commit comments

Comments
 (0)