blob: ecbb84337975d0edd3591e85939e8372ab9731e8 [file] [log] [blame]
Timur Iskhodzhanov88fd4392013-08-21 06:25:03 +00001// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
Peter Collingbourne66f82e62013-06-28 20:45:28 +00002
Timur Iskhodzhanov88fd4392013-08-21 06:25:03 +00003struct VBase {
4 virtual void foo();
5 virtual void bar();
6 int field;
Peter Collingbourne66f82e62013-06-28 20:45:28 +00007};
8
Timur Iskhodzhanov88fd4392013-08-21 06:25:03 +00009struct B : virtual VBase {
10 virtual void foo();
11 virtual void bar();
12};
13
14void B::foo() {
15// CHECK: define x86_thiscallcc void @"\01?foo@B@@UAEXXZ"(i8*
16//
17// B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we
18// need to adjust 'this' before use.
19//
20// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B*, align 4
21// CHECK: %[[THIS_i8:.*]] = getelementptr i8* %[[ECX:.*]], i64 -8
22// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_i8]] to %struct.B*
23// CHECK: store %struct.B* %[[THIS]], %struct.B** %[[THIS_ADDR]], align 4
24
25 field = 42;
26// CHECK: %[[THIS:.*]] = load %struct.B** %[[THIS_ADDR]]
27// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
28// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 0
29// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
30// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
31// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
32// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
33// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
34// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
35// CHECK: %[[THIS8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
36// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS8]], i32 %[[VBOFFSET]]
37// CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
38// CHECK: %[[FIELD:.*]] = getelementptr inbounds %struct.VBase* %[[VBASE]], i32 0, i32 1
39// CHECK: store i32 42, i32* %[[FIELD]], align 4
40//
41// CHECK: ret void
42}
43
44void call_vbase_bar(B *obj) {
45// CHECK: define void @"\01?call_vbase_bar@@YAXPAUB@@@Z"(%struct.B* %obj)
46// CHECK: %[[OBJ:.*]] = load %struct.B
47
48 obj->bar();
49// When calling a vbase's virtual method, one needs to adjust 'this'
50// at the caller site.
51//
52// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
53// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
54// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
55// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
56// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
57// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
58// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
59// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
60// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
61// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
62// CHECK: %[[VFTABLE:.*]] = load void (i8*)*** %[[VFPTR]]
63// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)** %[[VFTABLE]], i64 1
64// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)** %[[VFUN]]
65//
66// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
67// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 0
68// CHECK: %[[VBPTR8:.*]] = bitcast i8* %[[VBPTR]] to i8**
69// CHECK: %[[VBTABLE:.*]] = load i8** %[[VBPTR8]]
70// CHECK: %[[VBENTRY8:.*]] = getelementptr inbounds i8* %[[VBTABLE]], i32 4
71// CHECK: %[[VBENTRY:.*]] = bitcast i8* %[[VBENTRY8]] to i32*
72// CHECK: %[[VBOFFSET32:.*]] = load i32* %[[VBENTRY]]
73// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
74// CHECK: %[[VBASE:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
75//
76// CHECK: call x86_thiscallcc void %[[VFUN_VALUE]](i8* %[[VBASE]])
77//
78// CHECK: ret void
79}