Skip to content

Commit a286437

Browse files
committed
Fix tests
1 parent 7c014a2 commit a286437

File tree

94 files changed

+5755
-2671
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+5755
-2671
lines changed

compiler/plc_ast/src/pre_processor.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@ fn process_global_variables(unit: &mut CompilationUnit, id_provider: &mut IdProv
196196
}
197197

198198
fn process_var_config_variables(unit: &mut CompilationUnit) {
199-
let block = get_internal_global_block(unit);
200199
let variables = unit.var_config.iter().filter_map(|ConfigVariable { data_type, address, .. }| {
201200
let AstStatement::HardwareAccess(hardware) = &address.stmt else {
202201
unreachable!("Must be parsed as hardware access")
@@ -206,10 +205,12 @@ fn process_var_config_variables(unit: &mut CompilationUnit) {
206205
return None;
207206
}
208207

208+
// Check if the mangled variable already exists in any of the global variable blocks
209+
// XXX: Not a fan of this, we should fix the underlying issue with variable block creation here...
209210
let name = hardware.get_mangled_variable_name();
210-
if block.is_some_and(|it| it.variables.iter().any(|v| v.name == name)) {
211-
return None;
212-
};
211+
if find_mangled_variable(unit, &name) {
212+
return None; // Already exists, skip
213+
}
213214

214215
Some(Variable {
215216
name,
@@ -220,7 +221,7 @@ fn process_var_config_variables(unit: &mut CompilationUnit) {
220221
})
221222
});
222223

223-
update_generated_globals(unit, variables.collect())
224+
update_generated_globals(unit, variables.collect());
224225
}
225226

226227
fn update_generated_globals(unit: &mut CompilationUnit, mangled_globals: Vec<Variable>) {
@@ -242,11 +243,8 @@ fn update_generated_globals(unit: &mut CompilationUnit, mangled_globals: Vec<Var
242243
unit.global_vars.push(block);
243244
}
244245

245-
fn get_internal_global_block(unit: &CompilationUnit) -> Option<&VariableBlock> {
246-
unit.global_vars
247-
.iter()
248-
.position(|block| block.kind == VariableBlockType::Global && block.location.is_builtin_internal())
249-
.and_then(|index| unit.global_vars.get(index))
246+
fn find_mangled_variable(unit: &CompilationUnit, name: &str) -> bool {
247+
unit.global_vars.iter().flat_map(|block| &block.variables).any(|var| var.name == name)
250248
}
251249

252250
fn build_enum_initializer(

compiler/plc_driver/src/runner.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub fn compile<T: Compilable>(codegen_context: &CodegenContext, source: T) -> Ge
6666
pub fn compile_and_run<T, U, S: Compilable>(source: S, params: &mut T) -> U {
6767
let context: CodegenContext = CodegenContext::create();
6868
let module = compile(&context, source);
69-
module.print_to_stderr();
69+
// module.print_to_stderr();
7070
module.run::<T, U>("main", params)
7171
}
7272

@@ -77,6 +77,6 @@ pub fn compile_and_run<T, U, S: Compilable>(source: S, params: &mut T) -> U {
7777
pub fn compile_and_run_no_params<U, S: Compilable>(source: S) -> U {
7878
let context: CodegenContext = CodegenContext::create();
7979
let module = compile(&context, source);
80-
module.print_to_stderr();
80+
// module.print_to_stderr();
8181
module.run_no_param::<U>("main")
8282
}

compiler/plc_driver/src/tests/.multi_files.rs.pending-snap

Lines changed: 3 additions & 0 deletions
Large diffs are not rendered by default.

compiler/plc_driver/src/tests/multi_files.rs

Lines changed: 73 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,13 @@ fn forward_declared_constant_is_also_marked_constant() {
159159
let results = compile_with_root(vec![src1, src2], vec![], "root", DebugLevel::Full(5)).unwrap();
160160

161161
// THEN the constant is marked as constant in the generated code
162-
filtered_assert_snapshot!(results.join("\n"), @r###"
162+
filtered_assert_snapshot!(results.join("\n"), @r#"
163163
; ModuleID = 'external_file1.st'
164164
source_filename = "external_file1.st"
165165
target datalayout = "[filtered]"
166166
target triple = "[filtered]"
167167
168-
%foo = type { i16 }
168+
%foo = type { i32*, i16 }
169169
%mainProg = type { i16 }
170170
171171
@__foo__init = external unnamed_addr constant %foo
@@ -175,28 +175,28 @@ fn forward_declared_constant_is_also_marked_constant() {
175175
entry:
176176
%main = alloca i16, align 2
177177
%f = alloca %foo, align 8
178-
call void @llvm.dbg.declare(metadata %foo* %f, metadata !9, metadata !DIExpression()), !dbg !15
178+
call void @llvm.dbg.declare(metadata %foo* %f, metadata !9, metadata !DIExpression()), !dbg !18
179179
%0 = bitcast %foo* %f to i8*
180180
call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %0, i8* align 1 bitcast (%foo* @__foo__init to i8*), i64 ptrtoint (%foo* getelementptr (%foo, %foo* null, i32 1) to i64), i1 false)
181-
call void @llvm.dbg.declare(metadata i16* %main, metadata !16, metadata !DIExpression()), !dbg !17
181+
call void @llvm.dbg.declare(metadata i16* %main, metadata !19, metadata !DIExpression()), !dbg !20
182182
store i16 0, i16* %main, align 2
183-
call void @__init_foo(%foo* %f), !dbg !18
184-
call void @__user_init_foo(%foo* %f), !dbg !18
185-
%something_to_initialize = getelementptr inbounds %foo, %foo* %f, i32 0, i32 0, !dbg !18
186-
%load_something_to_initialize = load i16, i16* %something_to_initialize, align 2, !dbg !18
187-
store i16 %load_something_to_initialize, i16* getelementptr inbounds (%mainProg, %mainProg* @mainProg_instance, i32 0, i32 0), align 2, !dbg !18
188-
call void @mainProg(%mainProg* @mainProg_instance), !dbg !19
189-
%main_ret = load i16, i16* %main, align 2, !dbg !20
190-
ret i16 %main_ret, !dbg !20
183+
call void @__init_foo(%foo* %f), !dbg !21
184+
call void @__user_init_foo(%foo* %f), !dbg !21
185+
%something_to_initialize = getelementptr inbounds %foo, %foo* %f, i32 0, i32 1, !dbg !21
186+
%load_something_to_initialize = load i16, i16* %something_to_initialize, align 2, !dbg !21
187+
store i16 %load_something_to_initialize, i16* getelementptr inbounds (%mainProg, %mainProg* @mainProg_instance, i32 0, i32 0), align 2, !dbg !21
188+
call void @mainProg(%mainProg* @mainProg_instance), !dbg !22
189+
%main_ret = load i16, i16* %main, align 2, !dbg !23
190+
ret i16 %main_ret, !dbg !23
191191
}
192192
193-
declare !dbg !21 void @foo(%foo*)
193+
declare !dbg !24 void @foo(%foo*)
194194
195195
declare void @__init_foo(%foo*)
196196
197-
declare !dbg !24 void @__user_init_foo(%foo*)
197+
declare void @__user_init_foo(%foo*)
198198
199-
declare !dbg !29 void @mainProg(%mainProg*)
199+
declare !dbg !27 void @mainProg(%mainProg*)
200200
201201
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
202202
declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
@@ -220,67 +220,66 @@ fn forward_declared_constant_is_also_marked_constant() {
220220
!7 = !{null}
221221
!8 = !{}
222222
!9 = !DILocalVariable(name: "f", scope: !4, file: !5, line: 4, type: !10, align: 64)
223-
!10 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", scope: !11, file: !11, line: 12, size: 16, align: 64, flags: DIFlagPublic, elements: !12, identifier: "foo")
223+
!10 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", scope: !11, file: !11, line: 12, size: 128, align: 64, flags: DIFlagPublic, elements: !12, identifier: "foo")
224224
!11 = !DIFile(filename: "external_file2.st", directory: "")
225-
!12 = !{!13}
226-
!13 = !DIDerivedType(tag: DW_TAG_member, name: "something_to_initialize", scope: !11, file: !11, line: 14, baseType: !14, size: 16, align: 16, flags: DIFlagPublic)
227-
!14 = !DIBasicType(name: "INT", size: 16, encoding: DW_ATE_signed, flags: DIFlagPublic)
228-
!15 = !DILocation(line: 4, column: 8, scope: !4)
229-
!16 = !DILocalVariable(name: "main", scope: !4, file: !5, line: 2, type: !14, align: 16)
230-
!17 = !DILocation(line: 2, column: 13, scope: !4)
231-
!18 = !DILocation(line: 0, scope: !4)
232-
!19 = !DILocation(line: 6, column: 8, scope: !4)
233-
!20 = !DILocation(line: 7, column: 4, scope: !4)
234-
!21 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !11, file: !11, line: 12, type: !22, scopeLine: 16, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !8)
235-
!22 = !DISubroutineType(flags: DIFlagPublic, types: !23)
236-
!23 = !{null, !10}
237-
!24 = distinct !DISubprogram(name: "__user_init_foo", linkageName: "__user_init_foo", scope: !25, file: !25, type: !26, scopeLine: 1, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !8)
238-
!25 = !DIFile(filename: "__initializers", directory: "")
239-
!26 = !DISubroutineType(flags: DIFlagPublic, types: !27)
240-
!27 = !{null, !28}
241-
!28 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__auto_pointer_to_foo", baseType: !10, size: 64, align: 64, dwarfAddressSpace: 1)
242-
!29 = distinct !DISubprogram(name: "mainProg", linkageName: "mainProg", scope: !11, file: !11, line: 6, type: !30, scopeLine: 10, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !8)
243-
!30 = !DISubroutineType(flags: DIFlagPublic, types: !31)
244-
!31 = !{null, !32, !14}
245-
!32 = !DICompositeType(tag: DW_TAG_structure_type, name: "mainProg", scope: !11, file: !11, line: 6, size: 16, align: 64, flags: DIFlagPublic, elements: !33, identifier: "mainProg")
246-
!33 = !{!34}
247-
!34 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !11, file: !11, line: 8, baseType: !14, size: 16, align: 16, flags: DIFlagPublic)
225+
!12 = !{!13, !16}
226+
!13 = !DIDerivedType(tag: DW_TAG_member, name: "__vtable", scope: !11, file: !11, baseType: !14, size: 64, align: 64, flags: DIFlagPublic)
227+
!14 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__VOID_POINTER", baseType: !15, size: 64, align: 64, dwarfAddressSpace: 1)
228+
!15 = !DIBasicType(name: "__VOID", encoding: DW_ATE_unsigned, flags: DIFlagPublic)
229+
!16 = !DIDerivedType(tag: DW_TAG_member, name: "something_to_initialize", scope: !11, file: !11, line: 14, baseType: !17, size: 16, align: 16, offset: 64, flags: DIFlagPublic)
230+
!17 = !DIBasicType(name: "INT", size: 16, encoding: DW_ATE_signed, flags: DIFlagPublic)
231+
!18 = !DILocation(line: 4, column: 8, scope: !4)
232+
!19 = !DILocalVariable(name: "main", scope: !4, file: !5, line: 2, type: !17, align: 16)
233+
!20 = !DILocation(line: 2, column: 13, scope: !4)
234+
!21 = !DILocation(line: 0, scope: !4)
235+
!22 = !DILocation(line: 6, column: 8, scope: !4)
236+
!23 = !DILocation(line: 7, column: 4, scope: !4)
237+
!24 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !11, file: !11, line: 12, type: !25, scopeLine: 16, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !8)
238+
!25 = !DISubroutineType(flags: DIFlagPublic, types: !26)
239+
!26 = !{null, !10}
240+
!27 = distinct !DISubprogram(name: "mainProg", linkageName: "mainProg", scope: !11, file: !11, line: 6, type: !28, scopeLine: 10, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !8)
241+
!28 = !DISubroutineType(flags: DIFlagPublic, types: !29)
242+
!29 = !{null, !30, !17}
243+
!30 = !DICompositeType(tag: DW_TAG_structure_type, name: "mainProg", scope: !11, file: !11, line: 6, size: 16, align: 64, flags: DIFlagPublic, elements: !31, identifier: "mainProg")
244+
!31 = !{!32}
245+
!32 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !11, file: !11, line: 8, baseType: !17, size: 16, align: 16, flags: DIFlagPublic)
248246
249247
; ModuleID = 'external_file2.st'
250248
source_filename = "external_file2.st"
251249
target datalayout = "[filtered]"
252250
target triple = "[filtered]"
253251
254252
%mainProg = type { i16 }
255-
%foo = type { i16 }
253+
%foo = type { i32*, i16 }
256254
257255
@a = unnamed_addr constant i16 10, !dbg !0
258256
@mainProg_instance = global %mainProg zeroinitializer, !dbg !5
259-
@__foo__init = unnamed_addr constant %foo { i16 20 }, !dbg !10
257+
@__foo__init = unnamed_addr constant %foo { i32* null, i16 20 }, !dbg !10
260258
261-
define void @mainProg(%mainProg* %0) !dbg !21 {
259+
define void @mainProg(%mainProg* %0) !dbg !24 {
262260
entry:
263-
call void @llvm.dbg.declare(metadata %mainProg* %0, metadata !25, metadata !DIExpression()), !dbg !26
261+
call void @llvm.dbg.declare(metadata %mainProg* %0, metadata !28, metadata !DIExpression()), !dbg !29
264262
%a = getelementptr inbounds %mainProg, %mainProg* %0, i32 0, i32 0
265-
ret void, !dbg !26
263+
ret void, !dbg !29
266264
}
267265
268-
define void @foo(%foo* %0) !dbg !27 {
266+
define void @foo(%foo* %0) !dbg !30 {
269267
entry:
270-
call void @llvm.dbg.declare(metadata %foo* %0, metadata !30, metadata !DIExpression()), !dbg !31
268+
call void @llvm.dbg.declare(metadata %foo* %0, metadata !33, metadata !DIExpression()), !dbg !34
271269
%this = alloca %foo*, align 8
272270
store %foo* %0, %foo** %this, align 8
273-
%something_to_initialize = getelementptr inbounds %foo, %foo* %0, i32 0, i32 0
274-
ret void, !dbg !31
271+
%__vtable = getelementptr inbounds %foo, %foo* %0, i32 0, i32 0
272+
%something_to_initialize = getelementptr inbounds %foo, %foo* %0, i32 0, i32 1
273+
ret void, !dbg !34
275274
}
276275
277276
; Function Attrs: nofree nosync nounwind readnone speculatable willreturn
278277
declare void @llvm.dbg.declare(metadata, metadata, metadata) #0
279278
280279
attributes #0 = { nofree nosync nounwind readnone speculatable willreturn }
281280
282-
!llvm.module.flags = !{!16, !17}
283-
!llvm.dbg.cu = !{!18}
281+
!llvm.module.flags = !{!19, !20}
282+
!llvm.dbg.cu = !{!21}
284283
285284
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
286285
!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !2, line: 3, type: !3, isLocal: false, isDefinition: true)
@@ -295,33 +294,36 @@ fn forward_declared_constant_is_also_marked_constant() {
295294
!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression())
296295
!11 = distinct !DIGlobalVariable(name: "__foo__init", scope: !2, file: !2, line: 12, type: !12, isLocal: false, isDefinition: true)
297296
!12 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !13)
298-
!13 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", scope: !2, file: !2, line: 12, size: 16, align: 64, flags: DIFlagPublic, elements: !14, identifier: "foo")
299-
!14 = !{!15}
300-
!15 = !DIDerivedType(tag: DW_TAG_member, name: "something_to_initialize", scope: !2, file: !2, line: 14, baseType: !4, size: 16, align: 16, flags: DIFlagPublic)
301-
!16 = !{i32 2, !"Dwarf Version", i32 5}
302-
!17 = !{i32 2, !"Debug Info Version", i32 3}
303-
!18 = distinct !DICompileUnit(language: DW_LANG_C, file: !19, producer: "RuSTy Structured text Compiler", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !20, splitDebugInlining: false)
304-
!19 = !DIFile(filename: "external_file2.st", directory: "root")
305-
!20 = !{!0, !5, !10}
306-
!21 = distinct !DISubprogram(name: "mainProg", linkageName: "mainProg", scope: !2, file: !2, line: 6, type: !22, scopeLine: 10, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !18, retainedNodes: !24)
307-
!22 = !DISubroutineType(flags: DIFlagPublic, types: !23)
308-
!23 = !{null, !7, !4}
309-
!24 = !{}
310-
!25 = !DILocalVariable(name: "mainProg", scope: !21, file: !2, line: 10, type: !7)
311-
!26 = !DILocation(line: 10, column: 4, scope: !21)
312-
!27 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !2, file: !2, line: 12, type: !28, scopeLine: 16, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !18, retainedNodes: !24)
313-
!28 = !DISubroutineType(flags: DIFlagPublic, types: !29)
314-
!29 = !{null, !13}
315-
!30 = !DILocalVariable(name: "foo", scope: !27, file: !2, line: 16, type: !13)
316-
!31 = !DILocation(line: 16, column: 4, scope: !27)
297+
!13 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", scope: !2, file: !2, line: 12, size: 128, align: 64, flags: DIFlagPublic, elements: !14, identifier: "foo")
298+
!14 = !{!15, !18}
299+
!15 = !DIDerivedType(tag: DW_TAG_member, name: "__vtable", scope: !2, file: !2, baseType: !16, size: 64, align: 64, flags: DIFlagPublic)
300+
!16 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "__VOID_POINTER", baseType: !17, size: 64, align: 64, dwarfAddressSpace: 1)
301+
!17 = !DIBasicType(name: "__VOID", encoding: DW_ATE_unsigned, flags: DIFlagPublic)
302+
!18 = !DIDerivedType(tag: DW_TAG_member, name: "something_to_initialize", scope: !2, file: !2, line: 14, baseType: !4, size: 16, align: 16, offset: 64, flags: DIFlagPublic)
303+
!19 = !{i32 2, !"Dwarf Version", i32 5}
304+
!20 = !{i32 2, !"Debug Info Version", i32 3}
305+
!21 = distinct !DICompileUnit(language: DW_LANG_C, file: !22, producer: "RuSTy Structured text Compiler", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !23, splitDebugInlining: false)
306+
!22 = !DIFile(filename: "external_file2.st", directory: "root")
307+
!23 = !{!0, !5, !10}
308+
!24 = distinct !DISubprogram(name: "mainProg", linkageName: "mainProg", scope: !2, file: !2, line: 6, type: !25, scopeLine: 10, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !21, retainedNodes: !27)
309+
!25 = !DISubroutineType(flags: DIFlagPublic, types: !26)
310+
!26 = !{null, !7, !4}
311+
!27 = !{}
312+
!28 = !DILocalVariable(name: "mainProg", scope: !24, file: !2, line: 10, type: !7)
313+
!29 = !DILocation(line: 10, column: 4, scope: !24)
314+
!30 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !2, file: !2, line: 12, type: !31, scopeLine: 16, flags: DIFlagPublic, spFlags: DISPFlagDefinition, unit: !21, retainedNodes: !27)
315+
!31 = !DISubroutineType(flags: DIFlagPublic, types: !32)
316+
!32 = !{null, !13}
317+
!33 = !DILocalVariable(name: "foo", scope: !30, file: !2, line: 16, type: !13)
318+
!34 = !DILocation(line: 16, column: 4, scope: !30)
317319
318320
; ModuleID = '__initializers'
319321
source_filename = "__initializers"
320322
target datalayout = "[filtered]"
321323
target triple = "[filtered]"
322324
323325
%mainProg = type { i16 }
324-
%foo = type { i16 }
326+
%foo = type { i32*, i16 }
325327
326328
@mainProg_instance = external global %mainProg
327329
@__foo__init = external unnamed_addr constant %foo
@@ -380,5 +382,5 @@ fn forward_declared_constant_is_also_marked_constant() {
380382
declare void @mainProg(%mainProg*)
381383
382384
declare void @__user_init_mainProg(%mainProg*)
383-
"###);
385+
"#);
384386
}

compiler/plc_source/src/source_location.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ impl SourceLocation {
422422
}
423423

424424
pub fn is_internal(&self) -> bool {
425-
self.file.is_internal()
425+
matches!(self.file, FileMarker::Internal(_)) | matches!(self.span, CodeSpan::None)
426426
}
427427

428428
pub fn is_builtin_internal(&self) -> bool {

libs/stdlib/src/bistable_functionblocks.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#[repr(C)]
22
#[derive(Debug, Default)]
33
pub struct SetResetParams {
4+
__vtable: usize,
45
set: bool,
56
reset: bool,
67
output: bool,
@@ -12,6 +13,21 @@ impl SetResetParams {
1213
}
1314
}
1415

16+
#[repr(C)]
17+
pub struct VTable {
18+
pub body: extern "C" fn(&mut SetResetParams),
19+
}
20+
21+
#[allow(non_upper_case_globals)]
22+
#[no_mangle]
23+
#[used]
24+
pub static __vtable_SR: VTable = VTable { body: SR };
25+
26+
#[allow(non_upper_case_globals)]
27+
#[no_mangle]
28+
#[used]
29+
pub static __SR__init: SetResetParams =
30+
SetResetParams { __vtable: 0, set: false, reset: false, output: false };
1531
///.
1632
/// Bistable function, set dominant
1733
///
@@ -21,6 +37,17 @@ pub extern "C" fn SR(params: &mut SetResetParams) {
2137
params.set_output(params.set | (!params.reset & params.output));
2238
}
2339

40+
#[allow(non_upper_case_globals)]
41+
#[no_mangle]
42+
#[used]
43+
pub static __vtable_RS: VTable = VTable { body: RS };
44+
45+
#[allow(non_upper_case_globals)]
46+
#[no_mangle]
47+
#[used]
48+
pub static __RS__init: SetResetParams =
49+
SetResetParams { __vtable: 0, set: false, reset: false, output: false };
50+
2451
///.
2552
/// Bistable function, reset dominant
2653
///

0 commit comments

Comments
 (0)