summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
diff options
context:
space:
mode:
authorThomas Preud'homme <thomas.preudhomme@arm.com>2018-07-25 11:11:12 +0000
committerThomas Preud'homme <thomas.preudhomme@arm.com>2018-07-25 11:11:12 +0000
commit768d6ce4a3af1c32d73e139499300579c27b6b35 (patch)
tree1d62c0671de01ceccbccd3c4b07d292786a5fa46 /llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
parent0913dcd7471bc98672139df38d436a64d10ecfeb (diff)
downloadbcm5719-llvm-768d6ce4a3af1c32d73e139499300579c27b6b35.tar.gz
bcm5719-llvm-768d6ce4a3af1c32d73e139499300579c27b6b35.zip
Fix PR34170: Crash on inline asm with 64bit output in 32bit GPR
Add support for inline assembly with output operand that do not naturally go in the register class it is constrained to (eg. double in a 32-bit GPR as in the PR). llvm-svn: 337903
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp56
1 files changed, 36 insertions, 20 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 1e36ea049b1..b9c7a8f5bc3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7185,27 +7185,37 @@ static void GetRegistersForValue(SelectionDAG &DAG, const TargetLowering &TLI,
unsigned NumRegs = 1;
if (OpInfo.ConstraintVT != MVT::Other) {
- // If this is a FP input in an integer register (or visa versa) insert a bit
- // cast of the input value. More generally, handle any case where the input
- // value disagrees with the register class we plan to stick this in.
- if (OpInfo.Type == InlineAsm::isInput && PhysReg.second &&
+ // If this is a FP operand in an integer register (or visa versa), or more
+ // generally if the operand value disagrees with the register class we plan
+ // to stick it in, fix the operand type.
+ //
+ // If this is an input value, the bitcast to the new type is done now.
+ // Bitcast for output value is done at the end of visitInlineAsm().
+ if ((OpInfo.Type == InlineAsm::isOutput ||
+ OpInfo.Type == InlineAsm::isInput) &&
+ PhysReg.second &&
!TRI.isTypeLegalForClass(*PhysReg.second, OpInfo.ConstraintVT)) {
// Try to convert to the first EVT that the reg class contains. If the
// types are identical size, use a bitcast to convert (e.g. two differing
- // vector types).
+ // vector types). Note: output bitcast is done at the end of
+ // visitInlineAsm().
MVT RegVT = *TRI.legalclasstypes_begin(*PhysReg.second);
- if (RegVT.getSizeInBits() == OpInfo.CallOperand.getValueSizeInBits()) {
- OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, DL,
- RegVT, OpInfo.CallOperand);
+ if (RegVT.getSizeInBits() == OpInfo.ConstraintVT.getSizeInBits()) {
+ // Exclude indirect inputs while they are unsupported because the code
+ // to perform the load is missing and thus OpInfo.CallOperand still
+ // refer to the input address rather than the pointed-to value.
+ if (OpInfo.Type == InlineAsm::isInput && !OpInfo.isIndirect)
+ OpInfo.CallOperand =
+ DAG.getNode(ISD::BITCAST, DL, RegVT, OpInfo.CallOperand);
OpInfo.ConstraintVT = RegVT;
+ // If the operand is a FP value and we want it in integer registers,
+ // use the corresponding integer type. This turns an f64 value into
+ // i64, which can be passed with two i32 values on a 32-bit machine.
} else if (RegVT.isInteger() && OpInfo.ConstraintVT.isFloatingPoint()) {
- // If the input is a FP value and we want it in FP registers, do a
- // bitcast to the corresponding integer type. This turns an f64 value
- // into i64, which can be passed with two i32 values on a 32-bit
- // machine.
RegVT = MVT::getIntegerVT(OpInfo.ConstraintVT.getSizeInBits());
- OpInfo.CallOperand = DAG.getNode(ISD::BITCAST, DL,
- RegVT, OpInfo.CallOperand);
+ if (OpInfo.Type == InlineAsm::isInput)
+ OpInfo.CallOperand =
+ DAG.getNode(ISD::BITCAST, DL, RegVT, OpInfo.CallOperand);
OpInfo.ConstraintVT = RegVT;
}
}
@@ -7717,12 +7727,18 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
if (CS.getType()->isSingleValueType() && CS.getType()->isSized()) {
EVT ResultType = TLI.getValueType(DAG.getDataLayout(), CS.getType());
- // If any of the results of the inline asm is a vector, it may have the
- // wrong width/num elts. This can happen for register classes that can
- // contain multiple different value types. The preg or vreg allocated may
- // not have the same VT as was expected. Convert it to the right type
- // with bit_convert.
- if (ResultType != Val.getValueType() && Val.getValueType().isVector()) {
+ // If the type of the inline asm call site return value is different but
+ // has same size as the type of the asm output bitcast it. One example
+ // of this is for vectors with different width / number of elements.
+ // This can happen for register classes that can contain multiple
+ // different value types. The preg or vreg allocated may not have the
+ // same VT as was expected.
+ //
+ // This can also happen for a return value that disagrees with the
+ // register class it is put in, eg. a double in a general-purpose
+ // register on a 32-bit machine.
+ if (ResultType != Val.getValueType() &&
+ ResultType.getSizeInBits() == Val.getValueSizeInBits()) {
Val = DAG.getNode(ISD::BITCAST, getCurSDLoc(),
ResultType, Val);
OpenPOWER on IntegriCloud