summaryrefslogtreecommitdiff
path: root/test/Sema/ms-inline-asm.c
blob: 3fc74fa99c35eba82a4469d16ae6564e9fac38c3 (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
// REQUIRES: x86-registered-target
// RUN: %clang_cc1 %s -triple i386-apple-darwin10 -fms-extensions -fasm-blocks -Wno-microsoft -Wunused-label -verify -fsyntax-only

void t1(void) { 
 __asm __asm // expected-error {{__asm used with no assembly instructions}}
}

void f() {
  int foo;
  __asm { 
    mov eax, eax
    .unknowndirective // expected-error {{unknown directive}}
  }
  f();
  __asm {
    mov eax, 1+=2 // expected-error {{unknown token in expression}}
  }
  f();
  __asm {
    mov eax, 1+++ // expected-error {{unknown token in expression}}
  }
  f();
  __asm {
    mov eax, LENGTH bar // expected-error {{unable to lookup expression}}
  }
  f();
  __asm {
    mov eax, SIZE bar // expected-error {{unable to lookup expression}}
  }
  f();
  __asm {
    mov eax, TYPE bar // expected-error {{unable to lookup expression}} expected-error {{use of undeclared label 'bar'}}
  }
}

void rdar15318432(void) {
  // We used to crash on this.  When LLVM called back to Clang to parse a name
  // and do name lookup, if parsing failed, we did not restore the lexer state
  // properly.

  __asm {
    and ecx, ~15
  }

  int x = 0;
  __asm {
    and ecx, x
    and ecx, ~15
  }
}

static int global;

int t2(int *arr, int i) {
  __asm {
    mov eax, arr;
    mov eax, arr[0];
    mov eax, arr[1 + 2];
    mov eax, arr[1 + (2 * 5) - 3 + 1<<1];
  }

  // expected-error@+1 {{cannot use more than one symbol in memory operand}}
  __asm { mov eax, arr[i] }
  // expected-error@+1 {{cannot use more than one symbol in memory operand}}
  __asm { mov eax, global[i] }

  // expected-error@+1 {{cannot use more than one symbol in memory operand}}
  __asm mov eax, [arr + i];
  return 0;
}

typedef struct {
  int a;
  int b;
} A;

void t3() {
  __asm { mov eax, [eax] UndeclaredId } // expected-error {{unknown token in expression}} expected-error {{use of undeclared label 'UndeclaredId'}}

  // FIXME: Only emit one diagnostic here.
  // expected-error@+3 {{use of undeclared label 'A'}}
  // expected-error@+2 {{unexpected type name 'A': expected expression}}
  // expected-error@+1 {{unknown token in expression}}
  __asm { mov eax, [eax] A }
}

void t4() {
  // The dot in the "intel dot operator" is optional in MSVC.  MSVC also does
  // global field lookup, but we don't.
  __asm { mov eax, [0] A.a }
  __asm { mov eax, [0].A.a }
  __asm { mov eax, [0].a } // expected-error {{Unable to lookup field reference!}}
  __asm { mov eax, fs:[0] A.a }
  __asm { mov eax, fs:[0].A.a }
  __asm { mov eax, fs:[0].a } // expected-error {{Unable to lookup field reference!}}
  __asm { mov eax, fs:[0]. A.a } // expected-error {{unexpected token in argument list}}
}

void test_operand_size() {
  __asm { call word t4 } // expected-error {{Expected 'PTR' or 'ptr' token!}}
}

__declspec(naked) int t5(int x) { // expected-note {{attribute is here}}
  asm { movl eax, x } // expected-error {{parameter references not allowed in naked functions}} expected-error {{use of undeclared label 'x'}}
  asm { retl }
}

int y;
__declspec(naked) int t6(int x) {
  asm { mov eax, y } // No error.
  asm { ret }
}

void t7() {
  __asm {
    foo: // expected-note {{inline assembly label 'foo' declared here}}
    mov eax, 0
  }
  goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
}

void t8() {
  __asm foo: // expected-note {{inline assembly label 'foo' declared here}}
  __asm mov eax, 0
  goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
}

void t9() {
  goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
  __asm {
    foo: // expected-note {{inline assembly label 'foo' declared here}}
    mov eax, 0
  }
}

void t10() {
  goto foo; // expected-error {{cannot jump from this goto statement to label 'foo' inside an inline assembly block}}
  __asm foo: // expected-note {{inline assembly label 'foo' declared here}}
  __asm mov eax, 0
}

void t11() {
foo:
  __asm mov eax, foo // expected-error {{use of undeclared label 'foo'}} expected-warning {{unused label 'foo'}}
}

void t12() {
  __asm foo:
  __asm bar: // expected-warning {{unused label 'bar'}}
  __asm jmp foo
}