Index: src/IceTargetLoweringARM32.cpp |
diff --git a/src/IceTargetLoweringARM32.cpp b/src/IceTargetLoweringARM32.cpp |
index 6691e1ed9c5a474a49f66f84d0fc2ef7d3bc1fa2..287e42dab33537604c52d985b2e65abfc1aaf544 100644 |
--- a/src/IceTargetLoweringARM32.cpp |
+++ b/src/IceTargetLoweringARM32.cpp |
@@ -30,6 +30,17 @@ |
namespace Ice { |
+namespace { |
+void UnimplementedError(const ClFlags &Flags) { |
+ if (!Flags.getSkipUnimplemented()) { |
+ // Use llvm_unreachable instead of report_fatal_error, which gives better |
+ // stack traces. |
+ llvm_unreachable("Not yet implemented"); |
+ abort(); |
+ } |
+} |
+} // end of anonymous namespace |
+ |
TargetARM32::TargetARM32(Cfg *Func) |
: TargetLowering(Func), UsesFramePointer(false) { |
// TODO: Don't initialize IntegerRegisters and friends every time. |
@@ -205,7 +216,8 @@ void TargetARM32::translateOm1() { |
bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) { |
(void)I; |
(void)NextNode; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
+ return false; |
} |
IceString TargetARM32::RegNames[] = { |
@@ -233,9 +245,9 @@ Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) { |
Reg = Func->makeVariable(Ty); |
Reg->setRegNum(RegNum); |
PhysicalRegisters[Ty][RegNum] = Reg; |
- // Specially mark SP as an "argument" so that it is considered |
+ // Specially mark SP and LR as an "argument" so that it is considered |
// live upon function entry. |
- if (RegNum == RegARM32::Reg_sp) { |
+ if (RegNum == RegARM32::Reg_sp || RegNum == RegARM32::Reg_lr) { |
Func->addImplicitArg(Reg); |
Reg->setIgnoreLiveness(); |
} |
@@ -245,25 +257,42 @@ Variable *TargetARM32::getPhysicalRegister(SizeT RegNum, Type Ty) { |
void TargetARM32::emitVariable(const Variable *Var) const { |
Ostream &Str = Ctx->getStrEmit(); |
- (void)Var; |
- (void)Str; |
- llvm::report_fatal_error("emitVariable: Not yet implemented"); |
+ if (Var->hasReg()) { |
+ Str << getRegName(Var->getRegNum(), Var->getType()); |
+ return; |
+ } |
+ if (Var->getWeight().isInf()) { |
+ llvm::report_fatal_error( |
+ "Infinite-weight Variable has no register assigned"); |
+ } |
+ int32_t Offset = Var->getStackOffset(); |
+ if (!hasFramePointer()) |
+ Offset += getStackAdjustment(); |
+ // TODO(jvoung): Handle out of range. Perhaps we need a scratch register |
+ // to materialize a larger offset. |
+ const bool SignExt = false; |
+ if (!OperandARM32Mem::canHoldOffset(Var->getType(), SignExt, Offset)) { |
+ llvm::report_fatal_error("Illegal stack offset"); |
+ } |
+ const Type FrameSPTy = IceType_i32; |
+ Str << "[" << getRegName(getFrameOrStackReg(), FrameSPTy) << ", " << Offset |
+ << "]"; |
} |
void TargetARM32::lowerArguments() { |
- llvm::report_fatal_error("lowerArguments: Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
Type TargetARM32::stackSlotType() { return IceType_i32; } |
void TargetARM32::addProlog(CfgNode *Node) { |
(void)Node; |
- llvm::report_fatal_error("addProlog: Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::addEpilog(CfgNode *Node) { |
(void)Node; |
- llvm::report_fatal_error("addEpilog: Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
llvm::SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include, |
@@ -305,7 +334,7 @@ void TargetARM32::lowerAlloca(const InstAlloca *Inst) { |
// restriction can be relaxed in some cases. |
NeedsStackAlignment = true; |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { |
@@ -314,75 +343,75 @@ void TargetARM32::lowerArithmetic(const InstArithmetic *Inst) { |
llvm_unreachable("Unknown arithmetic operator"); |
break; |
case InstArithmetic::Add: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::And: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Or: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Xor: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Sub: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Mul: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Shl: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Lshr: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Ashr: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Udiv: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Sdiv: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Urem: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Srem: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Fadd: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Fsub: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Fmul: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Fdiv: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstArithmetic::Frem: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
} |
} |
void TargetARM32::lowerAssign(const InstAssign *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerBr(const InstBr *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerCall(const InstCall *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerCast(const InstCast *Inst) { |
@@ -392,39 +421,39 @@ void TargetARM32::lowerCast(const InstCast *Inst) { |
Func->setError("Cast type not supported"); |
return; |
case InstCast::Sext: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
} |
case InstCast::Zext: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
} |
case InstCast::Trunc: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
} |
case InstCast::Fptrunc: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstCast::Fpext: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
} |
case InstCast::Fptosi: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstCast::Fptoui: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstCast::Sitofp: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
case InstCast::Uitofp: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
} |
case InstCast::Bitcast: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
break; |
} |
} |
@@ -432,72 +461,72 @@ void TargetARM32::lowerCast(const InstCast *Inst) { |
void TargetARM32::lowerExtractElement(const InstExtractElement *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerFcmp(const InstFcmp *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerIcmp(const InstIcmp *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerInsertElement(const InstInsertElement *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
switch (Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID) { |
case Intrinsics::AtomicCmpxchg: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::AtomicFence: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
case Intrinsics::AtomicFenceAll: |
// NOTE: FenceAll should prevent and load/store from being moved |
// across the fence (both atomic and non-atomic). The InstARM32Mfence |
// instruction is currently marked coarsely as "HasSideEffects". |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
case Intrinsics::AtomicIsLockFree: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::AtomicLoad: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::AtomicRMW: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
case Intrinsics::AtomicStore: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::Bswap: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::Ctpop: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::Ctlz: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::Cttz: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::Fabs: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::Longjmp: { |
@@ -542,7 +571,7 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
} |
case Intrinsics::NaClReadTP: { |
if (Ctx->getFlags().getUseSandboxing()) { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} else { |
InstCall *Call = makeHelperCall(H_call_read_tp, Instr->getDest(), 0); |
lowerCall(Call); |
@@ -556,19 +585,19 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
return; |
} |
case Intrinsics::Sqrt: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::Stacksave: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::Stackrestore: { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
} |
case Intrinsics::Trap: |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
return; |
case Intrinsics::UnknownIntrinsic: |
Func->setError("Should not be lowering UnknownIntrinsic"); |
@@ -579,17 +608,17 @@ void TargetARM32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
void TargetARM32::lowerLoad(const InstLoad *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::doAddressOptLoad() { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::randomlyInsertNop(float Probability) { |
RandomNumberGeneratorWrapper RNG(Ctx->getRNG()); |
if (RNG.getTrueWithProbability(Probability)) { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
} |
@@ -598,27 +627,42 @@ void TargetARM32::lowerPhi(const InstPhi * /*Inst*/) { |
} |
void TargetARM32::lowerRet(const InstRet *Inst) { |
- (void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ Variable *Reg = nullptr; |
+ if (Inst->hasRetValue()) { |
+ UnimplementedError(Func->getContext()->getFlags()); |
+ } |
+ // Add a ret instruction even if sandboxing is enabled, because |
+ // addEpilog explicitly looks for a ret instruction as a marker for |
+ // where to insert the frame removal instructions. |
+ // addEpilog is responsible for restoring the "lr" register as needed |
+ // prior to this ret instruction. |
+ _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg); |
+ // Add a fake use of sp to make sure sp stays alive for the entire |
+ // function. Otherwise post-call sp adjustments get dead-code |
+ // eliminated. TODO: Are there more places where the fake use |
+ // should be inserted? E.g. "void f(int n){while(1) g(n);}" may not |
+ // have a ret instruction. |
+ Variable *SP = Func->getTarget()->getPhysicalRegister(RegARM32::Reg_sp); |
+ Context.insert(InstFakeUse::create(Func, SP)); |
} |
void TargetARM32::lowerSelect(const InstSelect *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerStore(const InstStore *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::doAddressOptStore() { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerSwitch(const InstSwitch *Inst) { |
(void)Inst; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
@@ -630,7 +674,7 @@ void TargetARM32::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
// turned into zeroes, since loOperand() and hiOperand() don't expect |
// Undef input. |
void TargetARM32::prelowerPhis() { |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
// Lower the pre-ordered list of assignments into mov instructions. |
@@ -639,7 +683,7 @@ void TargetARM32::lowerPhiAssignments(CfgNode *Node, |
const AssignList &Assignments) { |
(void)Node; |
(void)Assignments; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::postLower() { |
@@ -647,7 +691,7 @@ void TargetARM32::postLower() { |
return; |
// Find two-address non-SSA instructions where Dest==Src0, and set |
// the DestNonKillable flag to keep liveness analysis consistent. |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
void TargetARM32::makeRandomRegisterPermutation( |
@@ -655,7 +699,7 @@ void TargetARM32::makeRandomRegisterPermutation( |
const llvm::SmallBitVector &ExcludeRegisters) const { |
(void)Permutation; |
(void)ExcludeRegisters; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Func->getContext()->getFlags()); |
} |
/* TODO(jvoung): avoid duplicate symbols with multiple targets. |
@@ -673,7 +717,7 @@ TargetDataARM32::TargetDataARM32(GlobalContext *Ctx) |
void TargetDataARM32::lowerGlobal(const VariableDeclaration &Var) const { |
(void)Var; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Ctx->getFlags()); |
} |
void TargetDataARM32::lowerGlobals( |
@@ -699,7 +743,7 @@ void TargetDataARM32::lowerGlobals( |
void TargetDataARM32::lowerConstants() const { |
if (Ctx->getFlags().getDisableTranslation()) |
return; |
- llvm::report_fatal_error("Not yet implemented"); |
+ UnimplementedError(Ctx->getFlags()); |
} |
} // end of namespace Ice |