@@ -366,22 +366,41 @@ pub fn ty_of_inttype(ity: IntType) -> ty::t {
366
366
367
367
368
368
/**
369
- * Returns the fields of a struct for the given representation.
370
- * All nominal types are LLVM structs, in order to be able to use
371
- * forward-declared opaque types to prevent circularity in `type_of`.
369
+ * LLVM-level types are a little complicated.
370
+ *
371
+ * C-like enums need to be actual ints, not wrapped in a struct,
372
+ * because that changes the ABI on some platforms (see issue #10308).
373
+ *
374
+ * For nominal types, in some cases, we need to use LLVM named structs
375
+ * and fill in the actual contents in a second pass to prevent
376
+ * unbounded recursion; see also the comments in `trans::type_of`.
372
377
*/
373
- pub fn fields_of ( cx : & mut CrateContext , r : & Repr ) -> ~[ Type ] {
374
- generic_fields_of ( cx, r, false )
378
+ pub fn type_of ( cx : & mut CrateContext , r : & Repr ) -> Type {
379
+ generic_type_of ( cx, r, None , false )
380
+ }
381
+ pub fn sizing_type_of ( cx : & mut CrateContext , r : & Repr ) -> Type {
382
+ generic_type_of ( cx, r, None , true )
375
383
}
376
- /// Like `fields_of`, but for `type_of::sizing_type_of` (q.v.).
377
- pub fn sizing_fields_of ( cx : & mut CrateContext , r : & Repr ) -> ~[ Type ] {
378
- generic_fields_of ( cx, r, true )
384
+ pub fn incomplete_type_of ( cx : & mut CrateContext , r : & Repr , name : & str ) -> Type {
385
+ generic_type_of ( cx, r, Some ( name) , false )
386
+ }
387
+ pub fn finish_type_of ( cx : & mut CrateContext , r : & Repr , llty : & mut Type ) {
388
+ match * r {
389
+ CEnum ( * ) | General ( * ) => { }
390
+ Univariant ( ref st, _) | NullablePointer { nonnull : ref st, _ } =>
391
+ llty. set_struct_body ( struct_llfields ( cx, st, false ) , st. packed )
392
+ }
379
393
}
380
- fn generic_fields_of ( cx : & mut CrateContext , r : & Repr , sizing : bool ) -> ~[ Type ] {
394
+
395
+ fn generic_type_of ( cx : & mut CrateContext , r : & Repr , name : Option < & str > , sizing : bool ) -> Type {
381
396
match * r {
382
- CEnum ( ity, _, _) => ~[ ll_inttype ( cx, ity) ] ,
383
- Univariant ( ref st, _dtor) => struct_llfields ( cx, st, sizing) ,
384
- NullablePointer { nonnull : ref st, _ } => struct_llfields ( cx, st, sizing) ,
397
+ CEnum ( ity, _, _) => ll_inttype ( cx, ity) ,
398
+ Univariant ( ref st, _) | NullablePointer { nonnull : ref st, _ } => {
399
+ match name {
400
+ None => Type :: struct_ ( struct_llfields ( cx, st, sizing) , st. packed ) ,
401
+ Some ( name) => { assert_eq ! ( sizing, false ) ; Type :: named_struct ( name) }
402
+ }
403
+ }
385
404
General ( ity, ref sts) => {
386
405
// We need a representation that has:
387
406
// * The alignment of the most-aligned field
@@ -394,8 +413,7 @@ fn generic_fields_of(cx: &mut CrateContext, r: &Repr, sizing: bool) -> ~[Type] {
394
413
// more of its own type, then use alignment-sized ints to get the rest
395
414
// of the size.
396
415
//
397
- // Note: if/when we start exposing SIMD vector types (or f80, on some
398
- // platforms that have it), this will need some adjustment.
416
+ // FIXME #10604: this breaks when vector types are present.
399
417
let size = sts. iter ( ) . map ( |st| st. size ) . max ( ) . unwrap ( ) ;
400
418
let most_aligned = sts. iter ( ) . max_by ( |st| st. align ) . unwrap ( ) ;
401
419
let align = most_aligned. align ;
@@ -411,9 +429,17 @@ fn generic_fields_of(cx: &mut CrateContext, r: &Repr, sizing: bool) -> ~[Type] {
411
429
assert_eq ! ( machine:: llalign_of_min( cx, pad_ty) as u64 , align) ;
412
430
let align_units = ( size + align - 1 ) / align;
413
431
assert_eq ! ( align % discr_size, 0 ) ;
414
- ~[ discr_ty,
432
+ let fields = ~[ discr_ty,
415
433
Type :: array ( & discr_ty, align / discr_size - 1 ) ,
416
- Type :: array ( & pad_ty, align_units - 1 ) ]
434
+ Type :: array ( & pad_ty, align_units - 1 ) ] ;
435
+ match name {
436
+ None => Type :: struct_ ( fields, false ) ,
437
+ Some ( name) => {
438
+ let mut llty = Type :: named_struct ( name) ;
439
+ llty. set_struct_body ( fields, false ) ;
440
+ llty
441
+ }
442
+ }
417
443
}
418
444
}
419
445
}
@@ -460,7 +486,8 @@ pub fn trans_get_discr(bcx: @mut Block, r: &Repr, scrutinee: ValueRef, cast_to:
460
486
signed = ity. is_signed ( ) ;
461
487
}
462
488
General ( ity, ref cases) => {
463
- val = load_discr ( bcx, ity, scrutinee, 0 , ( cases. len ( ) - 1 ) as Disr ) ;
489
+ let ptr = GEPi ( bcx, scrutinee, [ 0 , 0 ] ) ;
490
+ val = load_discr ( bcx, ity, ptr, 0 , ( cases. len ( ) - 1 ) as Disr ) ;
464
491
signed = ity. is_signed ( ) ;
465
492
}
466
493
Univariant ( * ) => {
@@ -487,9 +514,8 @@ fn nullable_bitdiscr(bcx: @mut Block, nonnull: &Struct, nndiscr: Disr, ptrfield:
487
514
}
488
515
489
516
/// Helper for cases where the discriminant is simply loaded.
490
- fn load_discr ( bcx : @mut Block , ity : IntType , scrutinee : ValueRef , min : Disr , max : Disr )
517
+ fn load_discr ( bcx : @mut Block , ity : IntType , ptr : ValueRef , min : Disr , max : Disr )
491
518
-> ValueRef {
492
- let ptr = GEPi ( bcx, scrutinee, [ 0 , 0 ] ) ;
493
519
let llty = ll_inttype ( bcx. ccx ( ) , ity) ;
494
520
assert_eq ! ( val_ty( ptr) , llty. ptr_to( ) ) ;
495
521
let bits = machine:: llbitsize_of_real ( bcx. ccx ( ) , llty) ;
@@ -546,7 +572,7 @@ pub fn trans_start_init(bcx: @mut Block, r: &Repr, val: ValueRef, discr: Disr) {
546
572
CEnum ( ity, min, max) => {
547
573
assert_discr_in_range ( ity, min, max, discr) ;
548
574
Store ( bcx, C_integral ( ll_inttype ( bcx. ccx ( ) , ity) , discr as u64 , true ) ,
549
- GEPi ( bcx , val, [ 0 , 0 ] ) )
575
+ val)
550
576
}
551
577
General ( ity, _) => {
552
578
Store ( bcx, C_integral ( ll_inttype ( bcx. ccx ( ) , ity) , discr as u64 , true ) ,
0 commit comments