@@ -50,6 +50,7 @@ use middle::trans::common::*;
50
50
use middle:: trans:: machine;
51
51
use middle:: trans:: type_of;
52
52
use middle:: trans:: type_:: Type ;
53
+ use middle:: trans:: adt;
53
54
use middle:: trans;
54
55
use middle:: ty;
55
56
use util:: ppaux:: ty_to_str;
@@ -560,6 +561,161 @@ fn create_tuple_metadata(cx: &mut CrateContext,
560
561
span) ;
561
562
}
562
563
564
+ // The stage0 snapshot does not yet support the fixes from PR #7557, so there are two versions of
565
+ // following function for now
566
+ #[ cfg( not( stage0) ) ]
567
+ fn create_enum_metadata ( cx : & mut CrateContext ,
568
+ enum_type : ty:: t ,
569
+ enum_def_id : ast:: def_id ,
570
+ substs : & ty:: substs ,
571
+ span : span )
572
+ -> DIType {
573
+
574
+ let enum_name = ty_to_str ( cx. tcx , enum_type) ;
575
+
576
+ // For empty enums there is an early exit. Just describe it as an empty struct with the
577
+ // appropriate type name
578
+ if ty:: type_is_empty ( cx. tcx , enum_type) {
579
+ return create_composite_type_metadata ( cx, Type :: nil ( ) , enum_name, & [ ] , & [ ] , & [ ] , span) ;
580
+ }
581
+
582
+ // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be
583
+ // needed in all of the following cases.
584
+ let discriminant_llvm_type = Type :: enum_discrim ( cx) ;
585
+ let ( discriminant_size, discriminant_align) = size_and_align_of ( cx, discriminant_llvm_type) ;
586
+
587
+ assert ! ( Type :: enum_discrim( cx) == cx. int_type) ;
588
+ let discriminant_type_metadata = get_or_create_type_metadata ( cx, ty:: mk_int ( ) , span) ;
589
+
590
+ let variants : & [ @ty:: VariantInfo ] = * ty:: enum_variants ( cx. tcx , enum_def_id) ;
591
+
592
+ let enumerators_metadata : ~[ DIDescriptor ] = variants
593
+ . iter ( )
594
+ . transform ( |v| {
595
+ let name : & str = cx. sess . str_of ( v. name ) ;
596
+ let discriminant_value = v. disr_val as c_ulonglong ;
597
+
598
+ do name. as_c_str |name| { unsafe {
599
+ llvm:: LLVMDIBuilderCreateEnumerator (
600
+ DIB ( cx) ,
601
+ name,
602
+ discriminant_value)
603
+ } }
604
+ } )
605
+ . collect ( ) ;
606
+
607
+ let loc = span_start ( cx, span) ;
608
+ let file_metadata = get_or_create_file_metadata ( cx, loc. file . name ) ;
609
+
610
+ let discriminant_type_metadata = do enum_name. as_c_str |enum_name| { unsafe {
611
+ llvm:: LLVMDIBuilderCreateEnumerationType (
612
+ DIB ( cx) ,
613
+ file_metadata,
614
+ enum_name,
615
+ file_metadata,
616
+ loc. line as c_uint ,
617
+ bytes_to_bits ( discriminant_size) ,
618
+ bytes_to_bits ( discriminant_align) ,
619
+ create_DIArray ( DIB ( cx) , enumerators_metadata) ,
620
+ discriminant_type_metadata)
621
+ } } ;
622
+
623
+ let type_rep = adt:: represent_type ( cx, enum_type) ;
624
+
625
+ match * type_rep {
626
+ adt:: CEnum ( * ) => {
627
+ return discriminant_type_metadata;
628
+ }
629
+ adt:: Univariant ( ref struct_def, _destroyed_flag) => {
630
+ assert ! ( variants. len( ) == 1 ) ;
631
+ return create_adt_struct_metadata ( cx, struct_def, variants[ 0 ] , None , span) ;
632
+ }
633
+ adt:: General ( ref struct_defs) => {
634
+ let variants_member_metadata : ~[ DIDescriptor ] = do struct_defs
635
+ . iter ( )
636
+ . enumerate ( )
637
+ . transform |( i, struct_def) | {
638
+ let variant_type_metadata = create_adt_struct_metadata (
639
+ cx,
640
+ struct_def,
641
+ variants[ i] ,
642
+ Some ( discriminant_type_metadata) ,
643
+ span) ;
644
+
645
+ do "" . as_c_str |name| { unsafe {
646
+ llvm:: LLVMDIBuilderCreateMemberType (
647
+ DIB ( cx) ,
648
+ file_metadata,
649
+ name,
650
+ file_metadata,
651
+ loc. line as c_uint ,
652
+ bytes_to_bits ( struct_def. size as uint ) ,
653
+ bytes_to_bits ( struct_def. align as uint ) ,
654
+ bytes_to_bits ( 0 ) ,
655
+ 0 ,
656
+ variant_type_metadata)
657
+ } }
658
+ } . collect ( ) ;
659
+
660
+ let enum_llvm_type = type_of:: type_of ( cx, enum_type) ;
661
+ let ( enum_type_size, enum_type_align) = size_and_align_of ( cx, enum_llvm_type) ;
662
+
663
+ return do enum_name. as_c_str |enum_name| { unsafe { llvm:: LLVMDIBuilderCreateUnionType (
664
+ DIB ( cx) ,
665
+ file_metadata,
666
+ enum_name,
667
+ file_metadata,
668
+ loc. line as c_uint ,
669
+ bytes_to_bits ( enum_type_size) ,
670
+ bytes_to_bits ( enum_type_align) ,
671
+ 0 , // Flags
672
+ create_DIArray ( DIB ( cx) , variants_member_metadata) ,
673
+ 0 ) // RuntimeLang
674
+ } } ;
675
+ }
676
+ _ => { return ptr:: null ( ) ; }
677
+ }
678
+
679
+ fn create_adt_struct_metadata ( cx : & mut CrateContext ,
680
+ struct_def : & adt:: Struct ,
681
+ variant_info : & ty:: VariantInfo ,
682
+ discriminant_type_metadata : Option < DIType > ,
683
+ span : span )
684
+ -> DICompositeType
685
+ {
686
+ let arg_llvm_types : ~[ Type ] = do struct_def. fields . map |& ty| { type_of:: type_of ( cx, ty) } ;
687
+ let arg_metadata : ~[ DIType ] = do struct_def. fields . iter ( ) . enumerate ( )
688
+ . transform |( i, & ty) | {
689
+ match discriminant_type_metadata {
690
+ Some ( metadata) if i == 0 => metadata,
691
+ _ => get_or_create_type_metadata ( cx, ty, span)
692
+ }
693
+ } . collect ( ) ;
694
+
695
+ let mut arg_names = match variant_info. arg_names {
696
+ Some ( ref names) => do names. map |ident| { cx. sess . str_of ( * ident) . to_owned ( ) } ,
697
+ None => do variant_info. args . map |_| { ~"" }
698
+ } ;
699
+
700
+ if ( discriminant_type_metadata. is_some ( ) ) {
701
+ arg_names. insert ( 0 , ~"") ;
702
+ }
703
+
704
+ let variant_llvm_type = Type :: struct_ ( arg_llvm_types, struct_def. packed ) ;
705
+ let variant_name : & str = cx. sess . str_of ( variant_info. name ) ;
706
+
707
+ return create_composite_type_metadata (
708
+ cx,
709
+ variant_llvm_type,
710
+ variant_name,
711
+ arg_llvm_types,
712
+ arg_names,
713
+ arg_metadata,
714
+ span) ;
715
+ }
716
+ }
717
+
718
+ #[ cfg( stage0) ]
563
719
fn create_enum_metadata ( cx : & mut CrateContext ,
564
720
enum_type : ty:: t ,
565
721
enum_def_id : ast:: def_id ,
0 commit comments