aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2007-12-17 18:08:19 +0000
committerDuncan Sands <baldrick@free.fr>2007-12-17 18:08:19 +0000
commitfd7b326bea39c077eea8d378156bcf09051cc4ec (patch)
tree7eb74d7e82001116dae6ed86f61dd713c088a94f
parent9dfb11d32d302abfe8803d530138b38ddc567c60 (diff)
Make invokes of inline asm legal. Teach codegen
how to lower them (with no attempt made to be efficient, since they should only occur for unoptimized code). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45108 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp37
-rw-r--r--lib/Transforms/Utils/InlineFunction.cpp5
-rw-r--r--lib/VMCore/Verifier.cpp2
-rw-r--r--test/CodeGen/Generic/2007-12-17-InvokeAsm.ll15
-rw-r--r--test/Transforms/Inline/2007-04-15-InlineEH.ll2
5 files changed, 39 insertions, 22 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index ed89878a0d..bc336d2069 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -597,7 +597,7 @@ public:
void visitStore(StoreInst &I);
void visitPHI(PHINode &I) { } // PHI nodes are handled specially.
void visitCall(CallInst &I);
- void visitInlineAsm(CallInst &I);
+ void visitInlineAsm(CallSite CS);
const char *visitIntrinsicCall(CallInst &I, unsigned Intrinsic);
void visitTargetIntrinsic(CallInst &I, unsigned Intrinsic);
@@ -1449,11 +1449,14 @@ void SelectionDAGLowering::visitInvoke(InvokeInst &I) {
MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
MachineBasicBlock *LandingPad = FuncInfo.MBBMap[I.getSuccessor(1)];
- LowerCallTo(I, I.getCalledValue()->getType(), I.getParamAttrs(),
- I.getCallingConv(),
- false,
- getValue(I.getOperand(0)),
- 3, LandingPad);
+ if (isa<InlineAsm>(I.getCalledValue()))
+ visitInlineAsm(&I);
+ else
+ LowerCallTo(I, I.getCalledValue()->getType(), I.getParamAttrs(),
+ I.getCallingConv(),
+ false,
+ getValue(I.getOperand(0)),
+ 3, LandingPad);
// If the value of the invoke is used outside of its defining block, make it
// available as a virtual register.
@@ -3044,7 +3047,7 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
}
}
} else if (isa<InlineAsm>(I.getOperand(0))) {
- visitInlineAsm(I);
+ visitInlineAsm(&I);
return;
}
@@ -3425,8 +3428,8 @@ GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber,
/// visitInlineAsm - Handle a call to an InlineAsm object.
///
-void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
- InlineAsm *IA = cast<InlineAsm>(I.getOperand(0));
+void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
+ InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue());
/// ConstraintOperands - Information about all of the constraints.
std::vector<AsmOperandInfo> ConstraintOperands;
@@ -3446,7 +3449,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
// registers, because it will not know to avoid the earlyclobbered output reg.
bool SawEarlyClobber = false;
- unsigned OpNo = 1; // OpNo - The operand of the CallInst.
+ unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
ConstraintOperands.push_back(AsmOperandInfo(ConstraintInfos[i]));
AsmOperandInfo &OpInfo = ConstraintOperands.back();
@@ -3459,14 +3462,14 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
if (!OpInfo.isIndirect) {
// The return value of the call is this value. As such, there is no
// corresponding argument.
- assert(I.getType() != Type::VoidTy && "Bad inline asm!");
- OpVT = TLI.getValueType(I.getType());
+ assert(CS.getType() != Type::VoidTy && "Bad inline asm!");
+ OpVT = TLI.getValueType(CS.getType());
} else {
- OpInfo.CallOperandVal = I.getOperand(OpNo++);
+ OpInfo.CallOperandVal = CS.getArgument(ArgNo++);
}
break;
case InlineAsm::isInput:
- OpInfo.CallOperandVal = I.getOperand(OpNo++);
+ OpInfo.CallOperandVal = CS.getArgument(ArgNo++);
break;
case InlineAsm::isClobber:
// Nothing to do.
@@ -3617,7 +3620,7 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
// This is the result value of the call.
assert(RetValRegs.Regs.empty() &&
"Cannot have multiple output constraints yet!");
- assert(I.getType() != Type::VoidTy && "Bad inline asm!");
+ assert(CS.getType() != Type::VoidTy && "Bad inline asm!");
RetValRegs = OpInfo.AssignedRegs;
} else {
IndirectStoresToEmit.push_back(std::make_pair(OpInfo.AssignedRegs,
@@ -3751,13 +3754,13 @@ void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
// width/num elts. Make sure to convert it to the right type with
// bit_convert.
if (MVT::isVector(Val.getValueType())) {
- const VectorType *VTy = cast<VectorType>(I.getType());
+ const VectorType *VTy = cast<VectorType>(CS.getType());
MVT::ValueType DesiredVT = TLI.getValueType(VTy);
Val = DAG.getNode(ISD::BIT_CONVERT, DesiredVT, Val);
}
- setValue(&I, Val);
+ setValue(CS.getInstruction(), Val);
}
std::vector<std::pair<SDOperand, Value*> > StoresToEmit;
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index e88eb94282..69d0e12a37 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -69,9 +69,8 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
if (!isa<CallInst>(I)) continue;
CallInst *CI = cast<CallInst>(I);
- // If this call cannot unwind or is an inline asm, don't
- // convert it to an invoke.
- if (CI->isNoUnwind() || isa<InlineAsm>(CI->getCalledValue()))
+ // If this call cannot unwind, don't convert it to an invoke.
+ if (CI->isNoUnwind())
continue;
// Convert this function call into an invoke instruction.
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 08f031f40e..c083fe7810 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -1123,7 +1123,7 @@ void Verifier::visitInstruction(Instruction &I) {
"Instruction does not dominate all uses!", Op, &I);
}
} else if (isa<InlineAsm>(I.getOperand(i))) {
- Assert1(i == 0 && isa<CallInst>(I),
+ Assert1(i == 0 && (isa<CallInst>(I) || isa<InvokeInst>(I)),
"Cannot take the address of an inline asm!", &I);
}
}
diff --git a/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll b/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll
new file mode 100644
index 0000000000..98871d0e3a
--- /dev/null
+++ b/test/CodeGen/Generic/2007-12-17-InvokeAsm.ll
@@ -0,0 +1,15 @@
+; RUN: llvm-as < %s | llc -enable-eh
+
+target triple = "i686-pc-linux-gnu"
+
+define fastcc void @bc__support__high_resolution_time__initialize_clock_rate() {
+entry:
+ invoke void asm "rdtsc\0A\09movl %eax, $0\0A\09movl %edx, $1", "=*imr,=*imr,~{dirflag},~{fpsr},~{flags},~{dx},~{ax}"( i32* null, i32* null )
+ to label %.noexc unwind label %cleanup144
+
+.noexc: ; preds = %entry
+ ret void
+
+cleanup144: ; preds = %entry
+ unwind
+}
diff --git a/test/Transforms/Inline/2007-04-15-InlineEH.ll b/test/Transforms/Inline/2007-04-15-InlineEH.ll
index 9d28755d28..083a328ae6 100644
--- a/test/Transforms/Inline/2007-04-15-InlineEH.ll
+++ b/test/Transforms/Inline/2007-04-15-InlineEH.ll
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | opt -inline -disable-output
+; RUN: llvm-as < %s | opt -inline | llvm-dis | not grep {invoke void asm}
; PR1335
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"