Skip to content

Commit e6c4a73

Browse files
committed
wip
1 parent 97c2cd8 commit e6c4a73

File tree

4 files changed

+161
-393
lines changed

4 files changed

+161
-393
lines changed

src/codegen/generators/expression_generator.rs

Lines changed: 82 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use std::fmt::Pointer;
2-
use std::{collections::HashSet, vec};
1+
// Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
32

43
use inkwell::{
54
builder::Builder,
@@ -10,6 +9,7 @@ use inkwell::{
109
},
1110
AddressSpace, FloatPredicate, IntPredicate,
1211
};
12+
use rustc_hash::FxHashSet;
1313

1414
use plc_ast::ast::Assignment;
1515
use plc_ast::{
@@ -23,7 +23,6 @@ use plc_diagnostics::diagnostics::{Diagnostic, INTERNAL_LLVM_ERROR};
2323
use plc_source::source_location::SourceLocation;
2424
use plc_util::convention::qualified_name;
2525

26-
// Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
2726
use crate::{
2827
codegen::{
2928
debug::{Debug, DebugBuilderEnum},
@@ -41,7 +40,6 @@ use crate::{
4140
StringEncoding, VarArgs, DINT_TYPE, INT_SIZE, INT_TYPE, LINT_TYPE,
4241
},
4342
};
44-
use rustc_hash::FxHashSet;
4543

4644
use super::{llvm::Llvm, statement_generator::FunctionContext, ADDRESS_SPACE_CONST, ADDRESS_SPACE_GENERIC};
4745

@@ -530,27 +528,13 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
530528
function_name: &str,
531529
parameters: Vec<&AstNode>,
532530
) -> 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);
541532
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-
}
549533

550534
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) {
554538
self.assign_output_value(&CallParameterAssignment {
555539
assignment_statement,
556540
function_name,
@@ -559,79 +543,56 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
559543
})?
560544
}
561545
}
546+
562547
Ok(())
563548
}
564549

565550
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(
569553
param_context.parameter_struct,
570554
param_context.function_name,
571-
param_context.assignment_statement,
555+
assignment,
572556
),
573557

574558
_ => self.generate_output_assignment(param_context),
575559
}
576560
}
577561

578-
fn temp_xxx(
562+
fn generate_bit_access(
579563
&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,
584568
) -> 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)
609570
else {
610-
unreachable!("Invalid direct-access expression: {left_statement:#?}")
571+
unreachable!("Invalid direct-access expression: {statement_lhs:#?}")
611572
};
612573

613-
let left_type = self.get_type_hint_for(target)?;
574+
let type_left = self.get_type_hint_for(target)?;
614575

615576
//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 =
617578
if let DataTypeInformation::Integer { semantic_size: Some(typesystem::U1_SIZE), .. } =
618-
*right_type.get_type_information()
579+
*type_rhs.get_type_information()
619580
{
620581
self.index.get_type_or_panic(typesystem::U1_TYPE)
621582
} else {
622-
right_type
583+
type_rhs
623584
};
624585

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();
626587

627588
//Build index
628589
if let Some((element, direct_access)) = access_sequence.split_first() {
629590
let mut index = if let AstStatement::DirectAccess(data, ..) = element.get_stmt() {
630591
self.generate_direct_access_index(
631592
&data.access,
632593
&data.index,
633-
right_type.get_type_information(),
634-
left_type,
594+
type_right.get_type_information(),
595+
type_left,
635596
)
636597
} else {
637598
//TODO: using the global context we could get a slice here
@@ -644,8 +605,8 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
644605
self.generate_direct_access_index(
645606
&data.access,
646607
&data.index,
647-
right_type.get_type_information(),
648-
left_type,
608+
type_right.get_type_information(),
609+
type_left,
649610
)
650611
} else {
651612
//TODO: using the global context we could get a slice here
@@ -657,28 +618,28 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
657618
}
658619
//Build mask for the index
659620
//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();
661622
let ones = rhs_type.const_all_ones();
662623

663624
//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");
665626
//Position the ones in their correct locations
666627
let shifted_mask = self.llvm.builder.build_left_shift(extended_mask, index, "shift");
667628
//Invert the mask
668629
let mask = self.llvm.builder.build_not(shifted_mask, "invert");
669630
//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");
671632

672633
//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, "");
674635
//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();
676637
//Shift left by the direct access
677638
let value = self.llvm.builder.build_left_shift(lhs, index, "value");
678639

679640
//OR the result and store it in the left side
680641
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);
682643
} else {
683644
unreachable!()
684645
}
@@ -687,11 +648,9 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
687648
}
688649

