#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
+#include "llvm/CodeGen/Analysis.h"
+#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Constant.h"
case Intrinsic::smul_with_overflow: Op = TargetOpcode::G_SMULO; break;
case Intrinsic::memcpy:
return translateMemcpy(CI);
+ case Intrinsic::eh_typeid_for: {
+ GlobalValue *GV = ExtractTypeInfo(CI.getArgOperand(0));
+ unsigned Reg = getOrCreateVReg(CI);
+ unsigned TypeID = MIRBuilder.getMF().getMMI().getTypeIDFor(GV);
+ MIRBuilder.buildConstant(Reg, TypeID);
+ return true;
+ }
case Intrinsic::objectsize: {
// If we don't know by now, we're never going to know.
const ConstantInt *Min = cast<ConstantInt>(CI.getArgOperand(1));
return true;
}
+bool IRTranslator::translateInvoke(const User &U) {
+ const InvokeInst &I = cast<InvokeInst>(U);
+ MachineFunction &MF = MIRBuilder.getMF();
+ MachineModuleInfo &MMI = MF.getMMI();
+
+ const BasicBlock *ReturnBB = I.getSuccessor(0);
+ const BasicBlock *EHPadBB = I.getSuccessor(1);
+
+ const Value *Callee(I.getCalledValue());
+ const Function *Fn = dyn_cast<Function>(Callee);
+ if (isa<InlineAsm>(Callee))
+ return false;
+
+ // FIXME: support invoking patchpoint and statepoint intrinsics.
+ if (Fn && Fn->isIntrinsic())
+ return false;
+
+ // FIXME: support whatever these are.
+ if (I.countOperandBundlesOfType(LLVMContext::OB_deopt))
+ return false;
+
+ // FIXME: support Windows exception handling.
+ if (!isa<LandingPadInst>(EHPadBB->front()))
+ return false;
+
+
+ // Emit the actual call, bracketed by EH_LABELs so that the MMI knows about
+ // the region covered by the try.
+ MCSymbol *BeginSymbol = MMI.getContext().createTempSymbol();
+ MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(BeginSymbol);
+
+ unsigned Res = I.getType()->isVoidTy() ? 0 : getOrCreateVReg(I);
+ SmallVector<CallLowering::ArgInfo, 8> Args;
+ for (auto &Arg: I.arg_operands())
+ Args.emplace_back(getOrCreateVReg(*Arg), Arg->getType());
+
+ if (!CLI->lowerCall(MIRBuilder, MachineOperand::CreateGA(Fn, 0),
+ CallLowering::ArgInfo(Res, I.getType()), Args))
+ return false;
+
+ MCSymbol *EndSymbol = MMI.getContext().createTempSymbol();
+ MIRBuilder.buildInstr(TargetOpcode::EH_LABEL).addSym(EndSymbol);
+
+ // FIXME: track probabilities.
+ MachineBasicBlock &EHPadMBB = getOrCreateBB(*EHPadBB),
+ &ReturnMBB = getOrCreateBB(*ReturnBB);
+ MMI.addInvoke(&EHPadMBB, BeginSymbol, EndSymbol);
+ MIRBuilder.getMBB().addSuccessor(&ReturnMBB);
+ MIRBuilder.getMBB().addSuccessor(&EHPadMBB);
+
+ return true;
+}
+
+bool IRTranslator::translateLandingPad(const User &U) {
+ const LandingPadInst &LP = cast<LandingPadInst>(U);
+
+ MachineBasicBlock &MBB = MIRBuilder.getMBB();
+ MachineFunction &MF = MIRBuilder.getMF();
+ MachineModuleInfo &MMI = MF.getMMI();
+ AddLandingPadInfo(LP, MMI, &MBB);
+
+ MBB.setIsEHPad();
+
+ // If there aren't registers to copy the values into (e.g., during SjLj
+ // exceptions), then don't bother.
+ auto &TLI = *MF.getSubtarget().getTargetLowering();
+ const Constant *PersonalityFn = MF.getFunction()->getPersonalityFn();
+ if (TLI.getExceptionPointerRegister(PersonalityFn) == 0 &&
+ TLI.getExceptionSelectorRegister(PersonalityFn) == 0)
+ return true;
+
+ // If landingpad's return type is token type, we don't create DAG nodes
+ // for its exception pointer and selector value. The extraction of exception
+ // pointer or selector value from token type landingpads is not currently
+ // supported.
+ if (LP.getType()->isTokenTy())
+ return true;
+
+ // Add a label to mark the beginning of the landing pad. Deletion of the
+ // landing pad can thus be detected via the MachineModuleInfo.
+ MIRBuilder.buildInstr(TargetOpcode::EH_LABEL)
+ .addSym(MMI.addLandingPad(&MBB));
+
+ // Mark exception register as live in.
+ SmallVector<unsigned, 2> Regs;
+ SmallVector<uint64_t, 2> Offsets;
+ LLT p0 = LLT::pointer(0, DL->getPointerSizeInBits());
+ if (unsigned Reg = TLI.getExceptionPointerRegister(PersonalityFn)) {
+ unsigned VReg = MRI->createGenericVirtualRegister(p0);
+ MIRBuilder.buildCopy(VReg, Reg);
+ Regs.push_back(VReg);
+ Offsets.push_back(0);
+ }
+
+ if (unsigned Reg = TLI.getExceptionSelectorRegister(PersonalityFn)) {
+ unsigned VReg = MRI->createGenericVirtualRegister(p0);
+ MIRBuilder.buildCopy(VReg, Reg);
+ Regs.push_back(VReg);
+ Offsets.push_back(p0.getSizeInBits());
+ }
+
+ MIRBuilder.buildSequence(getOrCreateVReg(LP), Regs, Offsets);
+ return true;
+}
+
bool IRTranslator::translateStaticAlloca(const AllocaInst &AI) {
if (!TPC->isGlobalISelAbortEnabled() && !AI.isStaticAlloca())
return false;
return true;
}
-
void IRTranslator::finalizeFunction() {
finishPendingPhis();
// Set the insertion point of all the following translations to
// the end of this basic block.
MIRBuilder.setMBB(MBB);
+
for (const Instruction &Inst: BB) {
bool Succeeded = translate(Inst);
if (!Succeeded) {
--- /dev/null
+; RUN: llc -O0 -mtriple=aarch64-apple-ios -global-isel -stop-after=irtranslator %s -o - | FileCheck %s
+
+@_ZTIi = external global i8*
+
+declare i32 @foo(i32)
+declare i32 @__gxx_personality_v0(...)
+declare i32 @llvm.eh.typeid.for(i8*)
+
+; CHECK: name: bar
+; CHECK: body:
+; CHECK: bb.0:
+; CHECK: successors: %bb.2{{.*}}%bb.1
+; CHECK: EH_LABEL
+; CHECK: %w0 = COPY
+; CHECK: BL @foo, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %w0, implicit-def %w0
+; CHECK: {{%[0-9]+}}(s32) = COPY %w0
+; CHECK: EH_LABEL
+
+; CHECK: bb.1
+; CHECK: EH_LABEL
+; CHECK: [[PTR:%[0-9]+]](p0) = COPY %x0
+; CHECK: [[SEL:%[0-9]+]](p0) = COPY %x1
+; CHECK: [[PTR_SEL:%[0-9]+]](s128) = G_SEQUENCE [[PTR]](p0), 0, [[SEL]](p0), 64
+; CHECK: [[PTR_RET:%[0-9]+]](s64), [[SEL_RET:%[0-9]+]](s32) = G_EXTRACT [[PTR_SEL]](s128), 0, 64
+; CHECK: %x0 = COPY [[PTR_RET]]
+; CHECK: %w1 = COPY [[SEL_RET]]
+
+; CHECK: bb.2:
+; CHECK: [[SEL:%[0-9]+]](s32) = G_CONSTANT 1
+; CHECK: {{%[0-9]+}}(s128) = G_INSERT {{%[0-9]+}}(s128), [[SEL]](s32), 64
+
+define { i8*, i32 } @bar() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+ %res32 = invoke i32 @foo(i32 42) to label %continue unwind label %broken
+
+
+broken:
+ %ptr.sel = landingpad { i8*, i32 } catch i8* bitcast(i8** @_ZTIi to i8*)
+ ret { i8*, i32 } %ptr.sel
+
+continue:
+ %sel.int = tail call i32 @llvm.eh.typeid.for(i8* bitcast(i8** @_ZTIi to i8*))
+ %res.good = insertvalue { i8*, i32 } undef, i32 %sel.int, 1
+ ret { i8*, i32 } %res.good
+}