summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/CodeGen/TargetLowering.h1
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp35
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp18
-rw-r--r--llvm/lib/Target/AArch64/AArch64ISelLowering.cpp12
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp11
-rw-r--r--llvm/lib/Target/AVR/AVRISelLowering.cpp6
-rw-r--r--llvm/lib/Target/RISCV/RISCVISelLowering.cpp4
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.cpp2
-rw-r--r--llvm/lib/Target/SystemZ/SystemZISelLowering.cpp2
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp5
-rw-r--r--llvm/test/CodeGen/AArch64/arm64-inline-asm-error-I.ll2
-rw-r--r--llvm/test/CodeGen/AArch64/arm64-inline-asm-error-J.ll2
-rw-r--r--llvm/test/CodeGen/AArch64/arm64-inline-asm-error-K.ll2
-rw-r--r--llvm/test/CodeGen/AArch64/arm64-inline-asm-error-L.ll2
-rw-r--r--llvm/test/CodeGen/AArch64/arm64-inline-asm-error-M.ll2
-rw-r--r--llvm/test/CodeGen/AArch64/arm64-inline-asm-error-N.ll2
-rw-r--r--llvm/test/CodeGen/RISCV/inline-asm-invalid.ll10
-rw-r--r--llvm/test/CodeGen/X86/inline-asm-bad-constraint-n.ll2
-rw-r--r--llvm/test/CodeGen/X86/inline-asm-e-constraint.ll17
-rw-r--r--llvm/test/CodeGen/X86/inline-asm-imm-out-of-range.ll7
-rw-r--r--llvm/test/CodeGen/X86/inline-asm-n-constraint.ll13
21 files changed, 117 insertions, 40 deletions
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 3d6f4700255..30a251efb88 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -3742,6 +3742,7 @@ public:
C_Register, // Constraint represents specific register(s).
C_RegisterClass, // Constraint represents any of register(s) in class.
C_Memory, // Memory constraint.
+ C_Immediate, // Requires an immediate.
C_Other, // Something else.
C_Unknown // Unsupported constraint.
};
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 0b292b234fc..90494f2c612 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -8049,6 +8049,14 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
// Compute the constraint code and ConstraintType to use.
TLI.ComputeConstraintToUse(T, SDValue());
+ if (T.ConstraintType == TargetLowering::C_Immediate &&
+ OpInfo.CallOperand && !isa<ConstantSDNode>(OpInfo.CallOperand))
+ // We've delayed emitting a diagnostic like the "n" constraint because
+ // inlining could cause an integer showing up.
+ return emitInlineAsmError(
+ CS, "constraint '" + Twine(T.ConstraintCode) + "' expects an "
+ "integer constant expression");
+
ExtraInfo.update(T);
}
@@ -8133,7 +8141,8 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
switch (OpInfo.Type) {
case InlineAsm::isOutput:
if (OpInfo.ConstraintType == TargetLowering::C_Memory ||
- (OpInfo.ConstraintType == TargetLowering::C_Other &&
+ ((OpInfo.ConstraintType == TargetLowering::C_Immediate ||
+ OpInfo.ConstraintType == TargetLowering::C_Other) &&
OpInfo.isIndirect)) {
unsigned ConstraintID =
TLI.getInlineAsmMemConstraint(OpInfo.ConstraintCode);
@@ -8147,13 +8156,14 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
MVT::i32));
AsmNodeOperands.push_back(OpInfo.CallOperand);
break;
- } else if ((OpInfo.ConstraintType == TargetLowering::C_Other &&
+ } else if (((OpInfo.ConstraintType == TargetLowering::C_Immediate ||
+ OpInfo.ConstraintType == TargetLowering::C_Other) &&
!OpInfo.isIndirect) ||
OpInfo.ConstraintType == TargetLowering::C_Register ||
OpInfo.ConstraintType == TargetLowering::C_RegisterClass) {
// Otherwise, this outputs to a register (directly for C_Register /
- // C_RegisterClass, and a target-defined fashion for C_Other). Find a
- // register that we can use.
+ // C_RegisterClass, and a target-defined fashion for
+ // C_Immediate/C_Other). Find a register that we can use.
if (OpInfo.AssignedRegs.Regs.empty()) {
emitInlineAsmError(
CS, "couldn't allocate output register for constraint '" +
@@ -8233,15 +8243,24 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
}
// Treat indirect 'X' constraint as memory.
- if (OpInfo.ConstraintType == TargetLowering::C_Other &&
+ if ((OpInfo.ConstraintType == TargetLowering::C_Immediate ||
+ OpInfo.ConstraintType == TargetLowering::C_Other) &&
OpInfo.isIndirect)
OpInfo.ConstraintType = TargetLowering::C_Memory;
- if (OpInfo.ConstraintType == TargetLowering::C_Other) {
+ if (OpInfo.ConstraintType == TargetLowering::C_Immediate ||
+ OpInfo.ConstraintType == TargetLowering::C_Other) {
std::vector<SDValue> Ops;
TLI.LowerAsmOperandForConstraint(InOperandVal, OpInfo.ConstraintCode,
Ops, DAG);
if (Ops.empty()) {
+ if (OpInfo.ConstraintType == TargetLowering::C_Immediate)
+ if (isa<ConstantSDNode>(InOperandVal)) {
+ emitInlineAsmError(CS, "value out of range for constraint '" +
+ Twine(OpInfo.ConstraintCode) + "'");
+ return;
+ }
+
emitInlineAsmError(CS, "invalid operand for inline asm constraint '" +
Twine(OpInfo.ConstraintCode) + "'");
return;
@@ -8278,7 +8297,8 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
}
assert((OpInfo.ConstraintType == TargetLowering::C_RegisterClass ||
- OpInfo.ConstraintType == TargetLowering::C_Register) &&
+ OpInfo.ConstraintType == TargetLowering::C_Register ||
+ OpInfo.ConstraintType == TargetLowering::C_Immediate) &&
"Unknown constraint type!");
// TODO: Support this.
@@ -8384,6 +8404,7 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
Val = OpInfo.AssignedRegs.getCopyFromRegs(
DAG, FuncInfo, getCurSDLoc(), Chain, &Flag, CS.getInstruction());
break;
+ case TargetLowering::C_Immediate:
case TargetLowering::C_Other:
Val = TLI.LowerAsmOutputForConstraint(Chain, Flag, getCurSDLoc(),
OpInfo, DAG);
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index dd819eb7e2d..477a138dcbc 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -3873,15 +3873,17 @@ TargetLowering::getConstraintType(StringRef Constraint) const {
if (S == 1) {
switch (Constraint[0]) {
default: break;
- case 'r': return C_RegisterClass;
+ case 'r':
+ return C_RegisterClass;
case 'm': // memory
case 'o': // offsetable
case 'V': // not offsetable
return C_Memory;
- case 'i': // Simple Integer or Relocatable Constant
case 'n': // Simple Integer
case 'E': // Floating Point Constant
case 'F': // Floating Point Constant
+ return C_Immediate;
+ case 'i': // Simple Integer or Relocatable Constant
case 's': // Relocatable Constant
case 'p': // Address.
case 'X': // Allow ANY value.
@@ -4256,6 +4258,7 @@ TargetLowering::ParseConstraints(const DataLayout &DL,
/// Return an integer indicating how general CT is.
static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
switch (CT) {
+ case TargetLowering::C_Immediate:
case TargetLowering::C_Other:
case TargetLowering::C_Unknown:
return 0;
@@ -4375,11 +4378,12 @@ static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo,
TargetLowering::ConstraintType CType =
TLI.getConstraintType(OpInfo.Codes[i]);
- // If this is an 'other' constraint, see if the operand is valid for it.
- // For example, on X86 we might have an 'rI' constraint. If the operand
- // is an integer in the range [0..31] we want to use I (saving a load
- // of a register), otherwise we must use 'r'.
- if (CType == TargetLowering::C_Other && Op.getNode()) {
+ // If this is an 'other' or 'immediate' constraint, see if the operand is
+ // valid for it. For example, on X86 we might have an 'rI' constraint. If
+ // the operand is an integer in the range [0..31] we want to use I (saving a
+ // load of a register), otherwise we must use 'r'.
+ if ((CType == TargetLowering::C_Other ||
+ CType == TargetLowering::C_Immediate) && Op.getNode()) {
assert(OpInfo.Codes[i].size() == 1 &&
"Unhandled multi-letter 'other' constraint");
std::vector<SDValue> ResultOps;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 43a7e4f71dc..658cc5b6b2e 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -5686,8 +5686,6 @@ AArch64TargetLowering::getConstraintType(StringRef Constraint) const {
switch (Constraint[0]) {
default:
break;
- case 'z':
- return C_Other;
case 'x':
case 'w':
return C_RegisterClass;
@@ -5695,6 +5693,16 @@ AArch64TargetLowering::getConstraintType(StringRef Constraint) const {
// currently handle addresses it is the same as 'r'.
case 'Q':
return C_Memory;
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'Y':
+ case 'Z':
+ return C_Immediate;
+ case 'z':
case 'S': // A symbolic address
return C_Other;
}
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index c0232f01c3e..cce57a4d55f 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -14976,7 +14976,8 @@ const char *ARMTargetLowering::LowerXConstraint(EVT ConstraintVT) const {
/// constraint it is for this target.
ARMTargetLowering::ConstraintType
ARMTargetLowering::getConstraintType(StringRef Constraint) const {
- if (Constraint.size() == 1) {
+ unsigned S = Constraint.size();
+ if (S == 1) {
switch (Constraint[0]) {
default: break;
case 'l': return C_RegisterClass;
@@ -14984,12 +14985,12 @@ ARMTargetLowering::getConstraintType(StringRef Constraint) const {
case 'h': return C_RegisterClass;
case 'x': return C_RegisterClass;
case 't': return C_RegisterClass;
- case 'j': return C_Other; // Constant for movw.
- // An address with a single base register. Due to the way we
- // currently handle addresses it is the same as an 'r' memory constraint.
+ case 'j': return C_Immediate; // Constant for movw.
+ // An address with a single base register. Due to the way we
+ // currently handle addresses it is the same as an 'r' memory constraint.
case 'Q': return C_Memory;
}
- } else if (Constraint.size() == 2) {
+ } else if (S == 2) {
switch (Constraint[0]) {
default: break;
case 'T': return C_RegisterClass;
diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp
index b6ba5f22faf..f159beee973 100644
--- a/llvm/lib/Target/AVR/AVRISelLowering.cpp
+++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp
@@ -1689,6 +1689,8 @@ AVRTargetLowering::getConstraintType(StringRef Constraint) const {
if (Constraint.size() == 1) {
// See http://www.nongnu.org/avr-libc/user-manual/inline_asm.html
switch (Constraint[0]) {
+ default:
+ break;
case 'a': // Simple upper registers
case 'b': // Base pointer registers pairs
case 'd': // Upper register
@@ -1715,9 +1717,7 @@ AVRTargetLowering::getConstraintType(StringRef Constraint) const {
case 'O': // Integer constant (Range: 8, 16, 24)
case 'P': // Integer constant (Range: 1)
case 'R': // Integer constant (Range: -6 to 5)x
- return C_Other;
- default:
- break;
+ return C_Immediate;
}
}
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 62c6ba87738..dfedbba8968 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -2407,6 +2407,10 @@ RISCVTargetLowering::getConstraintType(StringRef Constraint) const {
break;
case 'f':
return C_RegisterClass;
+ case 'I':
+ case 'J':
+ case 'K':
+ return C_Immediate;
}
}
return TargetLowering::getConstraintType(Constraint);
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index a6d440fa8aa..804f7ba74ed 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -3183,7 +3183,7 @@ SparcTargetLowering::getConstraintType(StringRef Constraint) const {
case 'e':
return C_RegisterClass;
case 'I': // SIMM13
- return C_Other;
+ return C_Immediate;
}
}
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 78820f511ab..e7b7a5b0cd5 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -956,7 +956,7 @@ SystemZTargetLowering::getConstraintType(StringRef Constraint) const {
case 'K': // Signed 16-bit constant
case 'L': // Signed 20-bit displacement (on all targets we support)
case 'M': // 0x7fffffff
- return C_Other;
+ return C_Immediate;
default:
break;
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 8147168d5ec..ee25603a72f 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -44875,10 +44875,11 @@ X86TargetLowering::getConstraintType(StringRef Constraint) const {
case 'I':
case 'J':
case 'K':
- case 'L':
- case 'M':
case 'N':
case 'G':
+ case 'L':
+ case 'M':
+ return C_Immediate;
case 'C':
case 'e':
case 'Z':
diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-I.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-I.ll
index 7dc9f726003..7784c9b2442 100644
--- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-I.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-I.ll
@@ -2,7 +2,7 @@
; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
; Check for at least one invalid constant.
-; CHECK-ERRORS: error: invalid operand for inline asm constraint 'I'
+; CHECK-ERRORS: error: value out of range for constraint 'I'
define i32 @constraint_I(i32 %i, i32 %j) nounwind ssp {
entry:
diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-J.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-J.ll
index 592875b0cb0..c90178513d2 100644
--- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-J.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-J.ll
@@ -2,7 +2,7 @@
; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
; Check for at least one invalid constant.
-; CHECK-ERRORS: error: invalid operand for inline asm constraint 'J'
+; CHECK-ERRORS: error: value out of range for constraint 'J'
define i32 @constraint_J(i32 %i, i32 %j) nounwind ssp {
entry:
diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-K.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-K.ll
index 893e8d29e65..e5baf85e954 100644
--- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-K.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-K.ll
@@ -2,7 +2,7 @@
; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
; Check for at least one invalid constant.
-; CHECK-ERRORS: error: invalid operand for inline asm constraint 'K'
+; CHECK-ERRORS: error: value out of range for constraint 'K'
define i32 @constraint_K(i32 %i, i32 %j) nounwind {
entry:
diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-L.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-L.ll
index b2fb822aa29..cdba0562755 100644
--- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-L.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-L.ll
@@ -2,7 +2,7 @@
; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
; Check for at least one invalid constant.
-; CHECK-ERRORS: error: invalid operand for inline asm constraint 'L'
+; CHECK-ERRORS: error: value out of range for constraint 'L'
define i32 @constraint_L(i32 %i, i32 %j) nounwind {
entry:
diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-M.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-M.ll
index aaee933fd6d..c7a786b26bb 100644
--- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-M.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-M.ll
@@ -2,7 +2,7 @@
; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
; Check for at least one invalid constant.
-; CHECK-ERRORS: error: invalid operand for inline asm constraint 'M'
+; CHECK-ERRORS: error: value out of range for constraint 'M'
define i32 @constraint_M(i32 %i, i32 %j) nounwind {
entry:
diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-N.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-N.ll
index d1d2e03548e..38b0ab8fa29 100644
--- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-N.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-N.ll
@@ -2,7 +2,7 @@
; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
; Check for at least one invalid constant.
-; CHECK-ERRORS: error: invalid operand for inline asm constraint 'N'
+; CHECK-ERRORS: error: value out of range for constraint 'N'
define i32 @constraint_N(i32 %i, i32 %j) nounwind {
entry:
diff --git a/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll b/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll
index 06b0f2c2bfe..20ac5ef1111 100644
--- a/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll
+++ b/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll
@@ -2,23 +2,23 @@
; RUN: not llc -mtriple=riscv64 < %s 2>&1 | FileCheck %s
define void @constraint_I() {
-; CHECK: error: invalid operand for inline asm constraint 'I'
+; CHECK: error: value out of range for constraint 'I'
tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 2048)
-; CHECK: error: invalid operand for inline asm constraint 'I'
+; CHECK: error: value out of range for constraint 'I'
tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 -2049)
ret void
}
define void @constraint_J() {
-; CHECK: error: invalid operand for inline asm constraint 'J'
+; CHECK: error: value out of range for constraint 'J'
tail call void asm sideeffect "addi a0, a0, $0", "J"(i32 1)
ret void
}
define void @constraint_K() {
-; CHECK: error: invalid operand for inline asm constraint 'K'
+; CHECK: error: value out of range for constraint 'K'
tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 32)
-; CHECK: error: invalid operand for inline asm constraint 'K'
+; CHECK: error: value out of range for constraint 'K'
tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 -1)
ret void
}
diff --git a/llvm/test/CodeGen/X86/inline-asm-bad-constraint-n.ll b/llvm/test/CodeGen/X86/inline-asm-bad-constraint-n.ll
index 967477d076d..a3099ab3679 100644
--- a/llvm/test/CodeGen/X86/inline-asm-bad-constraint-n.ll
+++ b/llvm/test/CodeGen/X86/inline-asm-bad-constraint-n.ll
@@ -2,7 +2,7 @@
@x = global i32 0, align 4
-;CHECK: error: invalid operand for inline asm constraint 'n'
+; CHECK: error: constraint 'n' expects an integer constant expression
define void @foo() {
%a = getelementptr i32, i32* @x, i32 1
call void asm sideeffect "foo $0", "n"(i32* %a) nounwind
diff --git a/llvm/test/CodeGen/X86/inline-asm-e-constraint.ll b/llvm/test/CodeGen/X86/inline-asm-e-constraint.ll
new file mode 100644
index 00000000000..fd10ba42408
--- /dev/null
+++ b/llvm/test/CodeGen/X86/inline-asm-e-constraint.ll
@@ -0,0 +1,17 @@
+; RUN: not llc -mtriple=x86_64-unknown-unknown -no-integrated-as < %s 2>&1 | FileCheck %s
+
+%struct.s = type { i32, i32 }
+
+@pr40890.s = internal global %struct.s zeroinitializer, align 4
+
+; CHECK: error: invalid operand for inline asm constraint 'e'
+; CHECK: error: invalid operand for inline asm constraint 'e'
+
+define void @pr40890() {
+entry:
+ ; This pointer cannot be used as an integer constant expression.
+ tail call void asm sideeffect "\0A#define GLOBAL_A abcd$0\0A", "e,~{dirflag},~{fpsr},~{flags}"(i32* getelementptr inbounds (%struct.s, %struct.s* @pr40890.s, i64 0, i32 0))
+ ; Floating-point is also not okay.
+ tail call void asm sideeffect "\0A#define PI abcd$0\0A", "e,~{dirflag},~{fpsr},~{flags}"(float 0x40091EB860000000)
+ ret void
+}
diff --git a/llvm/test/CodeGen/X86/inline-asm-imm-out-of-range.ll b/llvm/test/CodeGen/X86/inline-asm-imm-out-of-range.ll
new file mode 100644
index 00000000000..9c5177d02a1
--- /dev/null
+++ b/llvm/test/CodeGen/X86/inline-asm-imm-out-of-range.ll
@@ -0,0 +1,7 @@
+; RUN: not llc -mtriple=i686-- -no-integrated-as < %s 2>&1 | FileCheck %s
+
+; CHECK: error: value out of range for constraint 'I'
+define void @foo() {
+ call void asm sideeffect "foo $0", "I"(i32 42)
+ ret void
+}
diff --git a/llvm/test/CodeGen/X86/inline-asm-n-constraint.ll b/llvm/test/CodeGen/X86/inline-asm-n-constraint.ll
new file mode 100644
index 00000000000..669e464f1f6
--- /dev/null
+++ b/llvm/test/CodeGen/X86/inline-asm-n-constraint.ll
@@ -0,0 +1,13 @@
+; RUN: llc -mtriple=x86_64-unknown-unknown -no-integrated-as < %s 2>&1 | FileCheck %s
+
+@x = global i32 0, align 4
+
+define void @foo() {
+; CHECK-LABEL: foo:
+ call void asm sideeffect "foo $0", "n"(i32 42) nounwind
+; CHECK: #APP
+; CHECK-NEXT: foo $42
+; CHECK-NEXT: #NO_APP
+ ret void
+; CHECK-NEXT: retq
+}
OpenPOWER on IntegriCloud