Skip to content

Commit 3a34a1c

Browse files
committed
Add working prototype
1 parent 5469bda commit 3a34a1c

14 files changed

+701
-27
lines changed

compiler/plc_ast/src/ast.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1397,6 +1397,16 @@ impl AstNode {
13971397
pub fn with_metadata(self, metadata: MetaData) -> AstNode {
13981398
AstNode { metadata: Some(metadata), ..self }
13991399
}
1400+
1401+
pub fn is_deref(&self) -> bool {
1402+
matches!(
1403+
self,
1404+
AstNode {
1405+
stmt: AstStatement::ReferenceExpr(ReferenceExpr { access: ReferenceAccess::Deref, .. }),
1406+
..
1407+
}
1408+
)
1409+
}
14001410
}
14011411

14021412
#[derive(Clone, Copy, Debug, PartialEq, Eq)]

src/builtins.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ lazy_static! {
103103
generic_name_resolver: no_generic_name_resolver,
104104
code: |generator, params, location| {
105105
if let [reference] = params {
106+
// TODO(vosa): See if there is a better way
107+
// Check if this is a qualified method reference like fb.fbSpecificMethod
108+
if let Some(resolver::StatementAnnotation::Function { qualified_name, .. }) = generator.annotations.get(reference) {
109+
// This is a qualified method reference - return the function pointer directly
110+
if let Some(fn_value) = generator.llvm_index.find_associated_implementation(&qualified_name) {
111+
return Ok(ExpressionValue::RValue(fn_value.as_global_value().as_pointer_value().as_basic_value_enum()));
112+
}
113+
}
114+
106115
generator
107116
.generate_lvalue(reference)
108117
.map(|it| ExpressionValue::RValue(it.as_basic_value_enum()))

src/codegen/generators/data_type_generator.rs

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
22
use crate::codegen::debug::Debug;
3-
use crate::index::{FxIndexSet, Index, VariableIndexEntry, VariableType};
3+
use crate::codegen::llvm_index::TypeHelper;
4+
use crate::index::{FxIndexSet, Index, PouIndexEntry, VariableIndexEntry, VariableType};
45
use crate::resolver::{AstAnnotations, Dependency};
56
use crate::typesystem::{self, DataTypeInformation, Dimension, StringEncoding, StructSource};
67
use crate::{
@@ -12,12 +13,13 @@ use crate::{
1213
typesystem::DataType,
1314
};
1415

16+
use inkwell::types::{AnyType, AnyTypeEnum, BasicMetadataTypeEnum, FunctionType};
1517
use inkwell::{
1618
types::{BasicType, BasicTypeEnum},
1719
values::{BasicValue, BasicValueEnum},
1820
AddressSpace,
1921
};
20-
use plc_ast::ast::{AstNode, AstStatement};
22+
use plc_ast::ast::{AstNode, AstStatement, PouType};
2123
use plc_ast::literals::AstLiteral;
2224
use plc_diagnostics::diagnostics::Diagnostic;
2325
use plc_source::source_location::SourceLocation;
@@ -174,6 +176,48 @@ pub fn generate_data_types<'ink>(
174176
}
175177

176178
impl<'ink> DataTypeGenerator<'ink, '_> {
179+
fn create_function_type(&self, name: &str) -> Result<FunctionType<'ink>, Diagnostic> {
180+
let return_type_dt = self.index.find_return_type(name).unwrap_or(self.index.get_void_type());
181+
182+
let return_type = self
183+
.types_index
184+
.find_associated_type(&return_type_dt.name)
185+
.map(|opt| opt.as_any_type_enum())
186+
.unwrap_or(self.llvm.context.void_type().into());
187+
188+
let mut parameter_types = vec![];
189+
190+
// For methods, we need to add the 'this' parameter as the first parameter
191+
if let Some(pou_entry) = self.index.find_pou(name) {
192+
if let PouIndexEntry::Method { parent_name, .. } = pou_entry {
193+
// Get the owner class type and add it as the first parameter (this pointer)
194+
if let Ok(owner_type) = self.types_index.get_associated_type(parent_name) {
195+
parameter_types
196+
.push(owner_type.ptr_type(AddressSpace::from(ADDRESS_SPACE_GENERIC)).into());
197+
}
198+
}
199+
}
200+
201+
// Add the declared parameters
202+
let declared_params = self
203+
.index
204+
.get_declared_parameters(name)
205+
.iter()
206+
.flat_map(|param| self.types_index.get_associated_type(&param.data_type_name))
207+
.map(|opt| opt.into())
208+
.collect::<Vec<BasicMetadataTypeEnum>>();
209+
210+
parameter_types.extend(declared_params);
211+
212+
let fn_type = match dbg!(return_type) {
213+
AnyTypeEnum::IntType(value) => value.fn_type(parameter_types.as_slice(), false),
214+
AnyTypeEnum::VoidType(value) => value.fn_type(parameter_types.as_slice(), false),
215+
_ => unimplemented!(),
216+
};
217+
218+
Ok(fn_type)
219+
}
220+
177221
/// generates the members of an opaque struct and associates its initial values
178222
fn expand_opaque_types(&mut self, data_type: &DataType) -> Result<(), Diagnostic> {
179223
let information = data_type.get_type_information();
@@ -200,15 +244,27 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
200244
/// Creates an llvm type to be associated with the given data type.
201245
/// Generates only an opaque type for structs.
202246
/// Eagerly generates but does not associate nested array and referenced aliased types
203-
fn create_type(&mut self, name: &str, data_type: &DataType) -> Result<BasicTypeEnum<'ink>, Diagnostic> {
247+
fn create_type(&mut self, name: &str, data_type: &DataType) -> Result<AnyTypeEnum<'ink>, Diagnostic> {
204248
let information = data_type.get_type_information();
205249
match information {
206250
DataTypeInformation::Struct { source, .. } => match source {
207-
StructSource::Pou(..) => self.types_index.get_associated_pou_type(data_type.get_name()),
251+
StructSource::Pou(PouType::Function | PouType::Method { .. }, ..) => {
252+
let gen_type = self.create_function_type(name)?;
253+
254+
// TODO(vosa): Strictly speaking we don't need to register in LLVM index, i.e. `return Ok(gen_type.as_any_type_enum())` would suffice without breaking any tests; re-think approach with AnyType changes in API
255+
self.types_index.associate_pou_type(name, gen_type.as_any_type_enum())?;
256+
self.types_index.get_associated_function_type(name).map(|it| it.as_any_type_enum())
257+
}
258+
StructSource::Pou(..) => self
259+
.types_index
260+
.get_associated_pou_type(data_type.get_name())
261+
.map(|it| it.as_any_type_enum()),
208262
StructSource::OriginalDeclaration => {
209-
self.types_index.get_associated_type(data_type.get_name())
263+
self.types_index.get_associated_type(data_type.get_name()).map(|it| it.as_any_type_enum())
264+
}
265+
StructSource::Internal(_) => {
266+
self.types_index.get_associated_type(data_type.get_name()).map(|it| it.as_any_type_enum())
210267
}
211-
StructSource::Internal(_) => self.types_index.get_associated_type(data_type.get_name()),
212268
},
213269

214270
// We distinguish between two types of arrays, normal and variable length ones.
@@ -222,7 +278,7 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
222278
.get_effective_type_by_name(inner_type_name)
223279
.and_then(|inner_type| self.create_type(inner_type_name, inner_type))
224280
.and_then(|inner_type| self.create_nested_array_type(inner_type, dimensions))
225-
.map(|it| it.as_basic_type_enum())
281+
.map(|it| it.as_any_type_enum())
226282
}
227283
}
228284
DataTypeInformation::Integer { size, .. } => {
@@ -264,7 +320,7 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
264320
DataTypeInformation::Void => Ok(get_llvm_int_type(self.llvm.context, 32, "Void").into()),
265321
DataTypeInformation::Pointer { inner_type_name, .. } => {
266322
let inner_type = self.create_type(inner_type_name, self.index.get_type(inner_type_name)?)?;
267-
Ok(inner_type.ptr_type(AddressSpace::from(ADDRESS_SPACE_GENERIC)).into())
323+
Ok(inner_type.create_ptr_type(AddressSpace::from(ADDRESS_SPACE_GENERIC)).into())
268324
}
269325
DataTypeInformation::Generic { .. } => {
270326
unreachable!("Generic types should not be generated")
@@ -435,9 +491,9 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
435491
/// `arr: ARRAY[0..3] OF INT`.
436492
fn create_nested_array_type(
437493
&self,
438-
inner_type: BasicTypeEnum<'ink>,
494+
inner_type: AnyTypeEnum<'ink>,
439495
dimensions: &[Dimension],
440-
) -> Result<BasicTypeEnum<'ink>, Diagnostic> {
496+
) -> Result<AnyTypeEnum<'ink>, Diagnostic> {
441497
let len = dimensions
442498
.iter()
443499
.map(|dimension| {
@@ -453,14 +509,17 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
453509
})?;
454510

455511
let result = match inner_type {
456-
BasicTypeEnum::IntType(ty) => ty.array_type(len),
457-
BasicTypeEnum::FloatType(ty) => ty.array_type(len),
458-
BasicTypeEnum::StructType(ty) => ty.array_type(len),
459-
BasicTypeEnum::ArrayType(ty) => ty.array_type(len),
460-
BasicTypeEnum::PointerType(ty) => ty.array_type(len),
461-
BasicTypeEnum::VectorType(ty) => ty.array_type(len),
512+
AnyTypeEnum::IntType(ty) => ty.array_type(len),
513+
AnyTypeEnum::FloatType(ty) => ty.array_type(len),
514+
AnyTypeEnum::StructType(ty) => ty.array_type(len),
515+
AnyTypeEnum::ArrayType(ty) => ty.array_type(len),
516+
AnyTypeEnum::PointerType(ty) => ty.array_type(len),
517+
AnyTypeEnum::VectorType(ty) => ty.array_type(len),
518+
519+
AnyTypeEnum::FunctionType(_) => unreachable!("Function types are not supported in arrays"),
520+
AnyTypeEnum::VoidType(_) => unreachable!("Void types are not supported in arrays"),
462521
}
463-
.as_basic_type_enum();
522+
.as_any_type_enum();
464523

465524
Ok(result)
466525
}

0 commit comments

Comments
 (0)