Skip to content

Commit

Permalink
fix annotation of adress-of expression
Browse files Browse the repository at this point in the history
adress-of expressions now result in pointer-types that will
be added dynamically to the index

fixes #353
  • Loading branch information
riederm committed Dec 2, 2021
1 parent ca2ebac commit 0bc0b11
Show file tree
Hide file tree
Showing 12 changed files with 356 additions and 86 deletions.
3 changes: 3 additions & 0 deletions src/codegen/generators/expression_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ impl<'a, 'b> ExpressionCodeGenerator<'a, 'b> {
Ok(llvm_typesystem::cast_if_needed(
self.llvm,
self.index,
self.llvm_index,
target_type,
v,
actual_type,
Expand Down Expand Up @@ -305,6 +306,7 @@ impl<'a, 'b> ExpressionCodeGenerator<'a, 'b> {
let reference = cast_if_needed(
self.llvm,
self.index,
self.llvm_index,
target_type,
reference,
self.get_type_hint_for(index)?,
Expand Down Expand Up @@ -739,6 +741,7 @@ impl<'a, 'b> ExpressionCodeGenerator<'a, 'b> {
let value = cast_if_needed(
self.llvm,
self.index,
self.llvm_index,
self.get_type_hint_for(right)?,
loaded_value,
param_type,
Expand Down
1 change: 1 addition & 0 deletions src/codegen/generators/statement_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
let lhs = llvm_typesystem::cast_if_needed(
self.llvm,
self.index,
self.llvm_index,
left_type,
right,
right_type,
Expand Down
36 changes: 35 additions & 1 deletion src/codegen/llvm_typesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
typesystem::{DataType, DataTypeInformation, StringEncoding},
};

use super::generators::llvm::Llvm;
use super::{generators::llvm::Llvm, llvm_index::LlvmTypedIndex};

pub fn promote_value_if_needed<'ctx>(
context: &'ctx Context,
Expand Down Expand Up @@ -114,6 +114,7 @@ fn create_llvm_extend_int_value<'a>(
pub fn cast_if_needed<'ctx>(
llvm: &Llvm<'ctx>,
index: &Index,
llvm_type_index: &LlvmTypedIndex<'ctx>,
target_type: &DataType,
value: BasicValueEnum<'ctx>,
value_type: &DataType,
Expand Down Expand Up @@ -198,6 +199,16 @@ pub fn cast_if_needed<'ctx>(
)
.into())
}
DataTypeInformation::Pointer {
auto_deref: false, ..
} => Ok(llvm
.builder
.build_ptr_to_int(
value.into_pointer_value(),
get_llvm_int_type(llvm.context, *lsize, "")?,
"",
)
.into()),
_ => Err(Diagnostic::casting_error(
value_type.get_name(),
target_type.get_name(),
Expand Down Expand Up @@ -327,6 +338,29 @@ pub fn cast_if_needed<'ctx>(
statement.get_location(),
)),
},
DataTypeInformation::Pointer {
auto_deref: false, ..
} => match value_type {
DataTypeInformation::Integer { .. } => Ok(llvm
.builder
.build_int_to_ptr(
value.into_int_value(),
llvm_type_index
.get_associated_type(target_type.get_name())?
.into_pointer_type(),
"",
)
.into()),
DataTypeInformation::Pointer { .. } | DataTypeInformation::Void { .. } => {
//this is ok, no cast required
Ok(value)
}
_ => Err(Diagnostic::casting_error(
value_type.get_name(),
target_type.get_name(),
statement.get_location(),
)),
},
_ => Ok(value),
}
}
Expand Down
38 changes: 38 additions & 0 deletions src/codegen/tests/expression_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,41 @@ fn aliased_number_type_comparing_test() {
//should result in normal number-comparisons
insta::assert_snapshot!(result);
}

#[test]
fn cast_pointer_to_lword() {
let result = codegen(
r#"
FUNCTION baz : INT
VAR
ptr_x : POINTER TO INT;
y : LWORD;
END_VAR;
y := ptr_x;
END_FUNCTION
"#,
);

//should result in normal number-comparisons
insta::assert_snapshot!(result);
}

#[test]
fn cast_lword_to_pointer() {
let result = codegen(
r#"
FUNCTION baz : INT
VAR
ptr_x : POINTER TO INT;
y : LWORD;
END_VAR;
ptr_x := y;
END_FUNCTION
"#,
);

//should result in normal number-comparisons
insta::assert_snapshot!(result);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
source: src/codegen/tests/expression_tests.rs
expression: result

---
; ModuleID = 'main'
source_filename = "main"

%baz_interface = type { i16*, i64 }

define i16 @baz(%baz_interface* %0) {
entry:
%ptr_x = getelementptr inbounds %baz_interface, %baz_interface* %0, i32 0, i32 0
%y = getelementptr inbounds %baz_interface, %baz_interface* %0, i32 0, i32 1
%baz = alloca i16, align 2
%load_y = load i64, i64* %y, align 4
%1 = inttoptr i64 %load_y to i16*
store i16* %1, i16** %ptr_x, align 8
%baz_ret = load i16, i16* %baz, align 2
ret i16 %baz_ret
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
source: src/codegen/tests/expression_tests.rs
expression: result

---
; ModuleID = 'main'
source_filename = "main"

%baz_interface = type { i16*, i64 }

define i16 @baz(%baz_interface* %0) {
entry:
%ptr_x = getelementptr inbounds %baz_interface, %baz_interface* %0, i32 0, i32 0
%y = getelementptr inbounds %baz_interface, %baz_interface* %0, i32 0, i32 1
%baz = alloca i16, align 2
%load_ptr_x = load i16*, i16** %ptr_x, align 8
%1 = ptrtoint i16* %load_ptr_x to i64
store i64 %1, i64* %y, align 4
%baz_ret = load i16, i16* %baz, align 2
ret i16 %baz_ret
}

22 changes: 22 additions & 0 deletions src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,12 @@ impl<'i> TypeAnnotator<'i> {
self.annotation_map
.annotate(statement, StatementAnnotation::value(target.get_name()));
}
} else if operator == &Operator::Address {
//this becomes a pointer to the given type:
let pointer_type_name =
add_pointer_type(&mut self.annotation_map.new_index, inner_type);
self.annotation_map
.annotate(statement, StatementAnnotation::value(&pointer_type_name));
} else {
//TODO: The adderss operator should report a correct pointer type. We need to have reproducable type names for that first.
self.annotation_map
Expand Down Expand Up @@ -1386,6 +1392,22 @@ impl<'i> TypeAnnotator<'i> {
}
}

/// adds a pointer to the given inner_type to the given index and return's its name
fn add_pointer_type(index: &mut Index, inner_type: &DataTypeInformation) -> String {
let new_type_name = format!("POINTER_TO_{}", inner_type.get_name());
index.register_type(crate::typesystem::DataType {
name: new_type_name.clone(),
initial_value: None,
nature: TypeNature::Any,
information: crate::typesystem::DataTypeInformation::Pointer {
auto_deref: false,
inner_type_name: inner_type.get_name().into(),
name: new_type_name.clone(),
},
});
new_type_name
}

fn find_implementation_annotation(name: &str, index: &Index) -> Option<StatementAnnotation> {
index
.find_implementation(name)
Expand Down
20 changes: 10 additions & 10 deletions src/resolver/tests/const_resolver_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,7 +1170,7 @@ fn const_string_initializers_should_be_converted() {
#[test]
fn const_lreal_initializers_should_be_resolved_correctly() {
// GIVEN some STRING constants used as initializers
let (parse_result, index) = index(
let (parse_result, mut index) = index(
r#"
VAR_GLOBAL CONSTANT
clreal : LREAL := 3.1415;
Expand All @@ -1184,7 +1184,7 @@ fn const_lreal_initializers_should_be_resolved_correctly() {

// WHEN compile-time evaluation is applied
// AND types are resolved
let annotations = annotate(&parse_result, &index);
let annotations = annotate(&parse_result, &mut index);
let (index, unresolvable) = evaluate_constants(index);

// THEN all should be resolved
Expand Down Expand Up @@ -1229,7 +1229,7 @@ fn const_lreal_initializers_should_be_resolved_correctly() {
#[test]
fn array_size_from_constant() {
// GIVEN some an array with const-expr -dimensions
let (parse_result, index) = index(
let (parse_result, mut index) = index(
r#"
PROGRAM aaa
VAR CONSTANT
Expand All @@ -1246,7 +1246,7 @@ fn array_size_from_constant() {

// WHEN compile-time evaluation is applied
// AND types are resolved
annotate(&parse_result, &index);
annotate(&parse_result, &mut index);
let (_, unresolvable) = evaluate_constants(index);

debug_assert_eq!(EMPTY, unresolvable);
Expand All @@ -1255,7 +1255,7 @@ fn array_size_from_constant() {
#[test]
fn array_literals_type_resolving() {
// GIVEN some STRING constants used as initializers
let (parse_result, index) = index(
let (parse_result, mut index) = index(
r#"
VAR_GLOBAL CONSTANT
a : ARRAY[0..5] OF BYTE := [1,2,3,4];
Expand All @@ -1265,7 +1265,7 @@ fn array_literals_type_resolving() {

// WHEN compile-time evaluation is applied
// AND types are resolved
let annotations = annotate(&parse_result, &index);
let annotations = annotate(&parse_result, &mut index);
let (index, unresolvable) = evaluate_constants(index);

// THEN all should be resolved
Expand Down Expand Up @@ -1318,7 +1318,7 @@ fn array_literals_type_resolving() {
#[test]
fn nested_array_literals_type_resolving() {
// GIVEN a multi-nested Array Type with an initializer
let (parse_result, index) = index(
let (parse_result, mut index) = index(
r#"
VAR_GLOBAL CONSTANT
a : ARRAY[0..1] OF ARRAY[0..1] OF BYTE := [[1,2],[3,4]];
Expand All @@ -1328,7 +1328,7 @@ fn nested_array_literals_type_resolving() {

// WHEN compile-time evaluation is applied
// AND types are resolved
let annotations = annotate(&parse_result, &index);
let annotations = annotate(&parse_result, &mut index);
let (index, unresolvable) = evaluate_constants(index);

// THEN all should be resolved
Expand Down Expand Up @@ -1391,7 +1391,7 @@ fn nested_array_literals_type_resolving() {
#[test]
fn nested_array_literals_multiplied_statement_type_resolving() {
// GIVEN a multi-nested Array Type with an initializer
let (parse_result, index) = index(
let (parse_result, mut index) = index(
r#"
VAR_GLOBAL CONSTANT
a : ARRAY[0..1] OF ARRAY[0..1] OF BYTE := [[2(2)],[2(3)]];
Expand All @@ -1401,7 +1401,7 @@ fn nested_array_literals_multiplied_statement_type_resolving() {

// WHEN compile-time evaluation is applied
// AND types are resolved
let annotations = annotate(&parse_result, &index);
let annotations = annotate(&parse_result, &mut index);
let (index, unresolvable) = evaluate_constants(index);

// THEN all should be resolved
Expand Down
Loading

0 comments on commit 0bc0b11

Please sign in to comment.