Skip to content

Commit ce29291

Browse files
committedAug 6, 2019
Delay diagnosing asm constraints that require immediates until after inlining
Summary: An inline asm call may result in an immediate input value after inlining. Therefore, don't emit a diagnostic here if the input isn't an immediate. Reviewers: joerg, eli.friedman, rsmith Subscribers: asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, s.egerton, krytarowski, mgorny, riccibruno, eraman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D60943 llvm-svn: 368104
1 parent 0b168ff commit ce29291

File tree

6 files changed

+35
-62
lines changed

6 files changed

+35
-62
lines changed
 

Diff for: ‎clang/lib/CodeGen/CGStmt.cpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -1846,11 +1846,9 @@ llvm::Value* CodeGenFunction::EmitAsmInput(
18461846
InputExpr->EvaluateAsRValue(EVResult, getContext(), true);
18471847

18481848
llvm::APSInt IntResult;
1849-
if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(),
1850-
getContext()))
1851-
llvm_unreachable("Invalid immediate constant!");
1852-
1853-
return llvm::ConstantInt::get(getLLVMContext(), IntResult);
1849+
if (EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(),
1850+
getContext()))
1851+
return llvm::ConstantInt::get(getLLVMContext(), IntResult);
18541852
}
18551853

18561854
Expr::EvalResult Result;

Diff for: ‎clang/lib/Sema/SemaStmtAsm.cpp

+13-19
Original file line numberDiff line numberDiff line change
@@ -383,25 +383,19 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
383383
} else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
384384
if (!InputExpr->isValueDependent()) {
385385
Expr::EvalResult EVResult;
386-
if (!InputExpr->EvaluateAsRValue(EVResult, Context, true))
387-
return StmtError(
388-
Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
389-
<< Info.getConstraintStr() << InputExpr->getSourceRange());
390-
391-
// For compatibility with GCC, we also allow pointers that would be
392-
// integral constant expressions if they were cast to int.
393-
llvm::APSInt IntResult;
394-
if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(),
395-
Context))
396-
return StmtError(
397-
Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected)
398-
<< Info.getConstraintStr() << InputExpr->getSourceRange());
399-
400-
if (!Info.isValidAsmImmediate(IntResult))
401-
return StmtError(Diag(InputExpr->getBeginLoc(),
402-
diag::err_invalid_asm_value_for_constraint)
403-
<< IntResult.toString(10) << Info.getConstraintStr()
404-
<< InputExpr->getSourceRange());
386+
if (InputExpr->EvaluateAsRValue(EVResult, Context, true)) {
387+
// For compatibility with GCC, we also allow pointers that would be
388+
// integral constant expressions if they were cast to int.
389+
llvm::APSInt IntResult;
390+
if (EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(),
391+
Context))
392+
if (!Info.isValidAsmImmediate(IntResult))
393+
return StmtError(Diag(InputExpr->getBeginLoc(),
394+
diag::err_invalid_asm_value_for_constraint)
395+
<< IntResult.toString(10)
396+
<< Info.getConstraintStr()
397+
<< InputExpr->getSourceRange());
398+
}
405399
}
406400

407401
} else {

Diff for: ‎clang/test/CodeGen/pr41027.c

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -S -O2 -o - %s | FileCheck %s
2+
3+
// CHECK-LABEL: f:
4+
// CHECK: movl $1, %eax
5+
// CHECK-NEXT: #APP
6+
// CHECK-NEXT: outl %eax, $1
7+
// CHECK-NEXT: #NO_APP
8+
9+
static inline void pr41027(unsigned a, unsigned b) {
10+
if (__builtin_constant_p(a)) {
11+
__asm__ volatile("outl %0,%w1" : : "a"(b), "n"(a));
12+
} else {
13+
__asm__ volatile("outl %0,%w1" : : "a"(b), "d"(a));
14+
}
15+
}
16+
17+
void f(unsigned port) {
18+
pr41027(1, 1);
19+
}

Diff for: ‎clang/test/Sema/inline-asm-validate-riscv.c

-3
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,20 @@
44
void I(int i) {
55
static const int BelowMin = -2049;
66
static const int AboveMax = 2048;
7-
asm volatile ("" :: "I"(i)); // expected-error{{constraint 'I' expects an integer constant expression}}
87
asm volatile ("" :: "I"(BelowMin)); // expected-error{{value '-2049' out of range for constraint 'I'}}
98
asm volatile ("" :: "I"(AboveMax)); // expected-error{{value '2048' out of range for constraint 'I'}}
109
}
1110

1211
void J(int j) {
1312
static const int BelowMin = -1;
1413
static const int AboveMax = 1;
15-
asm volatile ("" :: "J"(j)); // expected-error{{constraint 'J' expects an integer constant expression}}
1614
asm volatile ("" :: "J"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'J'}}
1715
asm volatile ("" :: "J"(AboveMax)); // expected-error{{value '1' out of range for constraint 'J'}}
1816
}
1917

