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 , 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 ;
@@ -200,15 +202,26 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
200
202
/// Creates an llvm type to be associated with the given data type.
201
203
/// Generates only an opaque type for structs.
202
204
/// 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 > {
205
+ fn create_type ( & mut self , name : & str , data_type : & DataType ) -> Result < AnyTypeEnum < ' ink > , Diagnostic > {
204
206
let information = data_type. get_type_information ( ) ;
205
207
match information {
206
208
DataTypeInformation :: Struct { source, .. } => match source {
207
- StructSource :: Pou ( ..) => self . types_index . get_associated_pou_type ( data_type. get_name ( ) ) ,
208
- StructSource :: OriginalDeclaration => {
209
- self . types_index . get_associated_type ( data_type. get_name ( ) )
209
+ StructSource :: Pou ( PouType :: Method { .. } ) => {
210
+ Ok ( self . create_function_type ( name) ?. as_any_type_enum ( ) )
210
211
}
211
- StructSource :: Internal ( _) => self . types_index . get_associated_type ( data_type. get_name ( ) ) ,
212
+
213
+ StructSource :: Pou ( ..) => self
214
+ . types_index
215
+ . get_associated_pou_type ( data_type. get_name ( ) )
216
+ . map ( |res| res. as_any_type_enum ( ) ) ,
217
+ StructSource :: OriginalDeclaration => self
218
+ . types_index
219
+ . get_associated_type ( data_type. get_name ( ) )
220
+ . map ( |res| res. as_any_type_enum ( ) ) ,
221
+ StructSource :: Internal ( _) => self
222
+ . types_index
223
+ . get_associated_type ( data_type. get_name ( ) )
224
+ . map ( |res| res. as_any_type_enum ( ) ) ,
212
225
} ,
213
226
214
227
// We distinguish between two types of arrays, normal and variable length ones.
@@ -222,7 +235,7 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
222
235
. get_effective_type_by_name ( inner_type_name)
223
236
. and_then ( |inner_type| self . create_type ( inner_type_name, inner_type) )
224
237
. and_then ( |inner_type| self . create_nested_array_type ( inner_type, dimensions) )
225
- . map ( |it| it. as_basic_type_enum ( ) )
238
+ . map ( |it| it. as_any_type_enum ( ) )
226
239
}
227
240
}
228
241
DataTypeInformation :: Integer { size, .. } => {
@@ -264,14 +277,63 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
264
277
DataTypeInformation :: Void => Ok ( get_llvm_int_type ( self . llvm . context , 32 , "Void" ) . into ( ) ) ,
265
278
DataTypeInformation :: Pointer { inner_type_name, .. } => {
266
279
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 ( ) )
280
+ Ok ( inner_type. create_ptr_type ( AddressSpace :: from ( ADDRESS_SPACE_GENERIC ) ) . into ( ) )
268
281
}
269
282
DataTypeInformation :: Generic { .. } => {
270
283
unreachable ! ( "Generic types should not be generated" )
271
284
}
272
285
}
273
286
}
274
287
288
+ // TODO(vosa): Is this neccessary? Are the function types indexed and later on used in the expression
289
+ // generator? If not this whole commit could be reverted, double-check before merging
290
+ fn create_function_type ( & mut self , pou_name : & str ) -> Result < FunctionType < ' ink > , Diagnostic > {
291
+ let return_type = self
292
+ . types_index
293
+ . find_associated_type ( self . index . get_return_type_or_void ( pou_name) . get_name ( ) )
294
+ . map ( |opt| opt. as_any_type_enum ( ) )
295
+ . unwrap_or ( self . llvm . context . void_type ( ) . as_any_type_enum ( ) ) ;
296
+
297
+ let mut parameter_types = Vec :: new ( ) ;
298
+
299
+ // Methods are defined as functions in the LLVM IR, but carry the underlying POU type as their first
300
+ // parameter to operate on them, hence push the POU type to the very first position.
301
+ if let Some ( PouIndexEntry :: Method { parent_name, .. } ) = self . index . find_pou ( pou_name) {
302
+ let ty = self . types_index . get_associated_type ( parent_name) . expect ( "must exist" ) ;
303
+ let ty_ptr = ty. ptr_type ( AddressSpace :: from ( ADDRESS_SPACE_GENERIC ) ) . into ( ) ;
304
+
305
+ parameter_types. push ( ty_ptr) ;
306
+ }
307
+
308
+ for parameter in self . index . get_declared_parameters ( pou_name) {
309
+ // Instead of relying on the LLVM index, we create data-types directly in here because some of
310
+ // them may not have been registered yet. For example, at the time of writing this comment the
311
+ // `__auto_pointer_to_DINT` type was not present in the index for a VAR_IN_OUT parameter which
312
+ // resulted in an error
313
+ let ty = self . create_type (
314
+ parameter. get_name ( ) ,
315
+ self . index . get_type ( & parameter. data_type_name ) . expect ( "must exist" ) ,
316
+ ) ?;
317
+
318
+ parameter_types. push ( ty. try_into ( ) . unwrap ( ) ) ;
319
+ }
320
+
321
+ let fn_type = match return_type {
322
+ AnyTypeEnum :: ArrayType ( value) => value. fn_type ( parameter_types. as_slice ( ) , false ) ,
323
+ AnyTypeEnum :: FloatType ( value) => value. fn_type ( parameter_types. as_slice ( ) , false ) ,
324
+ AnyTypeEnum :: IntType ( value) => value. fn_type ( parameter_types. as_slice ( ) , false ) ,
325
+ AnyTypeEnum :: PointerType ( value) => value. fn_type ( parameter_types. as_slice ( ) , false ) ,
326
+ AnyTypeEnum :: StructType ( value) => value. fn_type ( parameter_types. as_slice ( ) , false ) ,
327
+ AnyTypeEnum :: VectorType ( value) => value. fn_type ( parameter_types. as_slice ( ) , false ) ,
328
+ AnyTypeEnum :: VoidType ( value) => value. fn_type ( parameter_types. as_slice ( ) , false ) ,
329
+
330
+ AnyTypeEnum :: FunctionType ( _) => unreachable ! ( ) ,
331
+ } ;
332
+
333
+ eprintln ! ( "created function type: {}" , fn_type. print_to_string( ) ) ;
334
+ Ok ( fn_type)
335
+ }
336
+
275
337
fn generate_initial_value (
276
338
& mut self ,
277
339
data_type : & DataType ,
@@ -435,9 +497,9 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
435
497
/// `arr: ARRAY[0..3] OF INT`.
436
498
fn create_nested_array_type (
437
499
& self ,
438
- inner_type : BasicTypeEnum < ' ink > ,
500
+ inner_type : AnyTypeEnum < ' ink > ,
439
501
dimensions : & [ Dimension ] ,
440
- ) -> Result < BasicTypeEnum < ' ink > , Diagnostic > {
502
+ ) -> Result < AnyTypeEnum < ' ink > , Diagnostic > {
441
503
let len = dimensions
442
504
. iter ( )
443
505
. map ( |dimension| {
@@ -453,14 +515,17 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
453
515
} ) ?;
454
516
455
517
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) ,
518
+ AnyTypeEnum :: IntType ( ty) => ty. array_type ( len) ,
519
+ AnyTypeEnum :: FloatType ( ty) => ty. array_type ( len) ,
520
+ AnyTypeEnum :: StructType ( ty) => ty. array_type ( len) ,
521
+ AnyTypeEnum :: ArrayType ( ty) => ty. array_type ( len) ,
522
+ AnyTypeEnum :: PointerType ( ty) => ty. array_type ( len) ,
523
+ AnyTypeEnum :: VectorType ( ty) => ty. array_type ( len) ,
524
+
525
+ AnyTypeEnum :: FunctionType ( _) => unimplemented ! ( "function types are not supported in arrays" ) ,
526
+ AnyTypeEnum :: VoidType ( _) => unimplemented ! ( "void types not supported in arrays" ) ,
462
527
}
463
- . as_basic_type_enum ( ) ;
528
+ . as_any_type_enum ( ) ;
464
529
465
530
Ok ( result)
466
531
}
0 commit comments