Skip to content

Commit 8ed13a3

Browse files
fix: moved shl and shr library functions to builtin and made them compatible with integers
1 parent e058ca5 commit 8ed13a3

File tree

6 files changed

+95
-134
lines changed

6 files changed

+95
-134
lines changed

libs/stdlib/iec61131-st/bit_shift_functions.st

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,3 @@
1-
(**************************
2-
*
3-
* SHL(IN, n)
4-
*
5-
* This operator implements a bitwise shift of an operand to the left.
6-
* IN is shifted by n bit to the left and is filled from the right with zeros.
7-
*
8-
*************************)
9-
{external}
10-
FUNCTION SHL<T: ANY_BIT> : T
11-
VAR_INPUT
12-
IN : T;
13-
n : UDINT;
14-
END_VAR
15-
END_FUNCTION
16-
17-
(**************************
18-
*
19-
* SHR(IN, n)
20-
*
21-
* This operator implements a bitwise shift of an operand to the right.
22-
* IN is shifted by n bit to the right.
23-
* If an unsigned data type is used, filling from the left with zeros ensues.
24-
* In the case of signed data types, an arithmetic shifting is implemented,
25-
* i.e. it is filled with the value of the highest bit.
26-
*
27-
*************************)
28-
{external}
29-
FUNCTION SHR<T: ANY_BIT> : T
30-
VAR_INPUT
31-
IN : T;
32-
n : UDINT;
33-
END_VAR
34-
END_FUNCTION
35-
361
(**************************
372
*
383
* ROL(IN, n)

libs/stdlib/src/bit_shift_functions.rs

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,5 @@
11
//! Defines shift operations
22
3-
#[allow(non_snake_case)]
4-
#[no_mangle]
5-
/// Shift left operation on bytes
6-
pub fn SHL__BYTE(input: u8, n: u32) -> u8 {
7-
input << n
8-
}
9-
10-
#[allow(non_snake_case)]
11-
#[no_mangle]
12-
/// Shift left operation on word
13-
pub fn SHL__WORD(input: u16, n: u32) -> u16 {
14-
input << n
15-
}
16-
17-
#[allow(non_snake_case)]
18-
#[no_mangle]
19-
/// Shift left operation on dword
20-
pub fn SHL__DWORD(input: u32, n: u32) -> u32 {
21-
input << n
22-
}
23-
24-
#[allow(non_snake_case)]
25-
#[no_mangle]
26-
/// Shift left operation on lword
27-
pub fn SHL__LWORD(input: u64, n: u32) -> u64 {
28-
input << n
29-
}
30-
31-
#[allow(non_snake_case)]
32-
#[no_mangle]
33-
/// Shift right operation on bytes
34-
pub fn SHR__BYTE(input: u8, n: u32) -> u8 {
35-
input >> n
36-
}
37-
38-
#[allow(non_snake_case)]
39-
#[no_mangle]
40-
/// Shift right operation on word
41-
pub fn SHR__WORD(input: u16, n: u32) -> u16 {
42-
input >> n
43-
}
44-
45-
#[allow(non_snake_case)]
46-
#[no_mangle]
47-
/// Shift right operation on dword
48-
pub fn SHR__DWORD(input: u32, n: u32) -> u32 {
49-
input >> n
50-
}
51-
52-
#[allow(non_snake_case)]
53-
#[no_mangle]
54-
/// Shift right operation on lword
55-
pub fn SHR__LWORD(input: u64, n: u32) -> u64 {
56-
input >> n
57-
}
58-
593
#[allow(non_snake_case)]
604
#[no_mangle]
615
/// Rotate left operation on bytes

libs/stdlib/tests/bit_shift_functions_tests.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
mod common;
33

44
use common::add_std;
5+
use plc_source::SourceCode;
56

67
use crate::common::compile_and_run;
78

@@ -30,7 +31,7 @@ fn shift_left_test() {
3031
l := SHL(LWORD#2#0001_1001,59);
3132
END_PROGRAM
3233
";
33-
let sources = add_std!(src, "bit_shift_functions.st");
34+
let sources = SourceCode::new(src, "main.st");
3435
let mut maintype = MainType::default();
3536
let _res: u32 = compile_and_run(sources, &mut maintype);
3637
assert_eq!(maintype.byte, 0b1100_1000);
@@ -58,7 +59,7 @@ fn shift_right_test() {
5859
l := SHR(LWORD#16#1_0000_0000_0001,3);
5960
END_PROGRAM
6061
";
61-
let sources = add_std!(src, "bit_shift_functions.st");
62+
let sources = SourceCode::new(src, "main.st");
6263
let mut maintype = MainType::default();
6364
let _res: u32 = compile_and_run(sources, &mut maintype);
6465
assert_eq!(maintype.byte, 0x2);
@@ -116,3 +117,43 @@ fn rotate_right_test() {
116117
assert_eq!(maintype.dword, 0x3000_0000);
117118
assert_eq!(maintype.lword, 0x3000_0000_0000_0000);
118119
}
120+
121+
#[derive(Default, Debug)]
122+
#[repr(C)]
123+
struct MainTypePrg3569 {
124+
a: u32,
125+
}
126+
127+
#[test]
128+
fn bug_prg_3569_shl_must_be_usable_with_int() {
129+
let src = "
130+
PROGRAM main
131+
VAR
132+
a : INT;
133+
END_VAR
134+
a := SHL(21,2);
135+
END_PROGRAM
136+
";
137+
let sources = SourceCode::new(src, "main.st");
138+
let mut maintype = MainTypePrg3569::default();
139+
let _res: u32 = compile_and_run(sources, &mut maintype);
140+
let shift_left = 21 << 2;
141+
assert_eq!(maintype.a, shift_left);
142+
}
143+
144+
#[test]
145+
fn bug_prg_3569_shr_must_be_usable_with_int() {
146+
let src = "
147+
PROGRAM main
148+
VAR
149+
a : INT;
150+
END_VAR
151+
a := SHR(21,2);
152+
END_PROGRAM
153+
";
154+
let sources = SourceCode::new(src, "main.st");
155+
let mut maintype = MainTypePrg3569::default();
156+
let _res: u32 = compile_and_run(sources, &mut maintype);
157+
let shift_right = 21 >> 2;
158+
assert_eq!(maintype.a, shift_right);
159+
}

libs/stdlib/tests/common/mod.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,14 +90,6 @@ pub fn compile_with_native<T: Compilable>(context: &CodegenContext, source: T) -
9090
("WCHAR_TO_WSTRING", iec61131std::string_conversion::WCHAR_TO_WSTRING as usize),
9191
("WCHAR_TO_CHAR", iec61131std::string_conversion::WCHAR_TO_CHAR as usize),
9292
("CHAR_TO_WCHAR", iec61131std::string_conversion::CHAR_TO_WCHAR as usize),
93-
("SHL__BYTE", iec61131std::bit_shift_functions::SHL__BYTE as usize),
94-
("SHL__WORD", iec61131std::bit_shift_functions::SHL__WORD as usize),
95-
("SHL__DWORD", iec61131std::bit_shift_functions::SHL__DWORD as usize),
96-
("SHL__LWORD", iec61131std::bit_shift_functions::SHL__LWORD as usize),
97-
("SHR__BYTE", iec61131std::bit_shift_functions::SHR__BYTE as usize),
98-
("SHR__WORD", iec61131std::bit_shift_functions::SHR__WORD as usize),
99-
("SHR__DWORD", iec61131std::bit_shift_functions::SHR__DWORD as usize),
100-
("SHR__LWORD", iec61131std::bit_shift_functions::SHR__LWORD as usize),
10193
("ROL__BYTE", iec61131std::bit_shift_functions::ROL__BYTE as usize),
10294
("ROL__WORD", iec61131std::bit_shift_functions::ROL__WORD as usize),
10395
("ROL__DWORD", iec61131std::bit_shift_functions::ROL__DWORD as usize),

src/builtins.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,58 @@ lazy_static! {
604604
}
605605
}
606606
),
607+
(
608+
"SHL",
609+
BuiltIn {
610+
decl: "
611+
FUNCTION SHL<T: ANY> : T
612+
VAR_INPUT
613+
IN : T;
614+
n : UDINT;
615+
END_VAR
616+
END_FUNCTION
617+
",
618+
annotation: None,
619+
validation: Some(|validator, operator, parameters, _, _| {
620+
validate_argument_count(validator, operator, &parameters, 2);
621+
}),
622+
generic_name_resolver: no_generic_name_resolver,
623+
code: |generator, params, _| {
624+
let left = generator.generate_expression(params[0])?.into_int_value();
625+
let right = generator.generate_expression(params[1])?.into_int_value();
626+
627+
let shl = generator.llvm.builder.build_left_shift(left, right, "")?;
628+
629+
Ok(ExpressionValue::RValue(shl.as_basic_value_enum()))
630+
}
631+
},
632+
),
633+
(
634+
"SHR",
635+
BuiltIn {
636+
decl: "
637+
FUNCTION SHR<T: ANY> : T
638+
VAR_INPUT
639+
IN : T;
640+
n : UDINT;
641+
END_VAR
642+
END_FUNCTION
643+
",
644+
annotation: None,
645+
validation: Some(|validator, operator, parameters, _, _| {
646+
validate_argument_count(validator, operator, &parameters, 2);
647+
}),
648+
generic_name_resolver: no_generic_name_resolver,
649+
code: |generator, params, _| {
650+
let left = generator.generate_expression(params[0])?.into_int_value();
651+
let right = generator.generate_expression(params[1])?.into_int_value();
652+
653+
let shl = generator.llvm.builder.build_right_shift(left, right, false, "")?;
654+
655+
Ok(ExpressionValue::RValue(shl.as_basic_value_enum()))
656+
}
657+
},
658+
),
607659
]);
608660
}
609661

