2016-06-25 00:24:24 +08:00
; RUN: llc < %s -filetype=obj -o - | llvm-readobj - -codeview | FileCheck %s
; C++ source to regenerate:
; $ cat t.cpp
; struct A { int a; };
2018-05-15 05:21:22 +08:00
; struct B : virtual A { int b; virtual int get() { return b; } };
; struct C : virtual A { int c; virtual int get() { return c; } };
2016-06-25 00:24:24 +08:00
; struct D : B, C {
; virtual void f(); // make vbptr not offset zero
; int d;
; };
; D d;
; $ clang -fno-rtti -g -gcodeview t.cpp -emit-llvm -S -o t.ll -O1
2018-05-15 05:21:22 +08:00
; struct B's field list comes first.
2016-06-25 00:24:24 +08:00
; CHECK: FieldList ({{.*}}) {
; CHECK-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203)
; CHECK-NEXT: VirtualBaseClass {
2016-08-19 00:49:29 +08:00
; CHECK-NEXT: TypeLeafKind: LF_VBCLASS (0x1401)
2016-06-25 00:24:24 +08:00
; CHECK-NEXT: AccessSpecifier: Public (0x3)
; CHECK-NEXT: BaseType: A ({{.*}})
; CHECK-NEXT: VBPtrType: const int* ({{.*}})
2018-05-15 05:21:22 +08:00
; CHECK-NEXT: VBPtrOffset: 0x8
2016-06-25 00:24:24 +08:00
; CHECK-NEXT: VBTableIndex: 0x1
; CHECK-NEXT: }
; CHECK: }
2018-05-15 05:21:22 +08:00
; struct A's field list comes next.
; CHECK: FieldList ({{.*}})
; CHECK-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203)
; CHECK: }
; struct C's field list comes next.
; CHECK: FieldList ({{.*}})
; CHECK-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203)
; CHECK-NEXT: VirtualBaseClass {
; CHECK-NEXT: TypeLeafKind: LF_VBCLASS (0x1401)
; CHECK-NEXT: AccessSpecifier: Public (0x3)
; CHECK-NEXT: BaseType: A ({{.*}})
; CHECK-NEXT: VBPtrType: const int* ({{.*}})
; CHECK-NEXT: VBPtrOffset: 0x8
; CHECK-NEXT: VBTableIndex: 0x1
; CHECK-NEXT: }
; CHECK: }
; struct D's field list is last.
; CHECK: FieldList ({{.*}}) {
; CHECK-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203)
; CHECK-NEXT: BaseClass {
; CHECK-NEXT: TypeLeafKind: LF_BCLASS (0x1400)
; CHECK-NEXT: AccessSpecifier: Public (0x3)
; CHECK-NEXT: BaseType: B ({{.*}})
; CHECK-NEXT: BaseOffset: 0x0
; CHECK-NEXT: }
; CHECK-NEXT: BaseClass {
; CHECK-NEXT: TypeLeafKind: LF_BCLASS (0x1400)
; CHECK-NEXT: AccessSpecifier: Public (0x3)
; CHECK-NEXT: BaseType: C ({{.*}})
; CHECK-NEXT: BaseOffset: 0x18
; CHECK-NEXT: }
; CHECK-NEXT: IndirectVirtualBaseClass {
; CHECK-NEXT: TypeLeafKind: LF_IVBCLASS (0x1402)
; CHECK-NEXT: AccessSpecifier: Public (0x3)
; CHECK-NEXT: BaseType: A ({{.*}})
; CHECK-NEXT: VBPtrType: const int* ({{.*}})
; CHECK-NEXT: VBPtrOffset: 0x8
; CHECK-NEXT: VBTableIndex: 0x1
; CHECK-NEXT: }
; CHECK: }
2016-06-25 00:24:24 +08:00
; ModuleID = 't.cpp'
source_filename = "t.cpp"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
2018-05-15 05:21:22 +08:00
target triple = "x86_64-pc-windows-msvc19.12.25835"
2016-06-25 00:24:24 +08:00
2018-05-15 05:21:22 +08:00
%struct.D = type { %struct.B.base , %struct.C.base , i32 , [ 4 x i8 ] , %struct.A }
%struct.B.base = type { i32 ( . . . ) * * , i32 * , i32 }
%struct.C.base = type { i32 ( . . . ) * * , i32 * , i32 }
2016-06-25 00:24:24 +08:00
%struct.A = type { i32 }
2018-05-15 05:21:22 +08:00
%struct.B = type { i32 ( . . . ) * * , i32 * , i32 , [ 4 x i8 ] , %struct.A }
%struct.C = type { i32 ( . . . ) * * , i32 * , i32 , [ 4 x i8 ] , %struct.A }
$ "?get@B@@UEAAHXZ" = comdat any
$ "?get@C@@UEAAHXZ" = comdat any
$ "??_8D@@7BB@@@" = comdat any
2016-06-25 00:24:24 +08:00
2018-05-15 05:21:22 +08:00
$ "??_8D@@7BC@@@" = comdat any
2016-06-25 00:24:24 +08:00
2018-05-15 05:21:22 +08:00
$ "??_7D@@6BB@@@" = comdat any
2016-06-25 00:24:24 +08:00
2018-05-15 05:21:22 +08:00
$ "??_7D@@6BC@@@" = comdat any
2016-06-25 00:24:24 +08:00
2018-05-15 05:21:22 +08:00
@"?d@@3UD@@A" = d s o _ l o c a l local_unnamed_addr global %struct.D { %struct.B.base { i32 ( . . . ) * * bitcast ( { [ 2 x i8 * ] } * @"??_7D@@6BB@@@" to i32 ( . . . ) * * ) , i32 * getelementptr inbounds ( [ 2 x i32 ] , [ 2 x i32 ] * @"??_8D@@7BB@@@" , i32 0 , i32 0 ) , i32 0 } , %struct.C.base { i32 ( . . . ) * * bitcast ( { [ 1 x i8 * ] } * @"??_7D@@6BC@@@" to i32 ( . . . ) * * ) , i32 * getelementptr inbounds ( [ 2 x i32 ] , [ 2 x i32 ] * @"??_8D@@7BC@@@" , i32 0 , i32 0 ) , i32 0 } , i32 0 , [ 4 x i8 ] zeroinitializer , %struct.A zeroinitializer } , align 8 , !dbg !0
@"??_8D@@7BB@@@" = linkonce_odr unnamed_addr constant [ 2 x i32 ] [ i32 -8 , i32 48 ] , comdat
@"??_8D@@7BC@@@" = linkonce_odr unnamed_addr constant [ 2 x i32 ] [ i32 -8 , i32 24 ] , comdat
@"??_7D@@6BB@@@" = linkonce_odr unnamed_addr constant { [ 2 x i8 * ] } { [ 2 x i8 * ] [ i8 * bitcast ( i32 ( %struct.B * ) * @"?get@B@@UEAAHXZ" to i8 * ) , i8 * bitcast ( void ( %struct.D * ) * @"?f@D@@UEAAXXZ" to i8 * ) ] } , comdat
@"??_7D@@6BC@@@" = linkonce_odr unnamed_addr constant { [ 1 x i8 * ] } { [ 1 x i8 * ] [ i8 * bitcast ( i32 ( %struct.C * ) * @"?get@C@@UEAAHXZ" to i8 * ) ] } , comdat
2016-10-26 06:11:52 +08:00
@llvm.global_ctors = appending global [ 0 x { i32 , void ( ) * , i8 * } ] zeroinitializer
2018-05-15 05:21:22 +08:00
; Function Attrs: nounwind uwtable
define linkonce_odr d s o _ l o c a l i32 @"?get@B@@UEAAHXZ" ( %struct.B * %this ) unnamed_addr #0 comdat align 2 !dbg !46 {
entry:
call void @llvm.dbg.value ( metadata %struct.B * %this , metadata !48 , metadata !DIExpression ( ) ) , !dbg !50
%b = getelementptr inbounds %struct.B , %struct.B * %this , i64 0 , i32 2 , !dbg !51
%0 = load i32 , i32 * %b , align 8 , !dbg !51 , !tbaa !52
ret i32 %0 , !dbg !51
}
2016-10-26 06:11:52 +08:00
2018-05-15 05:21:22 +08:00
declare d s o _ l o c a l void @"?f@D@@UEAAXXZ" ( %struct.D * ) unnamed_addr #1
; Function Attrs: nounwind uwtable
define linkonce_odr d s o _ l o c a l i32 @"?get@C@@UEAAHXZ" ( %struct.C * %this ) unnamed_addr #0 comdat align 2 !dbg !57 {
entry:
call void @llvm.dbg.value ( metadata %struct.C * %this , metadata !59 , metadata !DIExpression ( ) ) , !dbg !61
%c = getelementptr inbounds %struct.C , %struct.C * %this , i64 0 , i32 2 , !dbg !62
%0 = load i32 , i32 * %c , align 8 , !dbg !62 , !tbaa !63
ret i32 %0 , !dbg !62
}
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.value ( metadata , metadata , metadata ) #2
attributes #0 = { nounwind uwtable "correctly-rounded-divide-sqrt-fp-math" = "false" "disable-tail-calls" = "false" "less-precise-fpmad" = "false" "no-frame-pointer-elim" = "false" "no-infs-fp-math" = "false" "no-jump-tables" = "false" "no-nans-fp-math" = "false" "no-signed-zeros-fp-math" = "false" "no-trapping-math" = "false" "stack-protector-buffer-size" = "8" "target-cpu" = "x86-64" "target-features" = "+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math" = "false" "use-soft-float" = "false" }
attributes #1 = { "correctly-rounded-divide-sqrt-fp-math" = "false" "disable-tail-calls" = "false" "less-precise-fpmad" = "false" "no-frame-pointer-elim" = "false" "no-infs-fp-math" = "false" "no-nans-fp-math" = "false" "no-signed-zeros-fp-math" = "false" "no-trapping-math" = "false" "stack-protector-buffer-size" = "8" "target-cpu" = "x86-64" "target-features" = "+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math" = "false" "use-soft-float" = "false" }
attributes #2 = { nounwind readnone s p e c u l a t a b l e }
2016-10-26 06:11:52 +08:00
2016-12-22 08:45:21 +08:00
!llvm.dbg.cu = ! { !2 }
2018-05-15 05:21:22 +08:00
!llvm.module.flags = ! { !41 , !42 , !43 , !44 }
!llvm.ident = ! { !45 }
2016-12-22 08:45:21 +08:00
2018-05-15 05:21:22 +08:00
!0 = !DIGlobalVariableExpression ( var: !1 , expr: !DIExpression ( ) )
!1 = distinct !DIGlobalVariable ( name: "d" , linkageName: "?d@@3UD@@A" , scope: !2 , file: !3 , line: 8 , type: !6 , isLocal: false , isDefinition: true )
!2 = distinct !DICompileUnit ( language: D W _ L A N G _ C _ p l u s _ p l u s , file: !3 , producer: "clang version 7.0.0 (trunk)" , isOptimized: true , runtimeVersion: 0 , emissionKind: F u l l D e b u g , enums: !4 , globals: !5 )
!3 = !DIFile ( filename: "t.cpp" , directory: "C:\5CPath\5CTo\5CDirectory" , checksumkind: C S K _ M D 5 , checksum: "7477d4db6bf8a461a719bcaab9c6d65e" )
2016-12-22 08:45:21 +08:00
!4 = ! { }
!5 = ! { !0 }
2018-05-15 05:21:22 +08:00
!6 = distinct !DICompositeType ( tag: D W _ T A G _ s t r u c t u r e _ type , name: "D" , file: !3 , line: 4 , size: 512 , flags: D I F l a g T y p e P a s s B y R e f e r e n c e , elements: !7 , vtableHolder: !9 , identifier: ".?AUD@@" )
!7 = ! { !8 , !24 , !34 , !35 , !36 , !37 }
!8 = !DIDerivedType ( tag: D W _ T A G _ i n h e r i t a n c e , scope: !6 , baseType: !9 , extraData: i32 0 )
!9 = distinct !DICompositeType ( tag: D W _ T A G _ s t r u c t u r e _ type , name: "B" , file: !3 , line: 2 , size: 256 , flags: D I F l a g T y p e P a s s B y R e f e r e n c e , elements: !10 , vtableHolder: !9 , identifier: ".?AUB@@" )
!10 = ! { !11 , !16 , !17 , !19 , !20 }
!11 = !DIDerivedType ( tag: D W _ T A G _ i n h e r i t a n c e , scope: !9 , baseType: !12 , offset: 4 , flags: D I F l a g V i r t u a l , extraData: i32 8 )
!12 = distinct !DICompositeType ( tag: D W _ T A G _ s t r u c t u r e _ type , name: "A" , file: !3 , line: 1 , size: 32 , flags: D I F l a g T y p e P a s s B y V a l u e , elements: !13 , identifier: ".?AUA@@" )
!13 = ! { !14 }
!14 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "a" , scope: !12 , file: !3 , line: 1 , baseType: !15 , size: 32 )
!15 = !DIBasicType ( name: "int" , size: 32 , encoding: D W _ A T E _ s i g n e d )
!16 = !DIDerivedType ( tag: D W _ T A G _ p o i n t e r _ type , name: "__vtbl_ptr_type" , baseType: null , size: 64 )
!17 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "_vptr$B" , scope: !3 , file: !3 , baseType: !18 , size: 64 , flags: D I F l a g A r t i f i c i a l )
!18 = !DIDerivedType ( tag: D W _ T A G _ p o i n t e r _ type , baseType: !16 , size: 64 )
!19 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "b" , scope: !9 , file: !3 , line: 2 , baseType: !15 , size: 32 , offset: 128 )
!20 = !DISubprogram ( name: "get" , linkageName: "?get@B@@UEAAHXZ" , scope: !9 , file: !3 , line: 2 , type: !21 , isLocal: false , isDefinition: false , scopeLine: 2 , containingType: !9 , virtuality: D W _ V I R T U A L I T Y _ v i r t u a l , virtualIndex: 0 , flags: D I F l a g P r o t o t y p e d | D I F l a g I n t r o d u c e d V i r t u a l , isOptimized: true )
!21 = !DISubroutineType ( types: !22 )
!22 = ! { !15 , !23 }
!23 = !DIDerivedType ( tag: D W _ T A G _ p o i n t e r _ type , baseType: !9 , size: 64 , flags: D I F l a g A r t i f i c i a l | D I F l a g O b j e c t P o i n t e r )
!24 = !DIDerivedType ( tag: D W _ T A G _ i n h e r i t a n c e , scope: !6 , baseType: !25 , offset: 192 , extraData: i32 0 )
!25 = distinct !DICompositeType ( tag: D W _ T A G _ s t r u c t u r e _ type , name: "C" , file: !3 , line: 3 , size: 256 , flags: D I F l a g T y p e P a s s B y R e f e r e n c e , elements: !26 , vtableHolder: !25 , identifier: ".?AUC@@" )
!26 = ! { !27 , !16 , !28 , !29 , !30 }
!27 = !DIDerivedType ( tag: D W _ T A G _ i n h e r i t a n c e , scope: !25 , baseType: !12 , offset: 4 , flags: D I F l a g V i r t u a l , extraData: i32 8 )
!28 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "_vptr$C" , scope: !3 , file: !3 , baseType: !18 , size: 64 , flags: D I F l a g A r t i f i c i a l )
!29 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "c" , scope: !25 , file: !3 , line: 3 , baseType: !15 , size: 32 , offset: 128 )
!30 = !DISubprogram ( name: "get" , linkageName: "?get@C@@UEAAHXZ" , scope: !25 , file: !3 , line: 3 , type: !31 , isLocal: false , isDefinition: false , scopeLine: 3 , containingType: !25 , virtuality: D W _ V I R T U A L I T Y _ v i r t u a l , virtualIndex: 0 , flags: D I F l a g P r o t o t y p e d | D I F l a g I n t r o d u c e d V i r t u a l , isOptimized: true )
!31 = !DISubroutineType ( types: !32 )
!32 = ! { !15 , !33 }
!33 = !DIDerivedType ( tag: D W _ T A G _ p o i n t e r _ type , baseType: !25 , size: 64 , flags: D I F l a g A r t i f i c i a l | D I F l a g O b j e c t P o i n t e r )
!34 = !DIDerivedType ( tag: D W _ T A G _ i n h e r i t a n c e , scope: !6 , baseType: !12 , offset: 4 , flags: D I F l a g I n d i r e c t V i r t u a l B a s e , extraData: i32 8 )
!35 = !DIDerivedType ( tag: D W _ T A G _ p o i n t e r _ type , name: "__vtbl_ptr_type" , baseType: null , size: 128 )
!36 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "d" , scope: !6 , file: !3 , line: 6 , baseType: !15 , size: 32 , offset: 384 )
!37 = !DISubprogram ( name: "f" , linkageName: "?f@D@@UEAAXXZ" , scope: !6 , file: !3 , line: 5 , type: !38 , isLocal: false , isDefinition: false , scopeLine: 5 , containingType: !6 , virtuality: D W _ V I R T U A L I T Y _ v i r t u a l , virtualIndex: 1 , flags: D I F l a g P r o t o t y p e d | D I F l a g I n t r o d u c e d V i r t u a l , isOptimized: true )
!38 = !DISubroutineType ( types: !39 )
!39 = ! { null , !40 }
!40 = !DIDerivedType ( tag: D W _ T A G _ p o i n t e r _ type , baseType: !6 , size: 64 , flags: D I F l a g A r t i f i c i a l | D I F l a g O b j e c t P o i n t e r )
!41 = ! { i32 2 , !"CodeView" , i32 1 }
!42 = ! { i32 2 , !"Debug Info Version" , i32 3 }
!43 = ! { i32 1 , !"wchar_size" , i32 2 }
!44 = ! { i32 7 , !"PIC Level" , i32 2 }
!45 = ! { !"clang version 7.0.0 (trunk)" }
!46 = distinct !DISubprogram ( name: "get" , linkageName: "?get@B@@UEAAHXZ" , scope: !9 , file: !3 , line: 2 , type: !21 , isLocal: false , isDefinition: true , scopeLine: 2 , flags: D I F l a g P r o t o t y p e d , isOptimized: true , unit: !2 , declaration: !20 , retainedNodes: !47 )
!47 = ! { !48 }
!48 = !DILocalVariable ( name: "this" , arg: 1 , scope: !46 , type: !49 , flags: D I F l a g A r t i f i c i a l | D I F l a g O b j e c t P o i n t e r )
!49 = !DIDerivedType ( tag: D W _ T A G _ p o i n t e r _ type , baseType: !9 , size: 64 )
!50 = !DILocation ( line: 0 , scope: !46 )
!51 = !DILocation ( line: 2 , scope: !46 )
!52 = ! { !53 , !54 , i64 16 }
!53 = ! { !"?AUB@@" , !54 , i64 16 }
!54 = ! { !"int" , !55 , i64 0 }
!55 = ! { !"omnipotent char" , !56 , i64 0 }
!56 = ! { !"Simple C++ TBAA" }
!57 = distinct !DISubprogram ( name: "get" , linkageName: "?get@C@@UEAAHXZ" , scope: !25 , file: !3 , line: 3 , type: !31 , isLocal: false , isDefinition: true , scopeLine: 3 , flags: D I F l a g P r o t o t y p e d , isOptimized: true , unit: !2 , declaration: !30 , retainedNodes: !58 )
!58 = ! { !59 }
!59 = !DILocalVariable ( name: "this" , arg: 1 , scope: !57 , type: !60 , flags: D I F l a g A r t i f i c i a l | D I F l a g O b j e c t P o i n t e r )
!60 = !DIDerivedType ( tag: D W _ T A G _ p o i n t e r _ type , baseType: !25 , size: 64 )
!61 = !DILocation ( line: 0 , scope: !57 )
!62 = !DILocation ( line: 3 , scope: !57 )
!63 = ! { !64 , !54 , i64 16 }
!64 = ! { !"?AUC@@" , !54 , i64 16 }