summaryrefslogtreecommitdiffstats
path: root/test/CodeGen/ms-inline-asm.cpp
blob: 039cde9e10ed5a9fc5b9e50068c253e66eed677b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// REQUIRES: x86-registered-target
// RUN: %clang_cc1 -x c++ %s -triple i386-apple-darwin10 -fasm-blocks -emit-llvm -o - -std=c++11 | FileCheck %s

// rdar://13645930

struct Foo {
  static int *ptr;
  static int a, b;
  int arr[4];
  struct Bar {
    static int *ptr;
    char arr[2];
  };
};

void t1() {
// CHECK-LABEL: define void @_Z2t1v()
  Foo::ptr = (int *)0xDEADBEEF;
  Foo::Bar::ptr = (int *)0xDEADBEEF;
// CHECK: call void asm sideeffect inteldialect
// CHECK-SAME: mov eax, $0
// CHECK-SAME: mov eax, $1
// CHECK-SAME: mov eax, $2
// CHECK-SAME: mov eax, dword ptr $3
// CHECK-SAME: mov eax, dword ptr $4
// CHECK-SAME: "*m,*m,*m,*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3ptrE)
  __asm mov eax, Foo ::ptr
  __asm mov eax, Foo :: Bar :: ptr
  __asm mov eax, [Foo:: ptr]
  __asm mov eax, dword ptr [Foo :: ptr]
  __asm mov eax, dword ptr [Foo :: ptr]
}

int gvar = 10;
void t2() {
  int lvar = 10;
  __asm mov eax, offset Foo::ptr
  __asm mov eax, offset Foo::Bar::ptr
// CHECK-LABEL: define void @_Z2t2v()
// CHECK: call void asm sideeffect inteldialect
// CHECK-SAME: mov eax, $0
// CHECK-SAME: mov eax, $1
// CHECK-SAME: "r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32** @_ZN3Foo3ptrE, i32** @_ZN3Foo3Bar3ptrE)
}

// CHECK-LABEL: define void @_Z2t3v()
void t3() {
  __asm mov eax, LENGTH Foo::ptr
  __asm mov eax, LENGTH Foo::Bar::ptr
  __asm mov eax, LENGTH Foo::arr
  __asm mov eax, LENGTH Foo::Bar::arr

  __asm mov eax, TYPE Foo::ptr
  __asm mov eax, TYPE Foo::Bar::ptr
  __asm mov eax, TYPE Foo::arr
  __asm mov eax, TYPE Foo::Bar::arr

  __asm mov eax, SIZE Foo::ptr
  __asm mov eax, SIZE Foo::Bar::ptr
  __asm mov eax, SIZE Foo::arr
  __asm mov eax, SIZE Foo::Bar::arr
// CHECK: call void asm sideeffect inteldialect
// CHECK-SAME: mov eax, $$1
// CHECK-SAME: mov eax, $$1
// CHECK-SAME: mov eax, $$4
// CHECK-SAME: mov eax, $$2
// CHECK-SAME: mov eax, $$4
// CHECK-SAME: mov eax, $$4
// CHECK-SAME: mov eax, $$4
// CHECK-SAME: mov eax, $$1
// CHECK-SAME: mov eax, $$4
// CHECK-SAME: mov eax, $$4
// CHECK-SAME: mov eax, $$16
// CHECK-SAME: mov eax, $$2
// CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"()

}

struct T4 {
  int x;
  static int y;
  void test();
};

// CHECK-LABEL: define void @_ZN2T44testEv(
void T4::test() {
// CHECK: [[T0:%.*]] = alloca [[T4:%.*]]*,
// CHECK: [[THIS:%.*]] = load [[T4]]*, [[T4]]** [[T0]]
// CHECK: [[X:%.*]] = getelementptr inbounds [[T4]], [[T4]]* [[THIS]], i32 0, i32 0
  __asm mov eax, x;
  __asm mov y, eax;
// CHECK: call void asm sideeffect inteldialect
// CHECK-SAME: mov eax, $1
// CHECK-SAME: mov $0, eax
// CHECK-SAME: "=*m,*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* @_ZN2T41yE, i32* {{.*}})
}

template <class T> struct T5 {
  template <class U> static T create(U);
  void run();
};
// CHECK-LABEL: define void @_Z5test5v()
void test5() {
  // CHECK: [[X:%.*]] = alloca i32
  // CHECK: [[Y:%.*]] = alloca i32
  int x, y;
  __asm push y
  __asm call T5<int>::create<float>
  __asm mov x, eax
  // CHECK: call void asm sideeffect inteldialect
  // CHECK-SAME: push $0
  // CHECK-SAME: call dword ptr $2
  // CHECK-SAME: mov $1, eax
  // CHECK-SAME: "=*m,=*m,*m,~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %y, i32* %x, i32 (float)* @_ZN2T5IiE6createIfEEiT_)
}

// Just verify this doesn't emit an error.
void test6() {
  __asm {
   a:
   jmp a
  }
}

void t7_struct() {
  struct A {
    int a;
    int b;
  };
  __asm mov eax, [eax].A.b
  // CHECK-LABEL: define void @_Z9t7_structv
  // CHECK: call void asm sideeffect inteldialect
  // CHECK-SAME: mov eax, [eax + $$4]
  // CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"()
}

void t7_typedef() {
  typedef struct {
    int a;
    int b;
  } A;
  __asm mov eax, [eax].A.b
  // CHECK-LABEL: define void @_Z10t7_typedefv
  // CHECK: call void asm sideeffect inteldialect
  // CHECK-SAME: mov eax, [eax + $$4]
  // CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"()
}

void t7_using() {
  using A = struct {
    int a;
    int b;
  };
  __asm mov eax, [eax].A.b
  // CHECK-LABEL: define void @_Z8t7_usingv
  // CHECK: call void asm sideeffect inteldialect
  // CHECK-SAME: mov eax, [eax + $$4]
  // CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"()
}

void t8() {
  __asm some_label:
  // CHECK-LABEL: define void @_Z2t8v()
  // CHECK: call void asm sideeffect inteldialect
  // CHECK-SAME: L__MSASMLABEL_.${:uid}__some_label:
  // CHECK-SAME: "~{dirflag},~{fpsr},~{flags}"()
  struct A {
    static void g() {
      __asm jmp some_label ; This should jump forwards
      __asm some_label:
      __asm nop
      // CHECK-LABEL: define internal void @_ZZ2t8vEN1A1gEv()
      // CHECK: call void asm sideeffect inteldialect
      // CHECK-SAME: jmp L__MSASMLABEL_.${:uid}__some_label
      // CHECK-SAME: L__MSASMLABEL_.${:uid}__some_label:
      // CHECK-SAME: nop
      // CHECK-SAME: "~{dirflag},~{fpsr},~{flags}"()
    }
  };
  A::g();
}

void t9() {
  // CHECK-LABEL: define void @_Z2t9v()
  struct A {
    int a;
    int b;
    void g() {
      __asm mov eax, dword ptr [eax]this.b
      // CHECK: call void asm sideeffect inteldialect
      // CHECK-SAME: mov eax, dword ptr [eax + $$4]
      // CHECK-SAME: "~{eax},~{dirflag},~{fpsr},~{flags}"()
    }
  };
  A AA;
  AA.g();
}