689650
fn generate_output_assignment(&self, context: &CallParameterAssignment) -> Result<(), Diagnostic> {
651+
let &CallParameterAssignment { assignment_statement, function_name, index, parameter_struct } =
652+
context;
690653
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;
695654

696655
let Some(parameter) = self.index.get_declared_parameter(function_name, index) else {
697656
panic!("or return?");
@@ -703,16 +662,16 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
703662
}
704663

705664
// TODO: How to trigger an empty statement here, this: `FOO(Q => );`?
706-
if expression.is_empty_statement() {
665+
if assignment_statement.is_empty_statement() {
707666
// Something like `foo(out1 => )`, which means we can just return here because no
708667
// assignment should happen
709668
return Ok(());
710669
}
711670

712671
// FOO(x => y)
713672
// 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() => {
716675
let _pou = self.index.find_pou(function_name).unwrap();
717676
let _struct = &_pou.find_instance_struct_type(self.index).unwrap().information;
718677
let DataTypeInformation::Struct { members, .. } = _struct else { panic!() };
@@ -722,38 +681,39 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
722681
let AstStatement::ReferenceExpr(ReferenceExpr {
723682
access: ReferenceAccess::Member(member),
724683
base,
725-
}) = &expression.get_stmt()
684+
}) = &assignment_statement.get_stmt()
726685
else {
727686
unreachable!("must be a bitaccess, will return early for all other cases")
728687
};
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()?;
731691

732692
if let AstStatement::DirectAccess(_) = member.as_ref().get_stmt() {
733693
let (Some(base), S_) = (base, ..) else { panic!() };
734694
// 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();
741698

742699
// Step 2
743700
let q_lvalue =
744701
self.llvm.builder.build_struct_gep(parameter_struct, index, "bbb").unwrap();
745702

746703
// lhs = lvalue
747704
// 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)?;
749707
};
750708
}
751709

752710
_ => {
753-
let assigned_output = self.generate_lvalue(expression)?;
711+
let assigned_output = self.generate_lvalue(assignment_statement)?;
754712

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();
757717

758718
let output = builder.build_struct_gep(parameter_struct, index, "").map_err(|_| {
759719
Diagnostic::codegen_error(
@@ -772,7 +732,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
772732
self.generate_string_store(
773733
assigned_output,
774734
assigned_output_type,
775-
expression.get_location(),
735+
assignment_statement.get_location(),
776736
output,
777737
output_value_type,
778738
parameter.source_location.clone(),
@@ -791,13 +751,11 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
791751
&self,
792752
parameter_struct: PointerValue<'ink>,
793753
function_name: &str,
794-
assignment: &AstNode,
754+
assignment: &Assignment,
795755
) -> Result<(), Diagnostic> {
796-
let AstStatement::OutputAssignment(Assignment { left, right, .. }) = assignment.get_stmt() else {
797-
todo!()
798-
};
756+
let Assignment { left, right } = assignment;
799757

800-
if let Some(StatementAnnotation::Variable { qualified_name, .. }) = self.annotations.get(&left) {
758+
if let Some(StatementAnnotation::Variable { qualified_name, .. }) = self.annotations.get(left) {
801759
let parameter = self
802760
.index
803761
.find_fully_qualified_variable(qualified_name)
@@ -811,6 +769,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
811769
parameter_struct,
812770
})?
813771
};
772+
814773
Ok(())
815774
}
816775

@@ -2866,3 +2825,29 @@ fn int_value_multiply_accumulate<'ink>(
28662825
}
28672826
llvm.builder.build_load(accum, "accessor").into_int_value()
28682827
}
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

Comments
 (0)