1
1
// Copyright (c) 2020 Ghaith Hachem and Mathias Rieder
2
2
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 } ;
4
5
use crate :: resolver:: { AstAnnotations , Dependency } ;
5
6
use crate :: typesystem:: { self , DataTypeInformation , Dimension , StringEncoding , StructSource } ;
6
7
use crate :: {
@@ -12,12 +13,13 @@ use crate::{
12
13
typesystem:: DataType ,
13
14
} ;
14
15
16
+ use inkwell:: types:: { AnyType , AnyTypeEnum , BasicMetadataTypeEnum , FunctionType } ;
15
17
use inkwell:: {
16
18
types:: { BasicType , BasicTypeEnum } ,
17
19
values:: { BasicValue , BasicValueEnum } ,
18
20
AddressSpace ,
19
21
} ;
20
- use plc_ast:: ast:: { AstNode , AstStatement } ;
22
+ use plc_ast:: ast:: { AstNode , AstStatement , PouType } ;
21
23
use plc_ast:: literals:: AstLiteral ;
22
24
use plc_diagnostics:: diagnostics:: Diagnostic ;
23
25
use plc_source:: source_location:: SourceLocation ;
@@ -174,6 +176,48 @@ pub fn generate_data_types<'ink>(
174
176
}
175
177
176
178
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
+
177
221
/// generates the members of an opaque struct and associates its initial values
178
222
fn expand_opaque_types ( & mut self , data_type : & DataType ) -> Result < ( ) , Diagnostic > {
179
223
let information = data_type. get_type_information ( ) ;
@@ -200,15 +244,27 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
200
244
/// Creates an llvm type to be associated with the given data type.
201
245
/// Generates only an opaque type for structs.
202
246
/// 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 > {
204
248
let information = data_type. get_type_information ( ) ;
205
249
match information {
206
250
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 ( ) ) ,
208
262
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 ( ) )
210
267
}
211
- StructSource :: Internal ( _) => self . types_index . get_associated_type ( data_type. get_name ( ) ) ,
212
268
} ,
213
269
214
270
// We distinguish between two types of arrays, normal and variable length ones.
@@ -222,7 +278,7 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
222
278
. get_effective_type_by_name ( inner_type_name)
223
279
. and_then ( |inner_type| self . create_type ( inner_type_name, inner_type) )
224
280
. 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 ( ) )
226
282
}
227
283
}
228
284
DataTypeInformation :: Integer { size, .. } => {
@@ -264,7 +320,7 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
264
320
DataTypeInformation :: Void => Ok ( get_llvm_int_type ( self . llvm . context , 32 , "Void" ) . into ( ) ) ,
265
321
DataTypeInformation :: Pointer { inner_type_name, .. } => {
266
322
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 ( ) )
268
324
}
269
325
DataTypeInformation :: Generic { .. } => {
270
326
unreachable ! ( "Generic types should not be generated" )
@@ -435,9 +491,9 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
435
491
/// `arr: ARRAY[0..3] OF INT`.
436
492
fn create_nested_array_type (
437
493
& self ,
438
- inner_type : BasicTypeEnum < ' ink > ,
494
+ inner_type : AnyTypeEnum < ' ink > ,
439
495
dimensions : & [ Dimension ] ,
440
- ) -> Result < BasicTypeEnum < ' ink > , Diagnostic > {
496
+ ) -> Result < AnyTypeEnum < ' ink > , Diagnostic > {
441
497
let len = dimensions
442
498
. iter ( )
443
499
. map ( |dimension| {
@@ -453,14 +509,17 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
453
509
} ) ?;
454
510
455
511
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" ) ,
462
521
}
463
- . as_basic_type_enum ( ) ;
522
+ . as_any_type_enum ( ) ;
464
523
465
524
Ok ( result)
466
525
}
0 commit comments