[llvm] b484fa8 - [X86] Fix crash with inline asm using wrong register name
Phoebe Wang via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 15 18:38:21 PST 2021
Author: Fabian Wolff
Date: 2021-11-16T10:38:12+08:00
New Revision: b484fa8289299a4a55708d8e4104aacfea8d7fd5
URL: https://github.com/llvm/llvm-project/commit/b484fa8289299a4a55708d8e4104aacfea8d7fd5
DIFF: https://github.com/llvm/llvm-project/commit/b484fa8289299a4a55708d8e4104aacfea8d7fd5.diff
LOG: [X86] Fix crash with inline asm using wrong register name
Fixes PR#48678. `X86TargetLowering::getRegForInlineAsmConstraint()` can adjust the register class to match the type, e.g. change `VR128X` to `VR256X` if the type needs 256 bits. However, the function currently returns the unadjusted register and the adjusted register class, e.g. `xmm15` and `VR256X`, which then causes an assertion failure later because the register class does not contain that register. This patch fixes this behavior.
Reviewed By: pengfei
Differential Revision: https://reviews.llvm.org/D113834
Added:
llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch-avx.ll
Modified:
llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 6408bff539ca..5d911c165293 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -8392,9 +8392,10 @@ static SDValue getAddressForMemoryInput(SDValue Chain, const SDLoc &Location,
///
/// OpInfo describes the operand
/// RefOpInfo describes the matching operand if any, the operand otherwise
-static void GetRegistersForValue(SelectionDAG &DAG, const SDLoc &DL,
- SDISelAsmOperandInfo &OpInfo,
- SDISelAsmOperandInfo &RefOpInfo) {
+static llvm::Optional<unsigned>
+getRegistersForValue(SelectionDAG &DAG, const SDLoc &DL,
+ SDISelAsmOperandInfo &OpInfo,
+ SDISelAsmOperandInfo &RefOpInfo) {
LLVMContext &Context = *DAG.getContext();
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
@@ -8404,7 +8405,7 @@ static void GetRegistersForValue(SelectionDAG &DAG, const SDLoc &DL,
// No work to do for memory operations.
if (OpInfo.ConstraintType == TargetLowering::C_Memory)
- return;
+ return None;
// If this is a constraint for a single physreg, or a constraint for a
// register class, find it.
@@ -8414,7 +8415,7 @@ static void GetRegistersForValue(SelectionDAG &DAG, const SDLoc &DL,
&TRI, RefOpInfo.ConstraintCode, RefOpInfo.ConstraintVT);
// RC is unset only on failure. Return immediately.
if (!RC)
- return;
+ return None;
// Get the actual register value type. This is important, because the user
// may have asked for (e.g.) the AX register in i32 type. We need to
@@ -8459,7 +8460,7 @@ static void GetRegistersForValue(SelectionDAG &DAG, const SDLoc &DL,
// No need to allocate a matching input constraint since the constraint it's
// matching to has already been allocated.
if (OpInfo.isMatchingInputConstraint())
- return;
+ return None;
EVT ValueVT = OpInfo.ConstraintVT;
if (OpInfo.ConstraintVT == MVT::Other)
@@ -8482,8 +8483,12 @@ static void GetRegistersForValue(SelectionDAG &DAG, const SDLoc &DL,
// Do not check for single registers.
if (AssignedReg) {
- for (; *I != AssignedReg; ++I)
- assert(I != RC->end() && "AssignedReg should be member of RC");
+ I = std::find(I, RC->end(), AssignedReg);
+ if (I == RC->end()) {
+ // RC does not contain the selected register, which indicates a
+ // mismatch between the register and the required type/bitwidth.
+ return {AssignedReg};
+ }
}
for (; NumRegs; --NumRegs, ++I) {
@@ -8493,6 +8498,7 @@ static void GetRegistersForValue(SelectionDAG &DAG, const SDLoc &DL,
}
OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT);
+ return None;
}
static unsigned
@@ -8726,7 +8732,18 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
OpInfo.isMatchingInputConstraint()
? ConstraintOperands[OpInfo.getMatchedOperand()]
: OpInfo;
- GetRegistersForValue(DAG, getCurSDLoc(), OpInfo, RefOpInfo);
+ const auto RegError =
+ getRegistersForValue(DAG, getCurSDLoc(), OpInfo, RefOpInfo);
+ if (RegError.hasValue()) {
+ const MachineFunction &MF = DAG.getMachineFunction();
+ const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
+ const char *RegName = TRI.getName(RegError.getValue());
+ emitInlineAsmError(Call, "register '" + Twine(RegName) +
+ "' allocated for constraint '" +
+ Twine(OpInfo.ConstraintCode) +
+ "' does not match required type");
+ return;
+ }
auto DetectWriteToReservedRegister = [&]() {
const MachineFunction &MF = DAG.getMachineFunction();
diff --git a/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch-avx.ll b/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch-avx.ll
new file mode 100644
index 000000000000..887de29e7e67
--- /dev/null
+++ b/llvm/test/CodeGen/X86/asm-reject-reg-type-mismatch-avx.ll
@@ -0,0 +1,9 @@
+; RUN: not llc -o /dev/null -mattr=avx %s 2>&1 | FileCheck %s
+target triple = "x86_64--"
+
+; CHECK: error: register 'XMM15' allocated for constraint '{xmm15}' does not match required type
+define void @test1() nounwind {
+entry:
+ tail call void asm sideeffect "call dummy", "{xmm15},~{dirflag},~{fpsr},~{flags}"(<8 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8>) #1
+ ret void
+}
More information about the llvm-commits
mailing list