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

#353 assigning pointer-address to DWORD and vice versa #388

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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 @@ -783,6 +783,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 @@ -1409,6 +1415,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