From e369a37a2b8d8faa0b0ecc9a46e415917bc3e51a Mon Sep 17 00:00:00 2001
From: Mathias Rieder <mathias.rieder@gmail.com>
Date: Tue, 21 Jun 2022 21:44:49 +0000
Subject: [PATCH] constant propagation in ranged type limits

added a test that shows that constants are propagated even in
ranged-type's limits, so even if you use (const-)expressions (a+b)
to define the limits of a ranged type, the const-expressions
will be evaluated during compile time and the result will be used.
- as in contrast we would do this calculation all the time at
runtime.

the behavior was introduced in PR #504 (016328)

fixes #350
---
 src/codegen/tests/code_gen_tests.rs           | 34 ++++++++++++++++++
 ...anged_type_declaration_are_propagated.snap | 36 +++++++++++++++++++
 2 files changed, 70 insertions(+)
 create mode 100644 src/codegen/tests/snapshots/rusty__codegen__tests__code_gen_tests__constant_expressions_in_ranged_type_declaration_are_propagated.snap

diff --git a/src/codegen/tests/code_gen_tests.rs b/src/codegen/tests/code_gen_tests.rs
index e97d52b3f2..b5e0a0ac2e 100644
--- a/src/codegen/tests/code_gen_tests.rs
+++ b/src/codegen/tests/code_gen_tests.rs
@@ -2923,3 +2923,37 @@ fn optional_output_assignment() {
     // codegen should be successful
     insta::assert_snapshot!(result);
 }
+
+#[test]
+fn constant_expressions_in_ranged_type_declaration_are_propagated() {
+    //GIVEN a ranged type from 0 .. MIN+1 where MIN is a global constant
+    //WHEN the code is generated
+    let result = codegen(
+        "        
+        VAR_GLOBAL CONSTANT
+          MIN : INT := 7;
+        END_VAR 
+
+        FUNCTION CheckRangeSigned: INT 
+          VAR_INPUT
+              value : INT;
+              lower : INT;
+              upper : INT;
+          END_VAR
+          CheckRangeSigned := value;
+        END_FUNCTION
+
+        PROGRAM prg
+          VAR
+            x: INT(0 .. MIN+1);
+          END_VAR
+          x := 5;
+        END_PROGRAM",
+    );
+
+    // THEN we expect that the assignment to the range-typed variable (x := 5) will result
+    // in a call to CheckRangedSigned where the upper bound is a literal i16 8 - NOT an
+    // add-expression that really calculates the upper bound at runtime
+
+    insta::assert_snapshot!(result);
+}
diff --git a/src/codegen/tests/snapshots/rusty__codegen__tests__code_gen_tests__constant_expressions_in_ranged_type_declaration_are_propagated.snap b/src/codegen/tests/snapshots/rusty__codegen__tests__code_gen_tests__constant_expressions_in_ranged_type_declaration_are_propagated.snap
new file mode 100644
index 0000000000..10026ead95
--- /dev/null
+++ b/src/codegen/tests/snapshots/rusty__codegen__tests__code_gen_tests__constant_expressions_in_ranged_type_declaration_are_propagated.snap
@@ -0,0 +1,36 @@
+---
+source: src/codegen/tests/code_gen_tests.rs
+expression: result
+---
+; ModuleID = 'main'
+source_filename = "main"
+
+%prg_interface = type { i16 }
+
+@MIN = unnamed_addr constant i16 7
+@prg_instance = global %prg_interface zeroinitializer
+
+define i16 @CheckRangeSigned(i16 %0, i16 %1, i16 %2) {
+entry:
+  %value = alloca i16, align 2
+  store i16 %0, i16* %value, align 2
+  %lower = alloca i16, align 2
+  store i16 %1, i16* %lower, align 2
+  %upper = alloca i16, align 2
+  store i16 %2, i16* %upper, align 2
+  %CheckRangeSigned = alloca i16, align 2
+  store i16 0, i16* %CheckRangeSigned, align 2
+  %load_value = load i16, i16* %value, align 2
+  store i16 %load_value, i16* %CheckRangeSigned, align 2
+  %CheckRangeSigned_ret = load i16, i16* %CheckRangeSigned, align 2
+  ret i16 %CheckRangeSigned_ret
+}
+
+define void @prg(%prg_interface* %0) {
+entry:
+  %x = getelementptr inbounds %prg_interface, %prg_interface* %0, i32 0, i32 0
+  %call = call i16 @CheckRangeSigned(i16 5, i16 0, i16 8)
+  store i16 %call, i16* %x, align 2
+  ret void
+}
+