@@ -4,11 +4,11 @@ use super::{
4
4
llvm:: Llvm ,
5
5
} ;
6
6
use crate :: {
7
- codegen:: { debug:: Debug , llvm_typesystem :: cast_if_needed } ,
7
+ codegen:: debug:: Debug ,
8
8
codegen:: { debug:: DebugBuilderEnum , LlvmTypedIndex } ,
9
9
index:: { ImplementationIndexEntry , Index } ,
10
10
resolver:: { AnnotationMap , AstAnnotations , StatementAnnotation } ,
11
- typesystem:: { self , DataTypeInformation } ,
11
+ typesystem:: DataTypeInformation ,
12
12
} ;
13
13
use inkwell:: {
14
14
basic_block:: BasicBlock ,
@@ -244,7 +244,7 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
244
244
self . register_debug_location ( left_statement) ;
245
245
//TODO: Looks hacky, the strings will be similar so we should look into making the assignment a bit nicer.
246
246
if left_statement. has_direct_access ( ) {
247
- return self . generate_direct_access_assignment ( left_statement, right_statement) ;
247
+ return self . generate_assignment_statement_direct_access ( left_statement, right_statement) ;
248
248
}
249
249
//TODO: Also hacky but for now we cannot generate assignments for hardware access
250
250
if matches ! ( left_statement. get_stmt( ) , AstStatement :: HardwareAccess { .. } ) {
@@ -279,96 +279,32 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
279
279
self . debug . set_debug_location ( self . llvm , & self . function_context . function , line, column) ;
280
280
}
281
281
282
- fn generate_direct_access_assignment (
282
+ fn generate_assignment_statement_direct_access (
283
283
& self ,
284
284
left_statement : & AstNode ,
285
285
right_statement : & AstNode ,
286
286
) -> Result < ( ) , Diagnostic > {
287
- //TODO : Validation
288
287
let exp_gen = self . create_expr_generator ( ) ;
289
288
290
- // given a complex direct-access assignemnt: a.b.c.%W3,%X1
291
- // we want to deconstruct the targe-part (a.b.c) and the direct-access sequence (%W3.%X1)
292
- let Some ( ( target, access_sequence) ) = collect_base_and_direct_access_for_assignment ( left_statement)
293
- else {
289
+ // Left pointer
290
+ let Some ( ( base, _) ) = collect_base_and_direct_access_for_assignment ( left_statement) else {
294
291
unreachable ! ( "Invalid direct-access expression: {left_statement:#?}" )
295
292
} ;
293
+ let left_expr_value = exp_gen. generate_expression_value ( base) ?;
294
+ let left_value = left_expr_value. as_r_value ( self . llvm , None ) . into_int_value ( ) ;
295
+ let left_pointer = left_expr_value. get_basic_value_enum ( ) . into_pointer_value ( ) ;
296
296
297
- let left_type = exp_gen . get_type_hint_for ( target ) ? ;
297
+ // Generate an expression for the right size
298
298
let right_type = exp_gen. get_type_hint_for ( right_statement) ?;
299
-
300
- //special case if we deal with a single bit, then we need to switch to a faked u1 type
301
- let right_type =
302
- if let DataTypeInformation :: Integer { semantic_size : Some ( typesystem:: U1_SIZE ) , .. } =
303
- * right_type. get_type_information ( )
304
- {
305
- self . index . get_type_or_panic ( typesystem:: U1_TYPE )
306
- } else {
307
- right_type
308
- } ;
309
-
310
- //Left pointer
311
- let left_expression_value = exp_gen. generate_expression_value ( target) ?;
312
- let left_value = left_expression_value. as_r_value ( self . llvm , None ) . into_int_value ( ) ;
313
- let left = left_expression_value. get_basic_value_enum ( ) . into_pointer_value ( ) ;
314
- //Build index
315
- if let Some ( ( element, direct_access) ) = access_sequence. split_first ( ) {
316
- let mut rhs = if let AstStatement :: DirectAccess ( data, ..) = element. get_stmt ( ) {
317
- exp_gen. generate_direct_access_index (
318
- & data. access ,
319
- & data. index ,
320
- right_type. get_type_information ( ) ,
321
- left_type,
322
- )
323
- } else {
324
- //TODO: using the global context we could get a slice here
325
- Err ( Diagnostic :: new ( format ! ( "{element:?} not a direct access" ) )
326
- . with_error_code ( "E055" )
327
- . with_location ( element. get_location ( ) ) )
328
- } ?;
329
- for element in direct_access {
330
- let rhs_next = if let AstStatement :: DirectAccess ( data, ..) = element. get_stmt ( ) {
331
- exp_gen. generate_direct_access_index (
332
- & data. access ,
333
- & data. index ,
334
- right_type. get_type_information ( ) ,
335
- left_type,
336
- )
337
- } else {
338
- //TODO: using the global context we could get a slice here
339
- Err ( Diagnostic :: new ( & format ! ( "{element:?} not a direct access" ) )
340
- . with_error_code ( "E055" )
341
- . with_location ( element. get_location ( ) ) )
342
- } ?;
343
- rhs = self . llvm . builder . build_int_add ( rhs, rhs_next, "" ) ;
344
- }
345
- //Build mask for the index
346
- //Get the target bit type as all ones
347
- let rhs_type = self . llvm_index . get_associated_type ( right_type. get_name ( ) ) ?. into_int_type ( ) ;
348
- let ones = rhs_type. const_all_ones ( ) ;
349
- //Extend the mask to the target type
350
- let extended_mask = self . llvm . builder . build_int_z_extend ( ones, left_value. get_type ( ) , "ext" ) ;
351
- //Position the ones in their correct locations
352
- let shifted_mask = self . llvm . builder . build_left_shift ( extended_mask, rhs, "shift" ) ;
353
- //Invert the mask
354
- let mask = self . llvm . builder . build_not ( shifted_mask, "invert" ) ;
355
- //And the result with the mask to erase the set bits at the target location
356
- let and_value = self . llvm . builder . build_and ( left_value, mask, "erase" ) ;
357
-
358
- //Generate an expression for the right size
359
- let right = exp_gen. generate_expression ( right_statement) ?;
360
- //Cast the right side to the left side type
361
- let lhs = cast_if_needed ! ( self , left_type, right_type, right, None ) . into_int_value ( ) ;
362
- //Shift left by the direct access
363
- let value = self . llvm . builder . build_left_shift ( lhs, rhs, "value" ) ;
364
-
365
- //OR the result and store it in the left side
366
- let or_value = self . llvm . builder . build_or ( and_value, value, "or" ) ;
367
- self . llvm . builder . build_store ( left, or_value) ;
368
- } else {
369
- unreachable ! ( ) ;
370
- }
371
- Ok ( ( ) )
299
+ let right_expr = exp_gen. generate_expression ( right_statement) ?;
300
+
301
+ exp_gen. generate_assignment_with_direct_access (
302
+ left_statement,
303
+ left_value,
304
+ left_pointer,
305
+ right_type,
306
+ right_expr,
307
+ )
372
308
}
373
309
374
310
/// generates a for-loop statement
@@ -842,9 +778,8 @@ impl<'a, 'b> StatementCodeGenerator<'a, 'b> {
842
778
}
843
779
}
844
780
845
- /// when generating an assignment to a direct-access (e.g. a.b.c.%W3.%X2 := 2;)
846
- /// we want to deconstruct the sequence into the base-statement (a.b.c) and the sequence
847
- /// of direct-access commands (vec![%W3, %X2])
781
+ /// Deconstructs assignments such as `a.b.c.%W3.%X2 := 2` into a base statement and its direct-access sequences.
782
+ /// For the given example this function would return `(Node(a.b.c), vec![Node(%W3), Node(%X2)])`
848
783
fn collect_base_and_direct_access_for_assignment (
849
784
left_statement : & AstNode ,
850
785
) -> Option < ( & AstNode , Vec < & AstNode > ) > {
0 commit comments