1
- use std:: fmt:: Pointer ;
2
- use std:: { collections:: HashSet , vec} ;
1
+ // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
3
2
4
3
use inkwell:: {
5
4
builder:: Builder ,
@@ -10,6 +9,7 @@ use inkwell::{
10
9
} ,
11
10
AddressSpace , FloatPredicate , IntPredicate ,
12
11
} ;
12
+ use rustc_hash:: FxHashSet ;
13
13
14
14
use plc_ast:: ast:: Assignment ;
15
15
use plc_ast:: {
@@ -23,7 +23,6 @@ use plc_diagnostics::diagnostics::{Diagnostic, INTERNAL_LLVM_ERROR};
23
23
use plc_source:: source_location:: SourceLocation ;
24
24
use plc_util:: convention:: qualified_name;
25
25
26
- // Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
27
26
use crate :: {
28
27
codegen:: {
29
28
debug:: { Debug , DebugBuilderEnum } ,
@@ -41,7 +40,6 @@ use crate::{
41
40
StringEncoding , VarArgs , DINT_TYPE , INT_SIZE , INT_TYPE , LINT_TYPE ,
42
41
} ,
43
42
} ;
44
- use rustc_hash:: FxHashSet ;
45
43
46
44
use super :: { llvm:: Llvm , statement_generator:: FunctionContext , ADDRESS_SPACE_CONST , ADDRESS_SPACE_GENERIC } ;
47
45
@@ -530,27 +528,13 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
530
528
function_name : & str ,
531
529
parameters : Vec < & AstNode > ,
532
530
) -> Result < ( ) , Diagnostic > {
533
- // self.index.get_declared_parameter(function_name, index)
534
-
535
- // Before
536
- // parameter = vec![foo, bar, baz]
537
- // ^^^ output, index = 1
538
- // After (filtered)
539
- // parameter = vec![bar]
540
-
531
+ let implicit = is_implicit_function_call ( & parameters) ;
541
532
let pou_info = self . index . get_declared_parameters ( function_name) ;
542
- let mut implicit = true ;
543
- for statement in parameters. iter ( ) {
544
- if statement. is_assignment ( ) || statement. is_output_assignment ( ) {
545
- implicit = false ;
546
- break ;
547
- }
548
- }
549
533
550
534
for ( index, assignment_statement) in parameters. into_iter ( ) . enumerate ( ) {
551
- let temp = pou_info. get ( index) . is_some_and ( |it| it . get_variable_type ( ) . is_output ( ) ) ;
552
- // TODO: Filter this
553
- if assignment_statement. is_output_assignment ( ) || ( implicit && temp ) {
535
+ let is_output = pou_info. get ( index) . is_some_and ( |param| param . get_variable_type ( ) . is_output ( ) ) ;
536
+
537
+ if assignment_statement. is_output_assignment ( ) || ( implicit && is_output ) {
554
538
self . assign_output_value ( & CallParameterAssignment {
555
539
assignment_statement,
556
540
function_name,
@@ -559,79 +543,56 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
559
543
} ) ?
560
544
}
561
545
}
546
+
562
547
Ok ( ( ) )
563
548
}
564
549
565
550
fn assign_output_value ( & self , param_context : & CallParameterAssignment ) -> Result < ( ) , Diagnostic > {
566
- match param_context. assignment_statement . get_stmt ( ) {
567
- // TODO: AstStatement::Assignment should not be a part of this?
568
- AstStatement :: OutputAssignment ( data) => self . generate_explicit_output_assignment (
551
+ match & param_context. assignment_statement . stmt {
552
+ AstStatement :: OutputAssignment ( assignment) => self . generate_explicit_output_assignment (
569
553
param_context. parameter_struct ,
570
554
param_context. function_name ,
571
- param_context . assignment_statement ,
555
+ assignment ,
572
556
) ,
573
557
574
558
_ => self . generate_output_assignment ( param_context) ,
575
559
}
576
560
}
577
561
578
- fn temp_xxx (
562
+ fn generate_bit_access (
579
563
& self ,
580
- left_lvalue : PointerValue ,
581
- right_lvalue : PointerValue ,
582
- left_statement : & AstNode ,
583
- right_type : & DataType ,
564
+ lvalue_lhs : PointerValue ,
565
+ lvalue_rhs : PointerValue ,
566
+ statement_lhs : & AstNode ,
567
+ type_rhs : & DataType ,
584
568
) -> Result < ( ) , Diagnostic > {
585
- /// when generating an assignment to a direct-access (e.g. a.b.c.%W3.%X2 := 2;)
586
- /// we want to deconstruct the sequence into the base-statement (a.b.c) and the sequence
587
- /// of direct-access commands (vec![%W3, %X2])
588
- fn collect_base_and_direct_access_for_assignment (
589
- left_statement : & AstNode ,
590
- ) -> Option < ( & AstNode , Vec < & AstNode > ) > {
591
- let mut current = Some ( left_statement) ;
592
- let mut access_sequence = Vec :: new ( ) ;
593
- while let Some ( AstStatement :: ReferenceExpr ( ReferenceExpr {
594
- access : ReferenceAccess :: Member ( m) ,
595
- base,
596
- } ) ) = current. map ( |it| it. get_stmt ( ) )
597
- {
598
- if matches ! ( m. get_stmt( ) , AstStatement :: DirectAccess { .. } ) {
599
- access_sequence. insert ( 0 , m. as_ref ( ) ) ;
600
- current = base. as_deref ( ) ;
601
- } else {
602
- break ;
603
- }
604
- }
605
- current. zip ( Some ( access_sequence) )
606
- }
607
-
608
- let Some ( ( target, access_sequence) ) = collect_base_and_direct_access_for_assignment ( left_statement)
569
+ let Some ( ( target, access_sequence) ) = collect_base_and_direct_access_for_assignment ( statement_lhs)
609
570
else {
610
- unreachable ! ( "Invalid direct-access expression: {left_statement :#?}" )
571
+ unreachable ! ( "Invalid direct-access expression: {statement_lhs :#?}" )
611
572
} ;
612
573
613
- let left_type = self . get_type_hint_for ( target) ?;
574
+ let type_left = self . get_type_hint_for ( target) ?;
614
575
615
576
//special case if we deal with a single bit, then we need to switch to a faked u1 type
616
- let right_type =
577
+ let type_right =
617
578
if let DataTypeInformation :: Integer { semantic_size : Some ( typesystem:: U1_SIZE ) , .. } =
618
- * right_type . get_type_information ( )
579
+ * type_rhs . get_type_information ( )
619
580
{
620
581
self . index . get_type_or_panic ( typesystem:: U1_TYPE )
621
582
} else {
622
- right_type
583
+ type_rhs
623
584
} ;
624
585
625
- let left_value = self . llvm . builder . build_load ( left_lvalue , "" ) . into_int_value ( ) ;
586
+ let value_lhs = self . llvm . builder . build_load ( lvalue_lhs , "" ) . into_int_value ( ) ;
626
587
627
588
//Build index
628
589
if let Some ( ( element, direct_access) ) = access_sequence. split_first ( ) {
629
590
let mut index = if let AstStatement :: DirectAccess ( data, ..) = element. get_stmt ( ) {
630
591
self . generate_direct_access_index (
631
592
& data. access ,
632
593
& data. index ,
633
- right_type . get_type_information ( ) ,
634
- left_type ,
594
+ type_right . get_type_information ( ) ,
595
+ type_left ,
635
596
)
636
597
} else {
637
598
//TODO: using the global context we could get a slice here
@@ -644,8 +605,8 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
644
605
self . generate_direct_access_index (
645
606
& data. access ,
646
607
& data. index ,
647
- right_type . get_type_information ( ) ,
648
- left_type ,
608
+ type_right . get_type_information ( ) ,
609
+ type_left ,
649
610
)
650
611
} else {
651
612
//TODO: using the global context we could get a slice here
@@ -657,28 +618,28 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
657
618
}
658
619
//Build mask for the index
659
620
//Get the target bit type as all ones
660
- let rhs_type = self . llvm_index . get_associated_type ( right_type . get_name ( ) ) ?. into_int_type ( ) ;
621
+ let rhs_type = self . llvm_index . get_associated_type ( type_right . get_name ( ) ) ?. into_int_type ( ) ;
661
622
let ones = rhs_type. const_all_ones ( ) ;
662
623
663
624
//Extend the mask to the target type
664
- let extended_mask = self . llvm . builder . build_int_z_extend ( ones, left_value . get_type ( ) , "ext" ) ;
625
+ let extended_mask = self . llvm . builder . build_int_z_extend ( ones, value_lhs . get_type ( ) , "ext" ) ;
665
626
//Position the ones in their correct locations
666
627
let shifted_mask = self . llvm . builder . build_left_shift ( extended_mask, index, "shift" ) ;
667
628
//Invert the mask
668
629
let mask = self . llvm . builder . build_not ( shifted_mask, "invert" ) ;
669
630
//And the result with the mask to erase the set bits at the target location
670
- let and_value = self . llvm . builder . build_and ( left_value , mask, "erase" ) ;
631
+ let and_value = self . llvm . builder . build_and ( value_lhs , mask, "erase" ) ;
671
632
672
633
//Generate an expression for the right size
673
- let right = self . llvm . builder . build_load ( right_lvalue , "" ) ;
634
+ let right = self . llvm . builder . build_load ( lvalue_rhs , "" ) ;
674
635
//Cast the right side to the left side type
675
- let lhs = cast_if_needed ! ( self , left_type , right_type , right, None ) . into_int_value ( ) ;
636
+ let lhs = cast_if_needed ! ( self , type_left , type_right , right, None ) . into_int_value ( ) ;
676
637
//Shift left by the direct access
677
638
let value = self . llvm . builder . build_left_shift ( lhs, index, "value" ) ;
678
639
679
640
//OR the result and store it in the left side
680
641
let or_value = self . llvm . builder . build_or ( and_value, value, "or" ) ;
681
- self . llvm . builder . build_store ( left_lvalue , or_value) ;
642
+ self . llvm . builder . build_store ( lvalue_lhs , or_value) ;
682
643
} else {
683
644
unreachable ! ( )
684
645
}
@@ -687,11 +648,9 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
687
648
}
688
649
689
650
fn generate_output_assignment ( & self , context : & CallParameterAssignment ) -> Result < ( ) , Diagnostic > {
651
+ let & CallParameterAssignment { assignment_statement, function_name, index, parameter_struct } =
652
+ context;
690
653
let builder = & self . llvm . builder ;
691
- let expression = context. assignment_statement ;
692
- let parameter_struct = context. parameter_struct ;
693
- let function_name = context. function_name ;
694
- let index = context. index ;
695
654
696
655
let Some ( parameter) = self . index . get_declared_parameter ( function_name, index) else {
697
656
panic ! ( "or return?" ) ;
@@ -703,16 +662,16 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
703
662
}
704
663
705
664
// TODO: How to trigger an empty statement here, this: `FOO(Q => );`?
706
- if expression . is_empty_statement ( ) {
665
+ if assignment_statement . is_empty_statement ( ) {
707
666
// Something like `foo(out1 => )`, which means we can just return here because no
708
667
// assignment should happen
709
668
return Ok ( ( ) ) ;
710
669
}
711
670
712
671
// FOO(x => y)
713
672
// FOO(x => y.0)
714
- match expression . get_stmt ( ) {
715
- AstStatement :: ReferenceExpr ( _) if expression . has_direct_access ( ) => {
673
+ match assignment_statement . get_stmt ( ) {
674
+ AstStatement :: ReferenceExpr ( _) if assignment_statement . has_direct_access ( ) => {
716
675
let _pou = self . index . find_pou ( function_name) . unwrap ( ) ;
717
676
let _struct = & _pou. find_instance_struct_type ( self . index ) . unwrap ( ) . information ;
718
677
let DataTypeInformation :: Struct { members, .. } = _struct else { panic ! ( ) } ;
@@ -722,38 +681,39 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
722
681
let AstStatement :: ReferenceExpr ( ReferenceExpr {
723
682
access : ReferenceAccess :: Member ( member) ,
724
683
base,
725
- } ) = & expression . get_stmt ( )
684
+ } ) = & assignment_statement . get_stmt ( )
726
685
else {
727
686
unreachable ! ( "must be a bitaccess, will return early for all other cases" )
728
687
} ;
729
- let base_value_rvalue =
730
- base. as_ref ( ) . map ( |it| self . generate_expression_value ( it) ) . transpose ( ) ?;
688
+ // TODO: Do we need this?
689
+ // let base_value_rvalue =
690
+ // base.as_ref().map(|it| self.generate_expression_value(it)).transpose()?;
731
691
732
692
if let AstStatement :: DirectAccess ( _) = member. as_ref ( ) . get_stmt ( ) {
733
693
let ( Some ( base) , S_ ) = ( base, ..) else { panic ! ( ) } ;
734
694
// Step 1
735
- let error_bits_lvalue = self
736
- . llvm_index
737
- . find_loaded_associated_variable_value (
738
- self . annotations . get_qualified_name ( base) . unwrap ( ) ,
739
- )
740
- . unwrap ( ) ;
695
+ let var = dbg ! ( self . annotations. get_qualified_name( base) ) . unwrap ( ) ;
696
+ let error_bits_lvalue =
697
+ self . llvm_index . find_loaded_associated_variable_value ( var) . unwrap ( ) ;
741
698
742
699
// Step 2
743
700
let q_lvalue =
744
701
self . llvm . builder . build_struct_gep ( parameter_struct, index, "bbb" ) . unwrap ( ) ;
745
702
746
703
// lhs = lvalue
747
704
// rhs = astnode
748
- self . temp_xxx ( error_bits_lvalue, q_lvalue, & expression, & dt) ?;
705
+ dbg ! ( & assignment_statement) ;
706
+ self . generate_bit_access ( error_bits_lvalue, q_lvalue, & assignment_statement, & dt) ?;
749
707
} ;
750
708
}
751
709
752
710
_ => {
753
- let assigned_output = self . generate_lvalue ( expression ) ?;
711
+ let assigned_output = self . generate_lvalue ( assignment_statement ) ?;
754
712
755
- let assigned_output_type =
756
- self . annotations . get_type_or_void ( expression, self . index ) . get_type_information ( ) ;
713
+ let assigned_output_type = self
714
+ . annotations
715
+ . get_type_or_void ( assignment_statement, self . index )
716
+ . get_type_information ( ) ;
757
717
758
718
let output = builder. build_struct_gep ( parameter_struct, index, "" ) . map_err ( |_| {
759
719
Diagnostic :: codegen_error (
@@ -772,7 +732,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
772
732
self . generate_string_store (
773
733
assigned_output,
774
734
assigned_output_type,
775
- expression . get_location ( ) ,
735
+ assignment_statement . get_location ( ) ,
776
736
output,
777
737
output_value_type,
778
738
parameter. source_location . clone ( ) ,
@@ -791,13 +751,11 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
791
751
& self ,
792
752
parameter_struct : PointerValue < ' ink > ,
793
753
function_name : & str ,
794
- assignment : & AstNode ,
754
+ assignment : & Assignment ,
795
755
) -> Result < ( ) , Diagnostic > {
796
- let AstStatement :: OutputAssignment ( Assignment { left, right, .. } ) = assignment. get_stmt ( ) else {
797
- todo ! ( )
798
- } ;
756
+ let Assignment { left, right } = assignment;
799
757
800
- if let Some ( StatementAnnotation :: Variable { qualified_name, .. } ) = self . annotations . get ( & left) {
758
+ if let Some ( StatementAnnotation :: Variable { qualified_name, .. } ) = self . annotations . get ( left) {
801
759
let parameter = self
802
760
. index
803
761
. find_fully_qualified_variable ( qualified_name)
@@ -811,6 +769,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
811
769
parameter_struct,
812
770
} ) ?
813
771
} ;
772
+
814
773
Ok ( ( ) )
815
774
}
816
775
@@ -2866,3 +2825,29 @@ fn int_value_multiply_accumulate<'ink>(
2866
2825
}
2867
2826
llvm. builder . build_load ( accum, "accessor" ) . into_int_value ( )
2868
2827
}
2828
+
2829
+ /// Returns false if any argument in the given list is an (output-)assignment and true otherwise
2830
+ fn is_implicit_function_call ( arguments : & Vec < & AstNode > ) -> bool {
2831
+ !arguments. iter ( ) . any ( |argument| argument. is_assignment ( ) || argument. is_output_assignment ( ) )
2832
+ }
2833
+
2834
+ /// when generating an assignment to a direct-access (e.g. a.b.c.%W3.%X2 := 2;)
2835
+ /// we want to deconstruct the sequence into the base-statement (a.b.c) and the sequence
2836
+ /// of direct-access commands (vec![%W3, %X2])
2837
+ fn collect_base_and_direct_access_for_assignment (
2838
+ left_statement : & AstNode ,
2839
+ ) -> Option < ( & AstNode , Vec < & AstNode > ) > {
2840
+ let mut current = Some ( left_statement) ;
2841
+ let mut access_sequence = Vec :: new ( ) ;
2842
+ while let Some ( AstStatement :: ReferenceExpr ( ReferenceExpr { access : ReferenceAccess :: Member ( m) , base } ) ) =
2843
+ current. map ( |it| it. get_stmt ( ) )
2844
+ {
2845
+ if matches ! ( m. get_stmt( ) , AstStatement :: DirectAccess { .. } ) {
2846
+ access_sequence. insert ( 0 , m. as_ref ( ) ) ;
2847
+ current = base. as_deref ( ) ;
2848
+ } else {
2849
+ break ;
2850
+ }
2851
+ }
2852
+ current. zip ( Some ( access_sequence) )
2853
+ }
0 commit comments