llvm.org GIT mirror llvm / 2456fe5
Merging r367750: ------------------------------------------------------------------------ r367750 | void | 2019-08-03 07:52:47 +0200 (Sat, 03 Aug 2019) | 15 lines Emit diagnostic if an inline asm constraint requires an immediate Summary: An inline asm call can result in an immediate after inlining. Therefore emit a diagnostic here if constraint requires an immediate but one isn't supplied. Reviewers: joerg, mgorny, efriedma, rsmith Reviewed By: joerg Subscribers: asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, s.egerton, MaskRay, jyknight, dylanmckay, javed.absar, fedor.sergeev, jrtc27, Jim, krytarowski, eraman, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60942 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_90@368421 91177308-0d34-0410-b5e6-96231b3b80d8 Hans Wennborg 2 months ago
21 changed file(s) with 117 addition(s) and 40 deletion(s). Raw diff Collapse all Expand all
36643664 C_Register, // Constraint represents specific register(s).
36653665 C_RegisterClass, // Constraint represents any of register(s) in class.
36663666 C_Memory, // Memory constraint.
3667 C_Immediate, // Requires an immediate.
36673668 C_Other, // Something else.
36683669 C_Unknown // Unsupported constraint.
36693670 };
80208020 // Compute the constraint code and ConstraintType to use.
80218021 TLI.ComputeConstraintToUse(T, SDValue());
80228022
8023 if (T.ConstraintType == TargetLowering::C_Immediate &&
8024 OpInfo.CallOperand && !isa(OpInfo.CallOperand))
8025 // We've delayed emitting a diagnostic like the "n" constraint because
8026 // inlining could cause an integer showing up.
8027 return emitInlineAsmError(
8028 CS, "constraint '" + Twine(T.ConstraintCode) + "' expects an "
8029 "integer constant expression");
8030
80238031 ExtraInfo.update(T);
80248032 }
80258033
81048112 switch (OpInfo.Type) {
81058113 case InlineAsm::isOutput:
81068114 if (OpInfo.ConstraintType == TargetLowering::C_Memory ||
8107 (OpInfo.ConstraintType == TargetLowering::C_Other &&
8115 ((OpInfo.ConstraintType == TargetLowering::C_Immediate ||
8116 OpInfo.ConstraintType == TargetLowering::C_Other) &&
81088117 OpInfo.isIndirect)) {
81098118 unsigned ConstraintID =
81108119 TLI.getInlineAsmMemConstraint(OpInfo.ConstraintCode);
81188127 MVT::i32));
81198128 AsmNodeOperands.push_back(OpInfo.CallOperand);
81208129 break;
8121 } else if ((OpInfo.ConstraintType == TargetLowering::C_Other &&
8130 } else if (((OpInfo.ConstraintType == TargetLowering::C_Immediate ||
8131 OpInfo.ConstraintType == TargetLowering::C_Other) &&
81228132 !OpInfo.isIndirect) ||
81238133 OpInfo.ConstraintType == TargetLowering::C_Register ||
81248134 OpInfo.ConstraintType == TargetLowering::C_RegisterClass) {
81258135 // Otherwise, this outputs to a register (directly for C_Register /
8126 // C_RegisterClass, and a target-defined fashion for C_Other). Find a
8127 // register that we can use.
8136 // C_RegisterClass, and a target-defined fashion for
8137 // C_Immediate/C_Other). Find a register that we can use.
81288138 if (OpInfo.AssignedRegs.Regs.empty()) {
81298139 emitInlineAsmError(
81308140 CS, "couldn't allocate output register for constraint '" +
82048214 }
82058215
82068216 // Treat indirect 'X' constraint as memory.
8207 if (OpInfo.ConstraintType == TargetLowering::C_Other &&
8217 if ((OpInfo.ConstraintType == TargetLowering::C_Immediate ||
8218 OpInfo.ConstraintType == TargetLowering::C_Other) &&
82088219 OpInfo.isIndirect)
82098220 OpInfo.ConstraintType = TargetLowering::C_Memory;
82108221
8211 if (OpInfo.ConstraintType == TargetLowering::C_Other) {
8222 if (OpInfo.ConstraintType == TargetLowering::C_Immediate ||
8223 OpInfo.ConstraintType == TargetLowering::C_Other) {
82128224 std::vector Ops;
82138225 TLI.LowerAsmOperandForConstraint(InOperandVal, OpInfo.ConstraintCode,
82148226 Ops, DAG);
82158227 if (Ops.empty()) {
8228 if (OpInfo.ConstraintType == TargetLowering::C_Immediate)
8229 if (isa(InOperandVal)) {
8230 emitInlineAsmError(CS, "value out of range for constraint '" +
8231 Twine(OpInfo.ConstraintCode) + "'");
8232 return;
8233 }
8234
82168235 emitInlineAsmError(CS, "invalid operand for inline asm constraint '" +
82178236 Twine(OpInfo.ConstraintCode) + "'");
82188237 return;
82498268 }
82508269
82518270 assert((OpInfo.ConstraintType == TargetLowering::C_RegisterClass ||
8252 OpInfo.ConstraintType == TargetLowering::C_Register) &&
8271 OpInfo.ConstraintType == TargetLowering::C_Register ||
8272 OpInfo.ConstraintType == TargetLowering::C_Immediate) &&
82538273 "Unknown constraint type!");
82548274
82558275 // TODO: Support this.
83558375 Val = OpInfo.AssignedRegs.getCopyFromRegs(
83568376 DAG, FuncInfo, getCurSDLoc(), Chain, &Flag, CS.getInstruction());
83578377 break;
8378 case TargetLowering::C_Immediate:
83588379 case TargetLowering::C_Other:
83598380 Val = TLI.LowerAsmOutputForConstraint(Chain, Flag, getCurSDLoc(),
83608381 OpInfo, DAG);
35663566 if (S == 1) {
35673567 switch (Constraint[0]) {
35683568 default: break;
3569 case 'r': return C_RegisterClass;
3569 case 'r':
3570 return C_RegisterClass;
35703571 case 'm': // memory
35713572 case 'o': // offsetable
35723573 case 'V': // not offsetable
35733574 return C_Memory;
3574 case 'i': // Simple Integer or Relocatable Constant
35753575 case 'n': // Simple Integer
35763576 case 'E': // Floating Point Constant
35773577 case 'F': // Floating Point Constant
3578 return C_Immediate;
3579 case 'i': // Simple Integer or Relocatable Constant
35783580 case 's': // Relocatable Constant
35793581 case 'p': // Address.
35803582 case 'X': // Allow ANY value.
39493951 /// Return an integer indicating how general CT is.
39503952 static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
39513953 switch (CT) {
3954 case TargetLowering::C_Immediate:
39523955 case TargetLowering::C_Other:
39533956 case TargetLowering::C_Unknown:
39543957 return 0;
40684071 TargetLowering::ConstraintType CType =
40694072 TLI.getConstraintType(OpInfo.Codes[i]);
40704073
4071 // If this is an 'other' constraint, see if the operand is valid for it.
4072 // For example, on X86 we might have an 'rI' constraint. If the operand
4073 // is an integer in the range [0..31] we want to use I (saving a load
4074 // of a register), otherwise we must use 'r'.
4075 if (CType == TargetLowering::C_Other && Op.getNode()) {
4074 // If this is an 'other' or 'immediate' constraint, see if the operand is
4075 // valid for it. For example, on X86 we might have an 'rI' constraint. If
4076 // the operand is an integer in the range [0..31] we want to use I (saving a
4077 // load of a register), otherwise we must use 'r'.
4078 if ((CType == TargetLowering::C_Other ||
4079 CType == TargetLowering::C_Immediate) && Op.getNode()) {
40764080 assert(OpInfo.Codes[i].size() == 1 &&
40774081 "Unhandled multi-letter 'other' constraint");
40784082 std::vector ResultOps;
56645664 switch (Constraint[0]) {
56655665 default:
56665666 break;
5667 case 'z':
5668 return C_Other;
56695667 case 'x':
56705668 case 'w':
56715669 return C_RegisterClass;
56735671 // currently handle addresses it is the same as 'r'.
56745672 case 'Q':
56755673 return C_Memory;
5674 case 'I':
5675 case 'J':
5676 case 'K':
5677 case 'L':
5678 case 'M':
5679 case 'N':
5680 case 'Y':
5681 case 'Z':
5682 return C_Immediate;
5683 case 'z':
56765684 case 'S': // A symbolic address
56775685 return C_Other;
56785686 }
1436814368 /// constraint it is for this target.
1436914369 ARMTargetLowering::ConstraintType
1437014370 ARMTargetLowering::getConstraintType(StringRef Constraint) const {
14371 if (Constraint.size() == 1) {
14371 unsigned S = Constraint.size();
14372 if (S == 1) {
1437214373 switch (Constraint[0]) {
1437314374 default: break;
1437414375 case 'l': return C_RegisterClass;
1437614377 case 'h': return C_RegisterClass;
1437714378 case 'x': return C_RegisterClass;
1437814379 case 't': return C_RegisterClass;
14379 case 'j': return C_Other; // Constant for movw.
14380 // An address with a single base register. Due to the way we
14381 // currently handle addresses it is the same as an 'r' memory constraint.
14380 case 'j': return C_Immediate; // Constant for movw.
14381 // An address with a single base register. Due to the way we
14382 // currently handle addresses it is the same as an 'r' memory constraint.
1438214383 case 'Q': return C_Memory;
1438314384 }
14384 } else if (Constraint.size() == 2) {
14385 } else if (S == 2) {
1438514386 switch (Constraint[0]) {
1438614387 default: break;
1438714388 case 'T': return C_RegisterClass;
16881688 if (Constraint.size() == 1) {
16891689 // See http://www.nongnu.org/avr-libc/user-manual/inline_asm.html
16901690 switch (Constraint[0]) {
1691 default:
1692 break;
16911693 case 'a': // Simple upper registers
16921694 case 'b': // Base pointer registers pairs
16931695 case 'd': // Upper register
17141716 case 'O': // Integer constant (Range: 8, 16, 24)
17151717 case 'P': // Integer constant (Range: 1)
17161718 case 'R': // Integer constant (Range: -6 to 5)x
1717 return C_Other;
1718 default:
1719 break;
1719 return C_Immediate;
17201720 }
17211721 }
17221722
24062406 break;
24072407 case 'f':
24082408 return C_RegisterClass;
2409 case 'I':
2410 case 'J':
2411 case 'K':
2412 return C_Immediate;
24092413 }
24102414 }
24112415 return TargetLowering::getConstraintType(Constraint);
31823182 case 'e':
31833183 return C_RegisterClass;
31843184 case 'I': // SIMM13
3185 return C_Other;
3185 return C_Immediate;
31863186 }
31873187 }
31883188
955955 case 'K': // Signed 16-bit constant
956956 case 'L': // Signed 20-bit displacement (on all targets we support)
957957 case 'M': // 0x7fffffff
958 return C_Other;
958 return C_Immediate;
959959
960960 default:
961961 break;
4465544655 case 'I':
4465644656 case 'J':
4465744657 case 'K':
44658 case 'N':
44659 case 'G':
4465844660 case 'L':
4465944661 case 'M':
44660 case 'N':
44661 case 'G':
44662 return C_Immediate;
4466244663 case 'C':
4466344664 case 'e':
4466444665 case 'Z':
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
4 ; CHECK-ERRORS: error: invalid operand for inline asm constraint 'I'
4 ; CHECK-ERRORS: error: value out of range for constraint 'I'
55
66 define i32 @constraint_I(i32 %i, i32 %j) nounwind ssp {
77 entry:
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
4 ; CHECK-ERRORS: error: invalid operand for inline asm constraint 'J'
4 ; CHECK-ERRORS: error: value out of range for constraint 'J'
55
66 define i32 @constraint_J(i32 %i, i32 %j) nounwind ssp {
77 entry:
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
4 ; CHECK-ERRORS: error: invalid operand for inline asm constraint 'K'
4 ; CHECK-ERRORS: error: value out of range for constraint 'K'
55
66 define i32 @constraint_K(i32 %i, i32 %j) nounwind {
77 entry:
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
4 ; CHECK-ERRORS: error: invalid operand for inline asm constraint 'L'
4 ; CHECK-ERRORS: error: value out of range for constraint 'L'
55
66 define i32 @constraint_L(i32 %i, i32 %j) nounwind {
77 entry:
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
4 ; CHECK-ERRORS: error: invalid operand for inline asm constraint 'M'
4 ; CHECK-ERRORS: error: value out of range for constraint 'M'
55
66 define i32 @constraint_M(i32 %i, i32 %j) nounwind {
77 entry:
11 ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
22
33 ; Check for at least one invalid constant.
4 ; CHECK-ERRORS: error: invalid operand for inline asm constraint 'N'
4 ; CHECK-ERRORS: error: value out of range for constraint 'N'
55
66 define i32 @constraint_N(i32 %i, i32 %j) nounwind {
77 entry:
11 ; RUN: not llc -mtriple=riscv64 < %s 2>&1 | FileCheck %s
22
33 define void @constraint_I() {
4 ; CHECK: error: invalid operand for inline asm constraint 'I'
4 ; CHECK: error: value out of range for constraint 'I'
55 tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 2048)
6 ; CHECK: error: invalid operand for inline asm constraint 'I'
6 ; CHECK: error: value out of range for constraint 'I'
77 tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 -2049)
88 ret void
99 }
1010
1111 define void @constraint_J() {
12 ; CHECK: error: invalid operand for inline asm constraint 'J'
12 ; CHECK: error: value out of range for constraint 'J'
1313 tail call void asm sideeffect "addi a0, a0, $0", "J"(i32 1)
1414 ret void
1515 }
1616
1717 define void @constraint_K() {
18 ; CHECK: error: invalid operand for inline asm constraint 'K'
18 ; CHECK: error: value out of range for constraint 'K'
1919 tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 32)
20 ; CHECK: error: invalid operand for inline asm constraint 'K'
20 ; CHECK: error: value out of range for constraint 'K'
2121 tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 -1)
2222 ret void
2323 }
11
22 @x = global i32 0, align 4
33
4 ;CHECK: error: invalid operand for inline asm constraint 'n'
4 ; CHECK: error: constraint 'n' expects an integer constant expression
55 define void @foo() {
66 %a = getelementptr i32, i32* @x, i32 1
77 call void asm sideeffect "foo $0", "n"(i32* %a) nounwind
0 ; RUN: not llc -mtriple=x86_64-unknown-unknown -no-integrated-as < %s 2>&1 | FileCheck %s
1
2 %struct.s = type { i32, i32 }
3
4 @pr40890.s = internal global %struct.s zeroinitializer, align 4
5
6 ; CHECK: error: invalid operand for inline asm constraint 'e'
7 ; CHECK: error: invalid operand for inline asm constraint 'e'
8
9 define void @pr40890() {
10 entry:
11 ; This pointer cannot be used as an integer constant expression.
12 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))
13 ; Floating-point is also not okay.
14 tail call void asm sideeffect "\0A#define PI abcd$0\0A", "e,~{dirflag},~{fpsr},~{flags}"(float 0x40091EB860000000)
15 ret void
16 }
0 ; RUN: not llc -mtriple=i686-- -no-integrated-as < %s 2>&1 | FileCheck %s
1
2 ; CHECK: error: value out of range for constraint 'I'
3 define void @foo() {
4 call void asm sideeffect "foo $0", "I"(i32 42)
5 ret void
6 }
0 ; RUN: llc -mtriple=x86_64-unknown-unknown -no-integrated-as < %s 2>&1 | FileCheck %s
1
2 @x = global i32 0, align 4
3
4 define void @foo() {
5 ; CHECK-LABEL: foo:
6 call void asm sideeffect "foo $0", "n"(i32 42) nounwind
7 ; CHECK: #APP
8 ; CHECK-NEXT: foo $42
9 ; CHECK-NEXT: #NO_APP
10 ret void
11 ; CHECK-NEXT: retq
12 }