2018
void K(int k) {
2119
static const int BelowMin = -1;
2220
static const int AboveMax = 32;
23-
asm volatile ("" :: "K"(k)); // expected-error{{constraint 'K' expects an integer constant expression}}
2421
asm volatile ("" :: "K"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'K'}}
2522
asm volatile ("" :: "K"(AboveMax)); // expected-error{{value '32' out of range for constraint 'K'}}
2623
}

Diff for: ‎clang/test/Sema/inline-asm-validate-x86.c

-25
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
void I(int i, int j) {
55
static const int BelowMin = -1;
66
static const int AboveMax = 32;
7-
__asm__("xorl %0,%2"
8-
: "=r"(i)
9-
: "0"(i), "I"(j)); // expected-error{{constraint 'I' expects an integer constant expression}}
107
__asm__("xorl %0,%2"
118
: "=r"(i)
129
: "0"(i), "I"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'I'}}
@@ -21,9 +18,6 @@ void I(int i, int j) {
2118
void J(int i, int j) {
2219
static const int BelowMin = -1;
2320
static const int AboveMax = 64;
24-
__asm__("xorl %0,%2"
25-
: "=r"(i)
26-
: "0"(i), "J"(j)); // expected-error{{constraint 'J' expects an integer constant expression}}
2721
__asm__("xorl %0,%2"
2822
: "=r"(i)
2923
: "0"(i), "J"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'J'}}
@@ -38,9 +32,6 @@ void J(int i, int j) {
3832
void K(int i, int j) {
3933
static const int BelowMin = -129;
4034
static const int AboveMax = 128;
41-
__asm__("xorl %0,%2"
42-
: "=r"(i)
43-
: "0"(i), "K"(j)); // expected-error{{constraint 'K' expects an integer constant expression}}
4435
__asm__("xorl %0,%2"
4536
: "=r"(i)
4637
: "0"(i), "K"(BelowMin)); // expected-error{{value '-129' out of range for constraint 'K'}}
@@ -60,9 +51,6 @@ void L(int i, int j) {
6051
static const int Valid1 = 0xff;
6152
static const int Valid2 = 0xffff;
6253
static const int Valid3 = 0xffffffff;
63-
__asm__("xorl %0,%2"
64-
: "=r"(i)
65-
: "0"(i), "L"(j)); // expected-error{{constraint 'L' expects an integer constant expression}}
6654
__asm__("xorl %0,%2"
6755
: "=r"(i)
6856
: "0"(i), "L"(Invalid1)); // expected-error{{value '1' out of range for constraint 'L'}}
@@ -89,9 +77,6 @@ void L(int i, int j) {
8977
void M(int i, int j) {
9078
static const int BelowMin = -1;
9179
static const int AboveMax = 4;
92-
__asm__("xorl %0,%2"
93-
: "=r"(i)
94-
: "0"(i), "M"(j)); // expected-error{{constraint 'M' expects an integer constant expression}}
9580
__asm__("xorl %0,%2"
9681
: "=r"(i)
9782
: "0"(i), "M"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'M'}}
@@ -106,9 +91,6 @@ void M(int i, int j) {
10691
void N(int i, int j) {
10792
static const int BelowMin = -1;
10893
static const int AboveMax = 256;
109-
__asm__("xorl %0,%2"
110-
: "=r"(i)
111-
: "0"(i), "N"(j)); // expected-error{{constraint 'N' expects an integer constant expression}}
11294
__asm__("xorl %0,%2"
11395
: "=r"(i)
11496
: "0"(i), "N"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'N'}}
@@ -123,9 +105,6 @@ void N(int i, int j) {
123105
void O(int i, int j) {
124106
static const int BelowMin = -1;
125107
static const int AboveMax = 128;
126-
__asm__("xorl %0,%2"
127-
: "=r"(i)
128-
: "0"(i), "O"(j)); // expected-error{{constraint 'O' expects an integer constant expression}}
129108
__asm__("xorl %0,%2"
130109
: "=r"(i)
131110
: "0"(i), "O"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'O'}}
@@ -146,10 +125,6 @@ void pr40890(void) {
146125
__asm__ __volatile__("\n#define S_A abcd%0\n" : : "n"(&((struct s*)0)->a));
147126
// This offset-from-null pointer can be used as an integer constant expression.
148127
__asm__ __volatile__("\n#define S_B abcd%0\n" : : "n"(&((struct s*)0)->b));
149-
// This pointer cannot be used as an integer constant expression.
150-
__asm__ __volatile__("\n#define GLOBAL_A abcd%0\n" : : "n"(&s.a)); // expected-error{{constraint 'n' expects an integer constant expression}}
151-
// Floating-point is also not okay.
152-
__asm__ __volatile__("\n#define PI abcd%0\n" : : "n"(3.14f)); // expected-error{{constraint 'n' expects an integer constant expression}}
153128
#ifdef AMD64
154129
// This arbitrary pointer is fine.
155130
__asm__ __volatile__("\n#define BEEF abcd%0\n" : : "n"((int*)0xdeadbeeeeeef));

Diff for: ‎clang/test/Sema/pr41027.c

-10
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.