xtask/res/combined.st

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -914,39 +914,6 @@ FUNCTION DAY_OF_WEEK : SINT
914914
VAR_INPUT
915915
in : DATE;
916916
END_VAR
917-
END_FUNCTION (* *************************
918-
*
919-
* SHL(IN, n)
920-
*
921-
* This operator implements a bitwise shift of an operand to the left.
922-
* IN is shifted by n bit to the left and is filled from the right with zeros.
923-
*
924-
************************ *)
925-
{external}
926-
FUNCTION SHL < T : ANY_BIT > : T
927-
VAR_INPUT
928-
IN : T;
929-
n : UDINT;
930-
END_VAR
931-
END_FUNCTION
932-
933-
(**************************
934-
*
935-
* SHR(IN, n)
936-
*
937-
* This operator implements a bitwise shift of an operand to the right.
938-
* IN is shifted by n bit to the right.
939-
* If an unsigned data type is used, filling from the left with zeros ensues.
940-
* In the case of signed data types, an arithmetic shifting is implemented,
941-
* i.e. it is filled with the value of the highest bit.
942-
*
943-
************************ *)
944-
{external}
945-
FUNCTION SHR < T : ANY_BIT > : T
946-
VAR_INPUT
947-
IN : T;
948-
n : UDINT;
949-
END_VAR
950917
END_FUNCTION
951918

952919
(**************************

0 commit comments

Comments
 (0)