Skip to content
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

fix: Bitaccess for VAR_OUTPUT #1214

Merged
merged 34 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
da89a64
init
mhasel Apr 22, 2024
19e3522
working for example in github issue
volsa Apr 23, 2024
9a9fe84
Add tests
volsa Apr 23, 2024
483ba07
pain
volsa Apr 23, 2024
88ba4de
rip
volsa Apr 24, 2024
afe00ab
working state
volsa Apr 24, 2024
a25097a
working state
volsa Apr 25, 2024
cff0f62
wip
volsa Apr 25, 2024
2d5332f
wip
volsa Apr 25, 2024
3b8b0fb
wip
volsa Apr 30, 2024
b620689
fmt
volsa May 22, 2024
b0fdc68
Merge branch 'master' of https://github.com/plc-lang/rusty into outpu…
volsa May 22, 2024
8964391
Merge branch 'master' of https://github.com/plc-lang/rusty into outpu…
volsa May 23, 2024
467e5ad
Fix test input
volsa May 23, 2024
268c59f
fix tests
volsa May 23, 2024
97c2cd8
Update incorrect counter test input
volsa May 23, 2024
58cfcec
wip
volsa May 23, 2024
d253dc1
Merge branch 'master' of https://github.com/plc-lang/rusty into outpu…
volsa May 24, 2024
c2ef597
Update snapshots
volsa May 27, 2024
c252ee7
Merge branch 'master' of https://github.com/plc-lang/rusty into outpu…
volsa May 27, 2024
6cdf797
refactor: Merge duplicate bit-access logic code
volsa May 29, 2024
e3a1686
Update tests
volsa May 29, 2024
e809430
cleanup
volsa May 29, 2024
4f4eb80
Merge branch 'master' into output-bitaccess
volsa Jun 3, 2024
b3d51d2
format
volsa Jun 5, 2024
43f72ea
merge
volsa Jun 5, 2024
8570806
Merge branch 'output-bitaccess' of https://github.com/plc-lang/rusty …
volsa Jun 5, 2024
ffd2179
feedback
volsa Jun 7, 2024
4d9ce53
Merge branch 'master' into output-bitaccess
volsa Jun 11, 2024
6cbfc24
Merge branch 'master' into output-bitaccess
volsa Jun 14, 2024
bf3354e
Merge branch 'master' into output-bitaccess
volsa Jun 18, 2024
b13e53e
Merge branch 'master' of https://github.com/plc-lang/rusty into outpu…
volsa Jun 19, 2024
f00ec73
Update snapshots
volsa Jun 19, 2024
4c4576a
Merge branch 'output-bitaccess' of https://github.com/plc-lang/rusty …
volsa Jun 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions compiler/plc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,14 @@ impl AstNode {
matches!(self.stmt, AstStatement::EmptyStatement(..))
}

pub fn is_assignment(&self) -> bool {
matches!(self.stmt, AstStatement::Assignment(..))
}

pub fn is_output_assignment(&self) -> bool {
matches!(self.stmt, AstStatement::OutputAssignment(..))
}

pub fn is_reference(&self) -> bool {
matches!(self.stmt, AstStatement::ReferenceExpr(..))
}
Expand Down
144 changes: 72 additions & 72 deletions libs/stdlib/tests/counters_tests.rs

Large diffs are not rendered by default.

357 changes: 272 additions & 85 deletions src/codegen/generators/expression_generator.rs

Large diffs are not rendered by default.

