-
Notifications
You must be signed in to change notification settings - Fork 68
fix: moved shl and shr library functions to builtin #1562
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| mod common; | ||
|
|
||
| use common::add_std; | ||
| use plc_source::SourceCode; | ||
|
|
||
| use crate::common::compile_and_run; | ||
|
|
||
|
|
@@ -30,7 +31,7 @@ fn shift_left_test() { | |
| l := SHL(LWORD#2#0001_1001,59); | ||
| END_PROGRAM | ||
| "; | ||
| let sources = add_std!(src, "bit_shift_functions.st"); | ||
| let sources = SourceCode::new(src, "main.st"); | ||
| let mut maintype = MainType::default(); | ||
| let _res: u32 = compile_and_run(sources, &mut maintype); | ||
| assert_eq!(maintype.byte, 0b1100_1000); | ||
|
|
@@ -58,7 +59,7 @@ fn shift_right_test() { | |
| l := SHR(LWORD#16#1_0000_0000_0001,3); | ||
| END_PROGRAM | ||
| "; | ||
| let sources = add_std!(src, "bit_shift_functions.st"); | ||
| let sources = SourceCode::new(src, "main.st"); | ||
| let mut maintype = MainType::default(); | ||
| let _res: u32 = compile_and_run(sources, &mut maintype); | ||
| assert_eq!(maintype.byte, 0x2); | ||
|
|
@@ -116,3 +117,43 @@ fn rotate_right_test() { | |
| assert_eq!(maintype.dword, 0x3000_0000); | ||
| assert_eq!(maintype.lword, 0x3000_0000_0000_0000); | ||
| } | ||
|
|
||
| #[derive(Default, Debug)] | ||
| #[repr(C)] | ||
| struct MainTypePrg3569 { | ||
| a: u32, | ||
| } | ||
|
|
||
| #[test] | ||
| fn bug_prg_3569_shl_must_be_usable_with_int() { | ||
| let src = " | ||
| PROGRAM main | ||
| VAR | ||
| a : INT; | ||
| END_VAR | ||
| a := SHL(21,2); | ||
| END_PROGRAM | ||
| "; | ||
| let sources = SourceCode::new(src, "main.st"); | ||
| let mut maintype = MainTypePrg3569::default(); | ||
| let _res: u32 = compile_and_run(sources, &mut maintype); | ||
| let shift_left = 21 << 2; | ||
| assert_eq!(maintype.a, shift_left); | ||
| } | ||
|
|
||
| #[test] | ||
| fn bug_prg_3569_shr_must_be_usable_with_int() { | ||
| let src = " | ||
| PROGRAM main | ||
| VAR | ||
| a : INT; | ||
| END_VAR | ||
| a := SHR(21,2); | ||
| END_PROGRAM | ||
| "; | ||
| let sources = SourceCode::new(src, "main.st"); | ||
| let mut maintype = MainTypePrg3569::default(); | ||
| let _res: u32 = compile_and_run(sources, &mut maintype); | ||
| let shift_right = 21 >> 2; | ||
| assert_eq!(maintype.a, shift_right); | ||
| } | ||
|
Comment on lines
+121
to
+159
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you use lit for these integration tests? For context, we have decided to use lit for all of our integration tests moving forward. At some point we would also like to migrate the existing ones but that hasn't happened yet. For reference https://github.com/PLC-lang/rusty/tree/master/tests/lit |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -604,6 +604,58 @@ lazy_static! { | |
| } | ||
| } | ||
| ), | ||
| ( | ||
| "SHL", | ||
| BuiltIn { | ||
| decl: " | ||
| FUNCTION SHL<T: ANY> : T | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By declaring In general I'm not sure if #[test]
fn temp() {
let id_provider = IdProvider::default();
let (unit, mut index) = index_with_ids(
r#"
FUNCTION SHLL<T: ANY_BIT>: T
VAR_INPUT
IN : T;
n : UDINT;
END_VAR
END_FUNCTION
FUNCTION main
SHLL(5, 2);
END_FUNCTION
"#,
id_provider.clone(),
);
let annotations = annotate_with_ids(&unit, &mut index, id_provider);
let stmt = &unit.implementations.iter().find(|imp| imp.name == "main").unwrap().statements[0];
let AstStatement::CallStatement(CallStatement { operator, parameters: Some(parameters), .. }) =
stmt.get_stmt()
else {
unreachable!();
};
// SHLL(5, 2);
// ^^^^^^^^^^
insta::assert_debug_snapshot!(annotations.get(stmt), @r#"
Some(
Value {
resulting_type: "BOOL",
},
)
"#);
insta::assert_debug_snapshot!(annotations.get_type(stmt, &index), @r#"
Some(
DataType {
name: "BOOL",
initial_value: None,
information: Integer {
name: "BOOL",
signed: false,
size: 8,
semantic_size: Some(
1,
),
},
nature: Bit,
location: SourceLocation {
span: None,
},
},
)
"#);
insta::assert_debug_snapshot!(annotations.get_type_hint(stmt, &index), @"None");
let AstStatement::ExpressionList(arguments) = ¶meters.stmt else {
unreachable!();
};
// SHLL(5, 2);
// ^
insta::assert_debug_snapshot!(annotations.get(&arguments[0]), @r#"
Some(
Value {
resulting_type: "DINT",
},
)
"#);
insta::assert_debug_snapshot!(annotations.get_type(&arguments[0], &index), @r#"
Some(
DataType {
name: "DINT",
initial_value: None,
information: Integer {
name: "DINT",
signed: true,
size: 32,
semantic_size: None,
},
nature: Signed,
location: SourceLocation {
span: None,
},
},
)
"#);
insta::assert_debug_snapshot!(annotations.get_type_hint(&arguments[0], &index), @r#"
Some(
DataType {
name: "BOOL",
initial_value: None,
information: Integer {
name: "BOOL",
signed: false,
size: 8,
semantic_size: Some(
1,
),
},
nature: Bit,
location: SourceLocation {
span: None,
},
},
)
"#);
// SHLL(5, 2);
// ^
insta::assert_debug_snapshot!(annotations.get(&arguments[1]), @r#"
Some(
Value {
resulting_type: "DINT",
},
)
"#);
insta::assert_debug_snapshot!(annotations.get_type(&arguments[1], &index), @r#"
Some(
DataType {
name: "DINT",
initial_value: None,
information: Integer {
name: "DINT",
signed: true,
size: 32,
semantic_size: None,
},
nature: Signed,
location: SourceLocation {
span: None,
},
},
)
"#);
insta::assert_debug_snapshot!(annotations.get_type_hint(&arguments[1], &index), @r#"
Some(
DataType {
name: "UDINT",
initial_value: None,
information: Integer {
name: "UDINT",
signed: false,
size: 32,
semantic_size: None,
},
nature: Unsigned,
location: SourceLocation {
span: None,
},
},
)
"#); |
||
| VAR_INPUT | ||
| IN : T; | ||
| n : UDINT; | ||
| END_VAR | ||
| END_FUNCTION | ||
| ", | ||
| annotation: None, | ||
| validation: Some(|validator, operator, parameters, _, _| { | ||
| validate_argument_count(validator, operator, ¶meters, 2); | ||
| }), | ||
| generic_name_resolver: no_generic_name_resolver, | ||
| code: |generator, params, _| { | ||
| let left = generator.generate_expression(params[0])?.into_int_value(); | ||
| let right = generator.generate_expression(params[1])?.into_int_value(); | ||
|
|
||
| let shl = generator.llvm.builder.build_left_shift(left, right, "")?; | ||
|
|
||
| Ok(ExpressionValue::RValue(shl.as_basic_value_enum())) | ||
| } | ||
| }, | ||
| ), | ||
| ( | ||
| "SHR", | ||
| BuiltIn { | ||
| decl: " | ||
| FUNCTION SHR<T: ANY> : T | ||
| VAR_INPUT | ||
| IN : T; | ||
| n : UDINT; | ||
| END_VAR | ||
| END_FUNCTION | ||
| ", | ||
| annotation: None, | ||
| validation: Some(|validator, operator, parameters, _, _| { | ||
| validate_argument_count(validator, operator, ¶meters, 2); | ||
| }), | ||
| generic_name_resolver: no_generic_name_resolver, | ||
| code: |generator, params, _| { | ||
| let left = generator.generate_expression(params[0])?.into_int_value(); | ||
| let right = generator.generate_expression(params[1])?.into_int_value(); | ||
|
|
||
| let shl = generator.llvm.builder.build_right_shift(left, right, false, "")?; | ||
|
|
||
| Ok(ExpressionValue::RValue(shl.as_basic_value_enum())) | ||
| } | ||
| }, | ||
| ), | ||
| ]); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ghaith why the migration from SH{L,R} as a standard library function to a built-in one? Shouldn't we try to keep the built-ins as small as possible?