107 changes: 21 additions & 86 deletions src/codegen/generators/statement_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use super::{
llvm::Llvm,
};
use crate::{
codegen::{debug::Debug, llvm_typesystem::cast_if_needed},
codegen::debug::Debug,
codegen::{debug::DebugBuilderEnum, LlvmTypedIndex},
index::{ImplementationIndexEntry, Index},
resolver::{AnnotationMap, AstAnnotations, StatementAnnotation},
typesystem::{self, DataTypeInformation},
typesystem::DataTypeInformation,
};
use inkwell::{
basic_block::BasicBlock,
Expand Down Expand Up @@ -244,7 +244,7 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
self.register_debug_location(left_statement);
//TODO: Looks hacky, the strings will be similar so we should look into making the assignment a bit nicer.
if left_statement.has_direct_access() {
return self.generate_direct_access_assignment(left_statement, right_statement);
return self.generate_assignment_statement_direct_access(left_statement, right_statement);
}
//TODO: Also hacky but for now we cannot generate assignments for hardware access
if matches!(left_statement.get_stmt(), AstStatement::HardwareAccess { .. }) {
Expand Down Expand Up @@ -279,96 +279,32 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
self.debug.set_debug_location(self.llvm, &self.function_context.function, line, column);
}

fn generate_direct_access_assignment(
fn generate_assignment_statement_direct_access(
&self,
left_statement: &AstNode,
right_statement: &AstNode,
) -> Result<(), Diagnostic> {
//TODO : Validation
let exp_gen = self.create_expr_generator();

// given a complex direct-access assignemnt: a.b.c.%W3,%X1
// we want to deconstruct the targe-part (a.b.c) and the direct-access sequence (%W3.%X1)
let Some((target, access_sequence)) = collect_base_and_direct_access_for_assignment(left_statement)
else {
// Left pointer
let Some((base, _)) = collect_base_and_direct_access_for_assignment(left_statement) else {
unreachable!("Invalid direct-access expression: {left_statement:#?}")
};
let left_expr_value = exp_gen.generate_expression_value(base)?;
let left_value = left_expr_value.as_r_value(self.llvm, None).into_int_value();
let left_pointer = left_expr_value.get_basic_value_enum().into_pointer_value();

let left_type = exp_gen.get_type_hint_for(target)?;
// Generate an expression for the right size
let right_type = exp_gen.get_type_hint_for(right_statement)?;

//special case if we deal with a single bit, then we need to switch to a faked u1 type
let right_type =
if let DataTypeInformation::Integer { semantic_size: Some(typesystem::U1_SIZE), .. } =
*right_type.get_type_information()
{
self.index.get_type_or_panic(typesystem::U1_TYPE)
} else {
right_type
};

//Left pointer
let left_expression_value = exp_gen.generate_expression_value(target)?;
let left_value = left_expression_value.as_r_value(self.llvm, None).into_int_value();
let left = left_expression_value.get_basic_value_enum().into_pointer_value();
//Build index
if let Some((element, direct_access)) = access_sequence.split_first() {
let mut rhs = if let AstStatement::DirectAccess(data, ..) = element.get_stmt() {
exp_gen.generate_direct_access_index(
&data.access,
&data.index,
right_type.get_type_information(),
left_type,
)
} else {
//TODO: using the global context we could get a slice here
Err(Diagnostic::new(format!("{element:?} not a direct access"))
.with_error_code("E055")
.with_location(element.get_location()))
}?;
for element in direct_access {
let rhs_next = if let AstStatement::DirectAccess(data, ..) = element.get_stmt() {
exp_gen.generate_direct_access_index(
&data.access,
&data.index,
right_type.get_type_information(),
left_type,
)
} else {
//TODO: using the global context we could get a slice here
Err(Diagnostic::new(&format!("{element:?} not a direct access"))
.with_error_code("E055")
.with_location(element.get_location()))
}?;
rhs = self.llvm.builder.build_int_add(rhs, rhs_next, "");
}
//Build mask for the index
//Get the target bit type as all ones
let rhs_type = self.llvm_index.get_associated_type(right_type.get_name())?.into_int_type();
let ones = rhs_type.const_all_ones();
//Extend the mask to the target type
let extended_mask = self.llvm.builder.build_int_z_extend(ones, left_value.get_type(), "ext");
//Position the ones in their correct locations
let shifted_mask = self.llvm.builder.build_left_shift(extended_mask, rhs, "shift");
//Invert the mask
let mask = self.llvm.builder.build_not(shifted_mask, "invert");
//And the result with the mask to erase the set bits at the target location
let and_value = self.llvm.builder.build_and(left_value, mask, "erase");

//Generate an expression for the right size
let right = exp_gen.generate_expression(right_statement)?;
//Cast the right side to the left side type
let lhs = cast_if_needed!(self, left_type, right_type, right, None).into_int_value();
//Shift left by the direct access
let value = self.llvm.builder.build_left_shift(lhs, rhs, "value");

//OR the result and store it in the left side
let or_value = self.llvm.builder.build_or(and_value, value, "or");
self.llvm.builder.build_store(left, or_value);
} else {
unreachable!();
}
Ok(())
let right_expr = exp_gen.generate_expression(right_statement)?;

exp_gen.generate_assignment_with_direct_access(
left_statement,
left_value,
left_pointer,
right_type,
right_expr,
)
}

/// generates a for-loop statement
Expand Down Expand Up @@ -842,9 +778,8 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
}
}

/// when generating an assignment to a direct-access (e.g. a.b.c.%W3.%X2 := 2;)
/// we want to deconstruct the sequence into the base-statement (a.b.c) and the sequence
/// of direct-access commands (vec![%W3, %X2])
/// Deconstructs assignments such as `a.b.c.%W3.%X2 := 2` into a base statement and its direct-access sequences.
/// For the given example this function would return `(Node(a.b.c), vec![Node(%W3), Node(%X2)])`
fn collect_base_and_direct_access_for_assignment(
left_statement: &AstNode,
) -> Option<(&AstNode, Vec<&AstNode>)> {
Expand Down
Loading
Loading