1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceTargetLowering.h - Lowering interface -----*- C++ -*-===// 2*03ce13f7SAndroid Build Coastguard Worker // 3*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator 4*03ce13f7SAndroid Build Coastguard Worker // 5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*03ce13f7SAndroid Build Coastguard Worker // 8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*03ce13f7SAndroid Build Coastguard Worker /// 10*03ce13f7SAndroid Build Coastguard Worker /// \file 11*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares the TargetLowering, LoweringContext, and TargetDataLowering 12*03ce13f7SAndroid Build Coastguard Worker /// classes. 13*03ce13f7SAndroid Build Coastguard Worker /// 14*03ce13f7SAndroid Build Coastguard Worker /// TargetLowering is an abstract class used to drive the translation/lowering 15*03ce13f7SAndroid Build Coastguard Worker /// process. LoweringContext maintains a context for lowering each instruction, 16*03ce13f7SAndroid Build Coastguard Worker /// offering conveniences such as iterating over non-deleted instructions. 17*03ce13f7SAndroid Build Coastguard Worker /// TargetDataLowering is an abstract class used to drive the lowering/emission 18*03ce13f7SAndroid Build Coastguard Worker /// of global initializers, external global declarations, and internal constant 19*03ce13f7SAndroid Build Coastguard Worker /// pools. 20*03ce13f7SAndroid Build Coastguard Worker /// 21*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 22*03ce13f7SAndroid Build Coastguard Worker 23*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICETARGETLOWERING_H 24*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICETARGETLOWERING_H 25*03ce13f7SAndroid Build Coastguard Worker 26*03ce13f7SAndroid Build Coastguard Worker #include "IceBitVector.h" 27*03ce13f7SAndroid Build Coastguard Worker #include "IceCfgNode.h" 28*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h" 29*03ce13f7SAndroid Build Coastguard Worker #include "IceInst.h" // for the names of the Inst subtypes 30*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h" 31*03ce13f7SAndroid Build Coastguard Worker #include "IceRegAlloc.h" 32*03ce13f7SAndroid Build Coastguard Worker #include "IceTypes.h" 33*03ce13f7SAndroid Build Coastguard Worker 34*03ce13f7SAndroid Build Coastguard Worker #include <utility> 35*03ce13f7SAndroid Build Coastguard Worker 36*03ce13f7SAndroid Build Coastguard Worker namespace Ice { 37*03ce13f7SAndroid Build Coastguard Worker 38*03ce13f7SAndroid Build Coastguard Worker // UnimplementedError is defined as a macro so that we can get actual line 39*03ce13f7SAndroid Build Coastguard Worker // numbers. 40*03ce13f7SAndroid Build Coastguard Worker #define UnimplementedError(Flags) \ 41*03ce13f7SAndroid Build Coastguard Worker do { \ 42*03ce13f7SAndroid Build Coastguard Worker if (!static_cast<const ClFlags &>(Flags).getSkipUnimplemented()) { \ 43*03ce13f7SAndroid Build Coastguard Worker /* Use llvm_unreachable instead of report_fatal_error, which gives \ 44*03ce13f7SAndroid Build Coastguard Worker better stack traces. */ \ 45*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable("Not yet implemented"); \ 46*03ce13f7SAndroid Build Coastguard Worker abort(); \ 47*03ce13f7SAndroid Build Coastguard Worker } \ 48*03ce13f7SAndroid Build Coastguard Worker } while (0) 49*03ce13f7SAndroid Build Coastguard Worker 50*03ce13f7SAndroid Build Coastguard Worker // UnimplementedLoweringError is similar in style to UnimplementedError. Given 51*03ce13f7SAndroid Build Coastguard Worker // a TargetLowering object pointer and an Inst pointer, it adds appropriate 52*03ce13f7SAndroid Build Coastguard Worker // FakeDef and FakeUse instructions to try maintain liveness consistency. 53*03ce13f7SAndroid Build Coastguard Worker #define UnimplementedLoweringError(Target, Instr) \ 54*03ce13f7SAndroid Build Coastguard Worker do { \ 55*03ce13f7SAndroid Build Coastguard Worker if (getFlags().getSkipUnimplemented()) { \ 56*03ce13f7SAndroid Build Coastguard Worker (Target)->addFakeDefUses(Instr); \ 57*03ce13f7SAndroid Build Coastguard Worker } else { \ 58*03ce13f7SAndroid Build Coastguard Worker /* Use llvm_unreachable instead of report_fatal_error, which gives \ 59*03ce13f7SAndroid Build Coastguard Worker better stack traces. */ \ 60*03ce13f7SAndroid Build Coastguard Worker llvm_unreachable( \ 61*03ce13f7SAndroid Build Coastguard Worker (std::string("Not yet implemented: ") + Instr->getInstName()) \ 62*03ce13f7SAndroid Build Coastguard Worker .c_str()); \ 63*03ce13f7SAndroid Build Coastguard Worker abort(); \ 64*03ce13f7SAndroid Build Coastguard Worker } \ 65*03ce13f7SAndroid Build Coastguard Worker } while (0) 66*03ce13f7SAndroid Build Coastguard Worker 67*03ce13f7SAndroid Build Coastguard Worker /// LoweringContext makes it easy to iterate through non-deleted instructions in 68*03ce13f7SAndroid Build Coastguard Worker /// a node, and insert new (lowered) instructions at the current point. Along 69*03ce13f7SAndroid Build Coastguard Worker /// with the instruction list container and associated iterators, it holds the 70*03ce13f7SAndroid Build Coastguard Worker /// current node, which is needed when inserting new instructions in order to 71*03ce13f7SAndroid Build Coastguard Worker /// track whether variables are used as single-block or multi-block. 72*03ce13f7SAndroid Build Coastguard Worker class LoweringContext { 73*03ce13f7SAndroid Build Coastguard Worker LoweringContext(const LoweringContext &) = delete; 74*03ce13f7SAndroid Build Coastguard Worker LoweringContext &operator=(const LoweringContext &) = delete; 75*03ce13f7SAndroid Build Coastguard Worker 76*03ce13f7SAndroid Build Coastguard Worker public: 77*03ce13f7SAndroid Build Coastguard Worker LoweringContext() = default; 78*03ce13f7SAndroid Build Coastguard Worker ~LoweringContext() = default; 79*03ce13f7SAndroid Build Coastguard Worker void init(CfgNode *Node); getNextInst()80*03ce13f7SAndroid Build Coastguard Worker Inst *getNextInst() const { 81*03ce13f7SAndroid Build Coastguard Worker if (Next == End) 82*03ce13f7SAndroid Build Coastguard Worker return nullptr; 83*03ce13f7SAndroid Build Coastguard Worker return iteratorToInst(Next); 84*03ce13f7SAndroid Build Coastguard Worker } getNextInst(InstList::iterator & Iter)85*03ce13f7SAndroid Build Coastguard Worker Inst *getNextInst(InstList::iterator &Iter) const { 86*03ce13f7SAndroid Build Coastguard Worker advanceForward(Iter); 87*03ce13f7SAndroid Build Coastguard Worker if (Iter == End) 88*03ce13f7SAndroid Build Coastguard Worker return nullptr; 89*03ce13f7SAndroid Build Coastguard Worker return iteratorToInst(Iter); 90*03ce13f7SAndroid Build Coastguard Worker } getNode()91*03ce13f7SAndroid Build Coastguard Worker CfgNode *getNode() const { return Node; } atEnd()92*03ce13f7SAndroid Build Coastguard Worker bool atEnd() const { return Cur == End; } getCur()93*03ce13f7SAndroid Build Coastguard Worker InstList::iterator getCur() const { return Cur; } getNext()94*03ce13f7SAndroid Build Coastguard Worker InstList::iterator getNext() const { return Next; } getEnd()95*03ce13f7SAndroid Build Coastguard Worker InstList::iterator getEnd() const { return End; } 96*03ce13f7SAndroid Build Coastguard Worker void insert(Inst *Instr); insert(Args &&...A)97*03ce13f7SAndroid Build Coastguard Worker template <typename Inst, typename... Args> Inst *insert(Args &&...A) { 98*03ce13f7SAndroid Build Coastguard Worker auto *New = Inst::create(Node->getCfg(), std::forward<Args>(A)...); 99*03ce13f7SAndroid Build Coastguard Worker insert(New); 100*03ce13f7SAndroid Build Coastguard Worker return New; 101*03ce13f7SAndroid Build Coastguard Worker } 102*03ce13f7SAndroid Build Coastguard Worker Inst *getLastInserted() const; advanceCur()103*03ce13f7SAndroid Build Coastguard Worker void advanceCur() { Cur = Next; } advanceNext()104*03ce13f7SAndroid Build Coastguard Worker void advanceNext() { advanceForward(Next); } setCur(InstList::iterator C)105*03ce13f7SAndroid Build Coastguard Worker void setCur(InstList::iterator C) { Cur = C; } setNext(InstList::iterator N)106*03ce13f7SAndroid Build Coastguard Worker void setNext(InstList::iterator N) { Next = N; } 107*03ce13f7SAndroid Build Coastguard Worker void rewind(); setInsertPoint(const InstList::iterator & Position)108*03ce13f7SAndroid Build Coastguard Worker void setInsertPoint(const InstList::iterator &Position) { Next = Position; } 109*03ce13f7SAndroid Build Coastguard Worker void availabilityReset(); 110*03ce13f7SAndroid Build Coastguard Worker void availabilityUpdate(); 111*03ce13f7SAndroid Build Coastguard Worker Variable *availabilityGet(Operand *Src) const; 112*03ce13f7SAndroid Build Coastguard Worker 113*03ce13f7SAndroid Build Coastguard Worker private: 114*03ce13f7SAndroid Build Coastguard Worker /// Node is the argument to Inst::updateVars(). 115*03ce13f7SAndroid Build Coastguard Worker CfgNode *Node = nullptr; 116*03ce13f7SAndroid Build Coastguard Worker Inst *LastInserted = nullptr; 117*03ce13f7SAndroid Build Coastguard Worker /// Cur points to the current instruction being considered. It is guaranteed 118*03ce13f7SAndroid Build Coastguard Worker /// to point to a non-deleted instruction, or to be End. 119*03ce13f7SAndroid Build Coastguard Worker InstList::iterator Cur; 120*03ce13f7SAndroid Build Coastguard Worker /// Next doubles as a pointer to the next valid instruction (if any), and the 121*03ce13f7SAndroid Build Coastguard Worker /// new-instruction insertion point. It is also updated for the caller in case 122*03ce13f7SAndroid Build Coastguard Worker /// the lowering consumes more than one high-level instruction. It is 123*03ce13f7SAndroid Build Coastguard Worker /// guaranteed to point to a non-deleted instruction after Cur, or to be End. 124*03ce13f7SAndroid Build Coastguard Worker // TODO: Consider separating the notion of "next valid instruction" and "new 125*03ce13f7SAndroid Build Coastguard Worker // instruction insertion point", to avoid confusion when previously-deleted 126*03ce13f7SAndroid Build Coastguard Worker // instructions come between the two points. 127*03ce13f7SAndroid Build Coastguard Worker InstList::iterator Next; 128*03ce13f7SAndroid Build Coastguard Worker /// Begin is a copy of Insts.begin(), used if iterators are moved backward. 129*03ce13f7SAndroid Build Coastguard Worker InstList::iterator Begin; 130*03ce13f7SAndroid Build Coastguard Worker /// End is a copy of Insts.end(), used if Next needs to be advanced. 131*03ce13f7SAndroid Build Coastguard Worker InstList::iterator End; 132*03ce13f7SAndroid Build Coastguard Worker /// LastDest and LastSrc capture the parameters of the last "Dest=Src" simple 133*03ce13f7SAndroid Build Coastguard Worker /// assignment inserted (provided Src is a variable). This is used for simple 134*03ce13f7SAndroid Build Coastguard Worker /// availability analysis. 135*03ce13f7SAndroid Build Coastguard Worker Variable *LastDest = nullptr; 136*03ce13f7SAndroid Build Coastguard Worker Variable *LastSrc = nullptr; 137*03ce13f7SAndroid Build Coastguard Worker 138*03ce13f7SAndroid Build Coastguard Worker void skipDeleted(InstList::iterator &I) const; 139*03ce13f7SAndroid Build Coastguard Worker void advanceForward(InstList::iterator &I) const; 140*03ce13f7SAndroid Build Coastguard Worker }; 141*03ce13f7SAndroid Build Coastguard Worker 142*03ce13f7SAndroid Build Coastguard Worker /// A helper class to advance the LoweringContext at each loop iteration. 143*03ce13f7SAndroid Build Coastguard Worker class PostIncrLoweringContext { 144*03ce13f7SAndroid Build Coastguard Worker PostIncrLoweringContext() = delete; 145*03ce13f7SAndroid Build Coastguard Worker PostIncrLoweringContext(const PostIncrLoweringContext &) = delete; 146*03ce13f7SAndroid Build Coastguard Worker PostIncrLoweringContext &operator=(const PostIncrLoweringContext &) = delete; 147*03ce13f7SAndroid Build Coastguard Worker 148*03ce13f7SAndroid Build Coastguard Worker public: PostIncrLoweringContext(LoweringContext & Context)149*03ce13f7SAndroid Build Coastguard Worker explicit PostIncrLoweringContext(LoweringContext &Context) 150*03ce13f7SAndroid Build Coastguard Worker : Context(Context) {} ~PostIncrLoweringContext()151*03ce13f7SAndroid Build Coastguard Worker ~PostIncrLoweringContext() { 152*03ce13f7SAndroid Build Coastguard Worker Context.advanceCur(); 153*03ce13f7SAndroid Build Coastguard Worker Context.advanceNext(); 154*03ce13f7SAndroid Build Coastguard Worker } 155*03ce13f7SAndroid Build Coastguard Worker 156*03ce13f7SAndroid Build Coastguard Worker private: 157*03ce13f7SAndroid Build Coastguard Worker LoweringContext &Context; 158*03ce13f7SAndroid Build Coastguard Worker }; 159*03ce13f7SAndroid Build Coastguard Worker 160*03ce13f7SAndroid Build Coastguard Worker /// TargetLowering is the base class for all backends in Subzero. In addition to 161*03ce13f7SAndroid Build Coastguard Worker /// implementing the abstract methods in this class, each concrete target must 162*03ce13f7SAndroid Build Coastguard Worker /// also implement a named constructor in its own namespace. For instance, for 163*03ce13f7SAndroid Build Coastguard Worker /// X8632 we have: 164*03ce13f7SAndroid Build Coastguard Worker /// 165*03ce13f7SAndroid Build Coastguard Worker /// namespace X8632 { 166*03ce13f7SAndroid Build Coastguard Worker /// void createTargetLowering(Cfg *Func); 167*03ce13f7SAndroid Build Coastguard Worker /// } 168*03ce13f7SAndroid Build Coastguard Worker class TargetLowering { 169*03ce13f7SAndroid Build Coastguard Worker TargetLowering() = delete; 170*03ce13f7SAndroid Build Coastguard Worker TargetLowering(const TargetLowering &) = delete; 171*03ce13f7SAndroid Build Coastguard Worker TargetLowering &operator=(const TargetLowering &) = delete; 172*03ce13f7SAndroid Build Coastguard Worker 173*03ce13f7SAndroid Build Coastguard Worker public: 174*03ce13f7SAndroid Build Coastguard Worker static void staticInit(GlobalContext *Ctx); 175*03ce13f7SAndroid Build Coastguard Worker // Each target must define a public static method: 176*03ce13f7SAndroid Build Coastguard Worker // static void staticInit(GlobalContext *Ctx); 177*03ce13f7SAndroid Build Coastguard Worker static bool shouldBePooled(const class Constant *C); 178*03ce13f7SAndroid Build Coastguard Worker static Type getPointerType(); 179*03ce13f7SAndroid Build Coastguard Worker 180*03ce13f7SAndroid Build Coastguard Worker static std::unique_ptr<TargetLowering> createLowering(TargetArch Target, 181*03ce13f7SAndroid Build Coastguard Worker Cfg *Func); 182*03ce13f7SAndroid Build Coastguard Worker 183*03ce13f7SAndroid Build Coastguard Worker virtual std::unique_ptr<Assembler> createAssembler() const = 0; 184*03ce13f7SAndroid Build Coastguard Worker translate()185*03ce13f7SAndroid Build Coastguard Worker void translate() { 186*03ce13f7SAndroid Build Coastguard Worker switch (Func->getOptLevel()) { 187*03ce13f7SAndroid Build Coastguard Worker case Opt_m1: 188*03ce13f7SAndroid Build Coastguard Worker translateOm1(); 189*03ce13f7SAndroid Build Coastguard Worker break; 190*03ce13f7SAndroid Build Coastguard Worker case Opt_0: 191*03ce13f7SAndroid Build Coastguard Worker translateO0(); 192*03ce13f7SAndroid Build Coastguard Worker break; 193*03ce13f7SAndroid Build Coastguard Worker case Opt_1: 194*03ce13f7SAndroid Build Coastguard Worker translateO1(); 195*03ce13f7SAndroid Build Coastguard Worker break; 196*03ce13f7SAndroid Build Coastguard Worker case Opt_2: 197*03ce13f7SAndroid Build Coastguard Worker translateO2(); 198*03ce13f7SAndroid Build Coastguard Worker break; 199*03ce13f7SAndroid Build Coastguard Worker } 200*03ce13f7SAndroid Build Coastguard Worker } translateOm1()201*03ce13f7SAndroid Build Coastguard Worker virtual void translateOm1() { 202*03ce13f7SAndroid Build Coastguard Worker Func->setError("Target doesn't specify Om1 lowering steps."); 203*03ce13f7SAndroid Build Coastguard Worker } translateO0()204*03ce13f7SAndroid Build Coastguard Worker virtual void translateO0() { 205*03ce13f7SAndroid Build Coastguard Worker Func->setError("Target doesn't specify O0 lowering steps."); 206*03ce13f7SAndroid Build Coastguard Worker } translateO1()207*03ce13f7SAndroid Build Coastguard Worker virtual void translateO1() { 208*03ce13f7SAndroid Build Coastguard Worker Func->setError("Target doesn't specify O1 lowering steps."); 209*03ce13f7SAndroid Build Coastguard Worker } translateO2()210*03ce13f7SAndroid Build Coastguard Worker virtual void translateO2() { 211*03ce13f7SAndroid Build Coastguard Worker Func->setError("Target doesn't specify O2 lowering steps."); 212*03ce13f7SAndroid Build Coastguard Worker } 213*03ce13f7SAndroid Build Coastguard Worker 214*03ce13f7SAndroid Build Coastguard Worker /// Generates calls to intrinsics for operations the Target can't handle. 215*03ce13f7SAndroid Build Coastguard Worker void genTargetHelperCalls(); 216*03ce13f7SAndroid Build Coastguard Worker /// Tries to do address mode optimization on a single instruction. 217*03ce13f7SAndroid Build Coastguard Worker void doAddressOpt(); 218*03ce13f7SAndroid Build Coastguard Worker /// Lowers a single non-Phi instruction. 219*03ce13f7SAndroid Build Coastguard Worker void lower(); 220*03ce13f7SAndroid Build Coastguard Worker /// Inserts and lowers a single high-level instruction at a specific insertion 221*03ce13f7SAndroid Build Coastguard Worker /// point. 222*03ce13f7SAndroid Build Coastguard Worker void lowerInst(CfgNode *Node, InstList::iterator Next, InstHighLevel *Instr); 223*03ce13f7SAndroid Build Coastguard Worker /// Does preliminary lowering of the set of Phi instructions in the current 224*03ce13f7SAndroid Build Coastguard Worker /// node. The main intention is to do what's needed to keep the unlowered Phi 225*03ce13f7SAndroid Build Coastguard Worker /// instructions consistent with the lowered non-Phi instructions, e.g. to 226*03ce13f7SAndroid Build Coastguard Worker /// lower 64-bit operands on a 32-bit target. prelowerPhis()227*03ce13f7SAndroid Build Coastguard Worker virtual void prelowerPhis() {} 228*03ce13f7SAndroid Build Coastguard Worker /// Tries to do branch optimization on a single instruction. Returns true if 229*03ce13f7SAndroid Build Coastguard Worker /// some optimization was done. doBranchOpt(Inst *,const CfgNode *)230*03ce13f7SAndroid Build Coastguard Worker virtual bool doBranchOpt(Inst * /*I*/, const CfgNode * /*NextNode*/) { 231*03ce13f7SAndroid Build Coastguard Worker return false; 232*03ce13f7SAndroid Build Coastguard Worker } 233*03ce13f7SAndroid Build Coastguard Worker 234*03ce13f7SAndroid Build Coastguard Worker virtual SizeT getNumRegisters() const = 0; 235*03ce13f7SAndroid Build Coastguard Worker /// Returns a variable pre-colored to the specified physical register. This is 236*03ce13f7SAndroid Build Coastguard Worker /// generally used to get very direct access to the register such as in the 237*03ce13f7SAndroid Build Coastguard Worker /// prolog or epilog or for marking scratch registers as killed by a call. If 238*03ce13f7SAndroid Build Coastguard Worker /// a Type is not provided, a target-specific default type is used. 239*03ce13f7SAndroid Build Coastguard Worker virtual Variable *getPhysicalRegister(RegNumT RegNum, 240*03ce13f7SAndroid Build Coastguard Worker Type Ty = IceType_void) = 0; 241*03ce13f7SAndroid Build Coastguard Worker /// Returns a printable name for the register. 242*03ce13f7SAndroid Build Coastguard Worker virtual const char *getRegName(RegNumT RegNum, Type Ty) const = 0; 243*03ce13f7SAndroid Build Coastguard Worker hasFramePointer()244*03ce13f7SAndroid Build Coastguard Worker virtual bool hasFramePointer() const { return false; } 245*03ce13f7SAndroid Build Coastguard Worker virtual void setHasFramePointer() = 0; 246*03ce13f7SAndroid Build Coastguard Worker virtual RegNumT getStackReg() const = 0; 247*03ce13f7SAndroid Build Coastguard Worker virtual RegNumT getFrameReg() const = 0; 248*03ce13f7SAndroid Build Coastguard Worker virtual RegNumT getFrameOrStackReg() const = 0; 249*03ce13f7SAndroid Build Coastguard Worker virtual size_t typeWidthInBytesOnStack(Type Ty) const = 0; 250*03ce13f7SAndroid Build Coastguard Worker virtual uint32_t getStackAlignment() const = 0; needsStackPointerAlignment()251*03ce13f7SAndroid Build Coastguard Worker virtual bool needsStackPointerAlignment() const { return false; } 252*03ce13f7SAndroid Build Coastguard Worker virtual void reserveFixedAllocaArea(size_t Size, size_t Align) = 0; 253*03ce13f7SAndroid Build Coastguard Worker virtual int32_t getFrameFixedAllocaOffset() const = 0; maxOutArgsSizeBytes()254*03ce13f7SAndroid Build Coastguard Worker virtual uint32_t maxOutArgsSizeBytes() const { return 0; } 255*03ce13f7SAndroid Build Coastguard Worker // Addressing relative to frame pointer differs in MIPS compared to X86/ARM 256*03ce13f7SAndroid Build Coastguard Worker // since MIPS decrements its stack pointer prior to saving it in the frame 257*03ce13f7SAndroid Build Coastguard Worker // pointer register. getFramePointerOffset(uint32_t CurrentOffset,uint32_t Size)258*03ce13f7SAndroid Build Coastguard Worker virtual uint32_t getFramePointerOffset(uint32_t CurrentOffset, 259*03ce13f7SAndroid Build Coastguard Worker uint32_t Size) const { 260*03ce13f7SAndroid Build Coastguard Worker return -(CurrentOffset + Size); 261*03ce13f7SAndroid Build Coastguard Worker } 262*03ce13f7SAndroid Build Coastguard Worker /// Return whether a 64-bit Variable should be split into a Variable64On32. 263*03ce13f7SAndroid Build Coastguard Worker virtual bool shouldSplitToVariable64On32(Type Ty) const = 0; 264*03ce13f7SAndroid Build Coastguard Worker 265*03ce13f7SAndroid Build Coastguard Worker /// Return whether a Vector Variable should be split into a VariableVecOn32. shouldSplitToVariableVecOn32(Type Ty)266*03ce13f7SAndroid Build Coastguard Worker virtual bool shouldSplitToVariableVecOn32(Type Ty) const { 267*03ce13f7SAndroid Build Coastguard Worker (void)Ty; 268*03ce13f7SAndroid Build Coastguard Worker return false; 269*03ce13f7SAndroid Build Coastguard Worker } 270*03ce13f7SAndroid Build Coastguard Worker hasComputedFrame()271*03ce13f7SAndroid Build Coastguard Worker bool hasComputedFrame() const { return HasComputedFrame; } 272*03ce13f7SAndroid Build Coastguard Worker /// Returns true if this function calls a function that has the "returns 273*03ce13f7SAndroid Build Coastguard Worker /// twice" attribute. callsReturnsTwice()274*03ce13f7SAndroid Build Coastguard Worker bool callsReturnsTwice() const { return CallsReturnsTwice; } setCallsReturnsTwice(bool RetTwice)275*03ce13f7SAndroid Build Coastguard Worker void setCallsReturnsTwice(bool RetTwice) { CallsReturnsTwice = RetTwice; } makeNextLabelNumber()276*03ce13f7SAndroid Build Coastguard Worker SizeT makeNextLabelNumber() { return NextLabelNumber++; } makeNextJumpTableNumber()277*03ce13f7SAndroid Build Coastguard Worker SizeT makeNextJumpTableNumber() { return NextJumpTableNumber++; } getContext()278*03ce13f7SAndroid Build Coastguard Worker LoweringContext &getContext() { return Context; } getFunc()279*03ce13f7SAndroid Build Coastguard Worker Cfg *getFunc() const { return Func; } getGlobalContext()280*03ce13f7SAndroid Build Coastguard Worker GlobalContext *getGlobalContext() const { return Ctx; } 281*03ce13f7SAndroid Build Coastguard Worker 282*03ce13f7SAndroid Build Coastguard Worker enum RegSet { 283*03ce13f7SAndroid Build Coastguard Worker RegSet_None = 0, 284*03ce13f7SAndroid Build Coastguard Worker RegSet_CallerSave = 1 << 0, 285*03ce13f7SAndroid Build Coastguard Worker RegSet_CalleeSave = 1 << 1, 286*03ce13f7SAndroid Build Coastguard Worker RegSet_StackPointer = 1 << 2, 287*03ce13f7SAndroid Build Coastguard Worker RegSet_FramePointer = 1 << 3, 288*03ce13f7SAndroid Build Coastguard Worker RegSet_All = ~RegSet_None 289*03ce13f7SAndroid Build Coastguard Worker }; 290*03ce13f7SAndroid Build Coastguard Worker using RegSetMask = uint32_t; 291*03ce13f7SAndroid Build Coastguard Worker 292*03ce13f7SAndroid Build Coastguard Worker virtual SmallBitVector getRegisterSet(RegSetMask Include, 293*03ce13f7SAndroid Build Coastguard Worker RegSetMask Exclude) const = 0; 294*03ce13f7SAndroid Build Coastguard Worker /// Get the set of physical registers available for the specified Variable's 295*03ce13f7SAndroid Build Coastguard Worker /// register class, applying register restrictions from the command line. 296*03ce13f7SAndroid Build Coastguard Worker virtual const SmallBitVector & 297*03ce13f7SAndroid Build Coastguard Worker getRegistersForVariable(const Variable *Var) const = 0; 298*03ce13f7SAndroid Build Coastguard Worker /// Get the set of *all* physical registers available for the specified 299*03ce13f7SAndroid Build Coastguard Worker /// Variable's register class, *not* applying register restrictions from the 300*03ce13f7SAndroid Build Coastguard Worker /// command line. 301*03ce13f7SAndroid Build Coastguard Worker virtual const SmallBitVector & 302*03ce13f7SAndroid Build Coastguard Worker getAllRegistersForVariable(const Variable *Var) const = 0; 303*03ce13f7SAndroid Build Coastguard Worker virtual const SmallBitVector &getAliasesForRegister(RegNumT) const = 0; 304*03ce13f7SAndroid Build Coastguard Worker 305*03ce13f7SAndroid Build Coastguard Worker void regAlloc(RegAllocKind Kind); 306*03ce13f7SAndroid Build Coastguard Worker void postRegallocSplitting(const SmallBitVector &RegMask); 307*03ce13f7SAndroid Build Coastguard Worker 308*03ce13f7SAndroid Build Coastguard Worker /// Get the minimum number of clusters required for a jump table to be 309*03ce13f7SAndroid Build Coastguard Worker /// considered. 310*03ce13f7SAndroid Build Coastguard Worker virtual SizeT getMinJumpTableSize() const = 0; 311*03ce13f7SAndroid Build Coastguard Worker virtual void emitJumpTable(const Cfg *Func, 312*03ce13f7SAndroid Build Coastguard Worker const InstJumpTable *JumpTable) const = 0; 313*03ce13f7SAndroid Build Coastguard Worker 314*03ce13f7SAndroid Build Coastguard Worker virtual void emitVariable(const Variable *Var) const = 0; 315*03ce13f7SAndroid Build Coastguard Worker 316*03ce13f7SAndroid Build Coastguard Worker void emitWithoutPrefix(const ConstantRelocatable *CR, 317*03ce13f7SAndroid Build Coastguard Worker const char *Suffix = "") const; 318*03ce13f7SAndroid Build Coastguard Worker 319*03ce13f7SAndroid Build Coastguard Worker virtual void emit(const ConstantInteger32 *C) const = 0; 320*03ce13f7SAndroid Build Coastguard Worker virtual void emit(const ConstantInteger64 *C) const = 0; 321*03ce13f7SAndroid Build Coastguard Worker virtual void emit(const ConstantFloat *C) const = 0; 322*03ce13f7SAndroid Build Coastguard Worker virtual void emit(const ConstantDouble *C) const = 0; 323*03ce13f7SAndroid Build Coastguard Worker virtual void emit(const ConstantUndef *C) const = 0; 324*03ce13f7SAndroid Build Coastguard Worker virtual void emit(const ConstantRelocatable *CR) const = 0; 325*03ce13f7SAndroid Build Coastguard Worker 326*03ce13f7SAndroid Build Coastguard Worker /// Performs target-specific argument lowering. 327*03ce13f7SAndroid Build Coastguard Worker virtual void lowerArguments() = 0; 328*03ce13f7SAndroid Build Coastguard Worker initNodeForLowering(CfgNode *)329*03ce13f7SAndroid Build Coastguard Worker virtual void initNodeForLowering(CfgNode *) {} 330*03ce13f7SAndroid Build Coastguard Worker virtual void addProlog(CfgNode *Node) = 0; 331*03ce13f7SAndroid Build Coastguard Worker virtual void addEpilog(CfgNode *Node) = 0; 332*03ce13f7SAndroid Build Coastguard Worker 333*03ce13f7SAndroid Build Coastguard Worker /// Create a properly-typed "mov" instruction. This is primarily for local 334*03ce13f7SAndroid Build Coastguard Worker /// variable splitting. createLoweredMove(Variable * Dest,Variable * SrcVar)335*03ce13f7SAndroid Build Coastguard Worker virtual Inst *createLoweredMove(Variable *Dest, Variable *SrcVar) { 336*03ce13f7SAndroid Build Coastguard Worker // TODO(stichnot): make pure virtual by implementing for all targets 337*03ce13f7SAndroid Build Coastguard Worker (void)Dest; 338*03ce13f7SAndroid Build Coastguard Worker (void)SrcVar; 339*03ce13f7SAndroid Build Coastguard Worker llvm::report_fatal_error("createLoweredMove() unimplemented"); 340*03ce13f7SAndroid Build Coastguard Worker return nullptr; 341*03ce13f7SAndroid Build Coastguard Worker } 342*03ce13f7SAndroid Build Coastguard Worker 343*03ce13f7SAndroid Build Coastguard Worker virtual ~TargetLowering() = default; 344*03ce13f7SAndroid Build Coastguard Worker 345*03ce13f7SAndroid Build Coastguard Worker private: 346*03ce13f7SAndroid Build Coastguard Worker /// This indicates whether we are in the genTargetHelperCalls phase, and 347*03ce13f7SAndroid Build Coastguard Worker /// therefore can do things like scalarization. 348*03ce13f7SAndroid Build Coastguard Worker bool GeneratingTargetHelpers = false; 349*03ce13f7SAndroid Build Coastguard Worker 350*03ce13f7SAndroid Build Coastguard Worker protected: 351*03ce13f7SAndroid Build Coastguard Worker explicit TargetLowering(Cfg *Func); 352*03ce13f7SAndroid Build Coastguard Worker // Applies command line filters to TypeToRegisterSet array. 353*03ce13f7SAndroid Build Coastguard Worker static void filterTypeToRegisterSet( 354*03ce13f7SAndroid Build Coastguard Worker GlobalContext *Ctx, int32_t NumRegs, SmallBitVector TypeToRegisterSet[], 355*03ce13f7SAndroid Build Coastguard Worker size_t TypeToRegisterSetSize, 356*03ce13f7SAndroid Build Coastguard Worker std::function<std::string(RegNumT)> getRegName, 357*03ce13f7SAndroid Build Coastguard Worker std::function<const char *(RegClass)> getRegClassName); 358*03ce13f7SAndroid Build Coastguard Worker virtual void lowerAlloca(const InstAlloca *Instr) = 0; 359*03ce13f7SAndroid Build Coastguard Worker virtual void lowerArithmetic(const InstArithmetic *Instr) = 0; 360*03ce13f7SAndroid Build Coastguard Worker virtual void lowerAssign(const InstAssign *Instr) = 0; 361*03ce13f7SAndroid Build Coastguard Worker virtual void lowerBr(const InstBr *Instr) = 0; 362*03ce13f7SAndroid Build Coastguard Worker virtual void lowerBreakpoint(const InstBreakpoint *Instr) = 0; 363*03ce13f7SAndroid Build Coastguard Worker virtual void lowerCall(const InstCall *Instr) = 0; 364*03ce13f7SAndroid Build Coastguard Worker virtual void lowerCast(const InstCast *Instr) = 0; 365*03ce13f7SAndroid Build Coastguard Worker virtual void lowerFcmp(const InstFcmp *Instr) = 0; 366*03ce13f7SAndroid Build Coastguard Worker virtual void lowerExtractElement(const InstExtractElement *Instr) = 0; 367*03ce13f7SAndroid Build Coastguard Worker virtual void lowerIcmp(const InstIcmp *Instr) = 0; 368*03ce13f7SAndroid Build Coastguard Worker virtual void lowerInsertElement(const InstInsertElement *Instr) = 0; 369*03ce13f7SAndroid Build Coastguard Worker virtual void lowerIntrinsic(const InstIntrinsic *Instr) = 0; 370*03ce13f7SAndroid Build Coastguard Worker virtual void lowerLoad(const InstLoad *Instr) = 0; 371*03ce13f7SAndroid Build Coastguard Worker virtual void lowerPhi(const InstPhi *Instr) = 0; 372*03ce13f7SAndroid Build Coastguard Worker virtual void lowerRet(const InstRet *Instr) = 0; 373*03ce13f7SAndroid Build Coastguard Worker virtual void lowerSelect(const InstSelect *Instr) = 0; 374*03ce13f7SAndroid Build Coastguard Worker virtual void lowerShuffleVector(const InstShuffleVector *Instr) = 0; 375*03ce13f7SAndroid Build Coastguard Worker virtual void lowerStore(const InstStore *Instr) = 0; 376*03ce13f7SAndroid Build Coastguard Worker virtual void lowerSwitch(const InstSwitch *Instr) = 0; 377*03ce13f7SAndroid Build Coastguard Worker virtual void lowerUnreachable(const InstUnreachable *Instr) = 0; 378*03ce13f7SAndroid Build Coastguard Worker virtual void lowerOther(const Inst *Instr); 379*03ce13f7SAndroid Build Coastguard Worker 380*03ce13f7SAndroid Build Coastguard Worker virtual void genTargetHelperCallFor(Inst *Instr) = 0; 381*03ce13f7SAndroid Build Coastguard Worker virtual uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) = 0; 382*03ce13f7SAndroid Build Coastguard Worker 383*03ce13f7SAndroid Build Coastguard Worker /// Opportunity to modify other instructions to help Address Optimization doAddressOptOther()384*03ce13f7SAndroid Build Coastguard Worker virtual void doAddressOptOther() {} doAddressOptLoad()385*03ce13f7SAndroid Build Coastguard Worker virtual void doAddressOptLoad() {} doAddressOptStore()386*03ce13f7SAndroid Build Coastguard Worker virtual void doAddressOptStore() {} doAddressOptLoadSubVector()387*03ce13f7SAndroid Build Coastguard Worker virtual void doAddressOptLoadSubVector() {} doAddressOptStoreSubVector()388*03ce13f7SAndroid Build Coastguard Worker virtual void doAddressOptStoreSubVector() {} doMockBoundsCheck(Operand *)389*03ce13f7SAndroid Build Coastguard Worker virtual void doMockBoundsCheck(Operand *) {} 390*03ce13f7SAndroid Build Coastguard Worker /// This gives the target an opportunity to post-process the lowered expansion 391*03ce13f7SAndroid Build Coastguard Worker /// before returning. postLower()392*03ce13f7SAndroid Build Coastguard Worker virtual void postLower() {} 393*03ce13f7SAndroid Build Coastguard Worker 394*03ce13f7SAndroid Build Coastguard Worker /// When the SkipUnimplemented flag is set, addFakeDefUses() gets invoked by 395*03ce13f7SAndroid Build Coastguard Worker /// the UnimplementedLoweringError macro to insert fake uses of all the 396*03ce13f7SAndroid Build Coastguard Worker /// instruction variables and a fake def of the instruction dest, in order to 397*03ce13f7SAndroid Build Coastguard Worker /// preserve integrity of liveness analysis. 398*03ce13f7SAndroid Build Coastguard Worker void addFakeDefUses(const Inst *Instr); 399*03ce13f7SAndroid Build Coastguard Worker 400*03ce13f7SAndroid Build Coastguard Worker /// Find (non-SSA) instructions where the Dest variable appears in some source 401*03ce13f7SAndroid Build Coastguard Worker /// operand, and set the IsDestRedefined flag. This keeps liveness analysis 402*03ce13f7SAndroid Build Coastguard Worker /// consistent. 403*03ce13f7SAndroid Build Coastguard Worker void markRedefinitions(); 404*03ce13f7SAndroid Build Coastguard Worker 405*03ce13f7SAndroid Build Coastguard Worker /// Make a pass over the Cfg to determine which variables need stack slots and 406*03ce13f7SAndroid Build Coastguard Worker /// place them in a sorted list (SortedSpilledVariables). Among those, vars, 407*03ce13f7SAndroid Build Coastguard Worker /// classify the spill variables as local to the basic block vs global 408*03ce13f7SAndroid Build Coastguard Worker /// (multi-block) in order to compute the parameters GlobalsSize and 409*03ce13f7SAndroid Build Coastguard Worker /// SpillAreaSizeBytes (represents locals or general vars if the coalescing of 410*03ce13f7SAndroid Build Coastguard Worker /// locals is disallowed) along with alignments required for variables in each 411*03ce13f7SAndroid Build Coastguard Worker /// area. We rely on accurate VMetadata in order to classify a variable as 412*03ce13f7SAndroid Build Coastguard Worker /// global vs local (otherwise the variable is conservatively global). The 413*03ce13f7SAndroid Build Coastguard Worker /// in-args should be initialized to 0. 414*03ce13f7SAndroid Build Coastguard Worker /// 415*03ce13f7SAndroid Build Coastguard Worker /// This is only a pre-pass and the actual stack slot assignment is handled 416*03ce13f7SAndroid Build Coastguard Worker /// separately. 417*03ce13f7SAndroid Build Coastguard Worker /// 418*03ce13f7SAndroid Build Coastguard Worker /// There may be target-specific Variable types, which will be handled by 419*03ce13f7SAndroid Build Coastguard Worker /// TargetVarHook. If the TargetVarHook returns true, then the variable is 420*03ce13f7SAndroid Build Coastguard Worker /// skipped and not considered with the rest of the spilled variables. 421*03ce13f7SAndroid Build Coastguard Worker void getVarStackSlotParams(VarList &SortedSpilledVariables, 422*03ce13f7SAndroid Build Coastguard Worker SmallBitVector &RegsUsed, size_t *GlobalsSize, 423*03ce13f7SAndroid Build Coastguard Worker size_t *SpillAreaSizeBytes, 424*03ce13f7SAndroid Build Coastguard Worker uint32_t *SpillAreaAlignmentBytes, 425*03ce13f7SAndroid Build Coastguard Worker uint32_t *LocalsSlotsAlignmentBytes, 426*03ce13f7SAndroid Build Coastguard Worker std::function<bool(Variable *)> TargetVarHook); 427*03ce13f7SAndroid Build Coastguard Worker 428*03ce13f7SAndroid Build Coastguard Worker /// Calculate the amount of padding needed to align the local and global areas 429*03ce13f7SAndroid Build Coastguard Worker /// to the required alignment. This assumes the globals/locals layout used by 430*03ce13f7SAndroid Build Coastguard Worker /// getVarStackSlotParams and assignVarStackSlots. 431*03ce13f7SAndroid Build Coastguard Worker void alignStackSpillAreas(uint32_t SpillAreaStartOffset, 432*03ce13f7SAndroid Build Coastguard Worker uint32_t SpillAreaAlignmentBytes, 433*03ce13f7SAndroid Build Coastguard Worker size_t GlobalsSize, 434*03ce13f7SAndroid Build Coastguard Worker uint32_t LocalsSlotsAlignmentBytes, 435*03ce13f7SAndroid Build Coastguard Worker uint32_t *SpillAreaPaddingBytes, 436*03ce13f7SAndroid Build Coastguard Worker uint32_t *LocalsSlotsPaddingBytes); 437*03ce13f7SAndroid Build Coastguard Worker 438*03ce13f7SAndroid Build Coastguard Worker /// Make a pass through the SortedSpilledVariables and actually assign stack 439*03ce13f7SAndroid Build Coastguard Worker /// slots. SpillAreaPaddingBytes takes into account stack alignment padding. 440*03ce13f7SAndroid Build Coastguard Worker /// The SpillArea starts after that amount of padding. This matches the scheme 441*03ce13f7SAndroid Build Coastguard Worker /// in getVarStackSlotParams, where there may be a separate multi-block global 442*03ce13f7SAndroid Build Coastguard Worker /// var spill area and a local var spill area. 443*03ce13f7SAndroid Build Coastguard Worker void assignVarStackSlots(VarList &SortedSpilledVariables, 444*03ce13f7SAndroid Build Coastguard Worker size_t SpillAreaPaddingBytes, 445*03ce13f7SAndroid Build Coastguard Worker size_t SpillAreaSizeBytes, 446*03ce13f7SAndroid Build Coastguard Worker size_t GlobalsAndSubsequentPaddingSize, 447*03ce13f7SAndroid Build Coastguard Worker bool UsesFramePointer); 448*03ce13f7SAndroid Build Coastguard Worker 449*03ce13f7SAndroid Build Coastguard Worker /// Sort the variables in Source based on required alignment. The variables 450*03ce13f7SAndroid Build Coastguard Worker /// with the largest alignment need are placed in the front of the Dest list. 451*03ce13f7SAndroid Build Coastguard Worker void sortVarsByAlignment(VarList &Dest, const VarList &Source) const; 452*03ce13f7SAndroid Build Coastguard Worker 453*03ce13f7SAndroid Build Coastguard Worker InstCall *makeHelperCall(RuntimeHelper FuncID, Variable *Dest, SizeT MaxSrcs); 454*03ce13f7SAndroid Build Coastguard Worker _set_dest_redefined()455*03ce13f7SAndroid Build Coastguard Worker void _set_dest_redefined() { Context.getLastInserted()->setDestRedefined(); } 456*03ce13f7SAndroid Build Coastguard Worker 457*03ce13f7SAndroid Build Coastguard Worker bool shouldOptimizeMemIntrins(); 458*03ce13f7SAndroid Build Coastguard Worker 459*03ce13f7SAndroid Build Coastguard Worker void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest, 460*03ce13f7SAndroid Build Coastguard Worker Operand *Src0, Operand *Src1); 461*03ce13f7SAndroid Build Coastguard Worker 462*03ce13f7SAndroid Build Coastguard Worker /// Generalizes scalarizeArithmetic to support other instruction types. 463*03ce13f7SAndroid Build Coastguard Worker /// 464*03ce13f7SAndroid Build Coastguard Worker /// insertScalarInstruction is a function-like object with signature 465*03ce13f7SAndroid Build Coastguard Worker /// (Variable *Dest, Variable *Src0, Variable *Src1) -> Instr *. 466*03ce13f7SAndroid Build Coastguard Worker template <typename... Operands, 467*03ce13f7SAndroid Build Coastguard Worker typename F = std::function<Inst *(Variable *, Operands *...)>> scalarizeInstruction(Variable * Dest,F insertScalarInstruction,Operands * ...Srcs)468*03ce13f7SAndroid Build Coastguard Worker void scalarizeInstruction(Variable *Dest, F insertScalarInstruction, 469*03ce13f7SAndroid Build Coastguard Worker Operands *...Srcs) { 470*03ce13f7SAndroid Build Coastguard Worker assert(GeneratingTargetHelpers && 471*03ce13f7SAndroid Build Coastguard Worker "scalarizeInstruction called during incorrect phase"); 472*03ce13f7SAndroid Build Coastguard Worker const Type DestTy = Dest->getType(); 473*03ce13f7SAndroid Build Coastguard Worker assert(isVectorType(DestTy)); 474*03ce13f7SAndroid Build Coastguard Worker const Type DestElementTy = typeElementType(DestTy); 475*03ce13f7SAndroid Build Coastguard Worker const SizeT NumElements = typeNumElements(DestTy); 476*03ce13f7SAndroid Build Coastguard Worker 477*03ce13f7SAndroid Build Coastguard Worker Variable *T = Func->makeVariable(DestTy); 478*03ce13f7SAndroid Build Coastguard Worker if (auto *VarVecOn32 = llvm::dyn_cast<VariableVecOn32>(T)) { 479*03ce13f7SAndroid Build Coastguard Worker VarVecOn32->initVecElement(Func); 480*03ce13f7SAndroid Build Coastguard Worker auto *Undef = ConstantUndef::create(Ctx, DestTy); 481*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstAssign>(T, Undef); 482*03ce13f7SAndroid Build Coastguard Worker } else { 483*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeDef>(T); 484*03ce13f7SAndroid Build Coastguard Worker } 485*03ce13f7SAndroid Build Coastguard Worker 486*03ce13f7SAndroid Build Coastguard Worker for (SizeT I = 0; I < NumElements; ++I) { 487*03ce13f7SAndroid Build Coastguard Worker auto *Index = Ctx->getConstantInt32(I); 488*03ce13f7SAndroid Build Coastguard Worker 489*03ce13f7SAndroid Build Coastguard Worker auto makeExtractThunk = [this, Index, NumElements](Operand *Src) { 490*03ce13f7SAndroid Build Coastguard Worker return [this, Index, NumElements, Src]() { 491*03ce13f7SAndroid Build Coastguard Worker (void)NumElements; 492*03ce13f7SAndroid Build Coastguard Worker assert(typeNumElements(Src->getType()) == NumElements); 493*03ce13f7SAndroid Build Coastguard Worker 494*03ce13f7SAndroid Build Coastguard Worker const auto ElementTy = typeElementType(Src->getType()); 495*03ce13f7SAndroid Build Coastguard Worker auto *Op = Func->makeVariable(ElementTy); 496*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstExtractElement>(Op, Src, Index); 497*03ce13f7SAndroid Build Coastguard Worker return Op; 498*03ce13f7SAndroid Build Coastguard Worker }; 499*03ce13f7SAndroid Build Coastguard Worker }; 500*03ce13f7SAndroid Build Coastguard Worker 501*03ce13f7SAndroid Build Coastguard Worker // Perform the operation as a scalar operation. 502*03ce13f7SAndroid Build Coastguard Worker auto *Res = Func->makeVariable(DestElementTy); 503*03ce13f7SAndroid Build Coastguard Worker auto *Arith = applyToThunkedArgs(insertScalarInstruction, Res, 504*03ce13f7SAndroid Build Coastguard Worker makeExtractThunk(Srcs)...); 505*03ce13f7SAndroid Build Coastguard Worker genTargetHelperCallFor(Arith); 506*03ce13f7SAndroid Build Coastguard Worker 507*03ce13f7SAndroid Build Coastguard Worker Variable *DestT = Func->makeVariable(DestTy); 508*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstInsertElement>(DestT, T, Res, Index); 509*03ce13f7SAndroid Build Coastguard Worker T = DestT; 510*03ce13f7SAndroid Build Coastguard Worker } 511*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstAssign>(Dest, T); 512*03ce13f7SAndroid Build Coastguard Worker } 513*03ce13f7SAndroid Build Coastguard Worker 514*03ce13f7SAndroid Build Coastguard Worker // applyToThunkedArgs is used by scalarizeInstruction. Ideally, we would just 515*03ce13f7SAndroid Build Coastguard Worker // call insertScalarInstruction(Res, Srcs...), but C++ does not specify 516*03ce13f7SAndroid Build Coastguard Worker // evaluation order which means this leads to an unpredictable final 517*03ce13f7SAndroid Build Coastguard Worker // output. Instead, we wrap each of the Srcs in a thunk and these 518*03ce13f7SAndroid Build Coastguard Worker // applyToThunkedArgs functions apply the thunks in a well defined order so we 519*03ce13f7SAndroid Build Coastguard Worker // still get well-defined output. applyToThunkedArgs(std::function<Inst * (Variable *,Variable *)> insertScalarInstruction,Variable * Res,std::function<Variable * ()> thunk0)520*03ce13f7SAndroid Build Coastguard Worker Inst *applyToThunkedArgs( 521*03ce13f7SAndroid Build Coastguard Worker std::function<Inst *(Variable *, Variable *)> insertScalarInstruction, 522*03ce13f7SAndroid Build Coastguard Worker Variable *Res, std::function<Variable *()> thunk0) { 523*03ce13f7SAndroid Build Coastguard Worker auto *Src0 = thunk0(); 524*03ce13f7SAndroid Build Coastguard Worker return insertScalarInstruction(Res, Src0); 525*03ce13f7SAndroid Build Coastguard Worker } 526*03ce13f7SAndroid Build Coastguard Worker 527*03ce13f7SAndroid Build Coastguard Worker Inst * applyToThunkedArgs(std::function<Inst * (Variable *,Variable *,Variable *)> insertScalarInstruction,Variable * Res,std::function<Variable * ()> thunk0,std::function<Variable * ()> thunk1)528*03ce13f7SAndroid Build Coastguard Worker applyToThunkedArgs(std::function<Inst *(Variable *, Variable *, Variable *)> 529*03ce13f7SAndroid Build Coastguard Worker insertScalarInstruction, 530*03ce13f7SAndroid Build Coastguard Worker Variable *Res, std::function<Variable *()> thunk0, 531*03ce13f7SAndroid Build Coastguard Worker std::function<Variable *()> thunk1) { 532*03ce13f7SAndroid Build Coastguard Worker auto *Src0 = thunk0(); 533*03ce13f7SAndroid Build Coastguard Worker auto *Src1 = thunk1(); 534*03ce13f7SAndroid Build Coastguard Worker return insertScalarInstruction(Res, Src0, Src1); 535*03ce13f7SAndroid Build Coastguard Worker } 536*03ce13f7SAndroid Build Coastguard Worker applyToThunkedArgs(std::function<Inst * (Variable *,Variable *,Variable *,Variable *)> insertScalarInstruction,Variable * Res,std::function<Variable * ()> thunk0,std::function<Variable * ()> thunk1,std::function<Variable * ()> thunk2)537*03ce13f7SAndroid Build Coastguard Worker Inst *applyToThunkedArgs( 538*03ce13f7SAndroid Build Coastguard Worker std::function<Inst *(Variable *, Variable *, Variable *, Variable *)> 539*03ce13f7SAndroid Build Coastguard Worker insertScalarInstruction, 540*03ce13f7SAndroid Build Coastguard Worker Variable *Res, std::function<Variable *()> thunk0, 541*03ce13f7SAndroid Build Coastguard Worker std::function<Variable *()> thunk1, std::function<Variable *()> thunk2) { 542*03ce13f7SAndroid Build Coastguard Worker auto *Src0 = thunk0(); 543*03ce13f7SAndroid Build Coastguard Worker auto *Src1 = thunk1(); 544*03ce13f7SAndroid Build Coastguard Worker auto *Src2 = thunk2(); 545*03ce13f7SAndroid Build Coastguard Worker return insertScalarInstruction(Res, Src0, Src1, Src2); 546*03ce13f7SAndroid Build Coastguard Worker } 547*03ce13f7SAndroid Build Coastguard Worker 548*03ce13f7SAndroid Build Coastguard Worker Cfg *Func; 549*03ce13f7SAndroid Build Coastguard Worker GlobalContext *Ctx; 550*03ce13f7SAndroid Build Coastguard Worker bool HasComputedFrame = false; 551*03ce13f7SAndroid Build Coastguard Worker bool CallsReturnsTwice = false; 552*03ce13f7SAndroid Build Coastguard Worker SizeT NextLabelNumber = 0; 553*03ce13f7SAndroid Build Coastguard Worker SizeT NextJumpTableNumber = 0; 554*03ce13f7SAndroid Build Coastguard Worker LoweringContext Context; 555*03ce13f7SAndroid Build Coastguard Worker }; 556*03ce13f7SAndroid Build Coastguard Worker 557*03ce13f7SAndroid Build Coastguard Worker /// TargetDataLowering is used for "lowering" data including initializers for 558*03ce13f7SAndroid Build Coastguard Worker /// global variables, and the internal constant pools. It is separated out from 559*03ce13f7SAndroid Build Coastguard Worker /// TargetLowering because it does not require a Cfg. 560*03ce13f7SAndroid Build Coastguard Worker class TargetDataLowering { 561*03ce13f7SAndroid Build Coastguard Worker TargetDataLowering() = delete; 562*03ce13f7SAndroid Build Coastguard Worker TargetDataLowering(const TargetDataLowering &) = delete; 563*03ce13f7SAndroid Build Coastguard Worker TargetDataLowering &operator=(const TargetDataLowering &) = delete; 564*03ce13f7SAndroid Build Coastguard Worker 565*03ce13f7SAndroid Build Coastguard Worker public: 566*03ce13f7SAndroid Build Coastguard Worker static std::unique_ptr<TargetDataLowering> createLowering(GlobalContext *Ctx); 567*03ce13f7SAndroid Build Coastguard Worker virtual ~TargetDataLowering(); 568*03ce13f7SAndroid Build Coastguard Worker 569*03ce13f7SAndroid Build Coastguard Worker virtual void lowerGlobals(const VariableDeclarationList &Vars, 570*03ce13f7SAndroid Build Coastguard Worker const std::string &SectionSuffix) = 0; 571*03ce13f7SAndroid Build Coastguard Worker virtual void lowerConstants() = 0; 572*03ce13f7SAndroid Build Coastguard Worker virtual void lowerJumpTables() = 0; emitTargetRODataSections()573*03ce13f7SAndroid Build Coastguard Worker virtual void emitTargetRODataSections() {} 574*03ce13f7SAndroid Build Coastguard Worker 575*03ce13f7SAndroid Build Coastguard Worker protected: 576*03ce13f7SAndroid Build Coastguard Worker void emitGlobal(const VariableDeclaration &Var, 577*03ce13f7SAndroid Build Coastguard Worker const std::string &SectionSuffix); 578*03ce13f7SAndroid Build Coastguard Worker 579*03ce13f7SAndroid Build Coastguard Worker /// For now, we assume .long is the right directive for emitting 4 byte emit 580*03ce13f7SAndroid Build Coastguard Worker /// global relocations. However, LLVM MIPS usually uses .4byte instead. 581*03ce13f7SAndroid Build Coastguard Worker /// Perhaps there is some difference when the location is unaligned. getEmit32Directive()582*03ce13f7SAndroid Build Coastguard Worker static const char *getEmit32Directive() { return ".long"; } 583*03ce13f7SAndroid Build Coastguard Worker TargetDataLowering(GlobalContext * Ctx)584*03ce13f7SAndroid Build Coastguard Worker explicit TargetDataLowering(GlobalContext *Ctx) : Ctx(Ctx) {} 585*03ce13f7SAndroid Build Coastguard Worker GlobalContext *Ctx; 586*03ce13f7SAndroid Build Coastguard Worker }; 587*03ce13f7SAndroid Build Coastguard Worker 588*03ce13f7SAndroid Build Coastguard Worker /// TargetHeaderLowering is used to "lower" the header of an output file. It 589*03ce13f7SAndroid Build Coastguard Worker /// writes out the target-specific header attributes. E.g., for ARM this writes 590*03ce13f7SAndroid Build Coastguard Worker /// out the build attributes (float ABI, etc.). 591*03ce13f7SAndroid Build Coastguard Worker class TargetHeaderLowering { 592*03ce13f7SAndroid Build Coastguard Worker TargetHeaderLowering() = delete; 593*03ce13f7SAndroid Build Coastguard Worker TargetHeaderLowering(const TargetHeaderLowering &) = delete; 594*03ce13f7SAndroid Build Coastguard Worker TargetHeaderLowering &operator=(const TargetHeaderLowering &) = delete; 595*03ce13f7SAndroid Build Coastguard Worker 596*03ce13f7SAndroid Build Coastguard Worker public: 597*03ce13f7SAndroid Build Coastguard Worker static std::unique_ptr<TargetHeaderLowering> 598*03ce13f7SAndroid Build Coastguard Worker createLowering(GlobalContext *Ctx); 599*03ce13f7SAndroid Build Coastguard Worker virtual ~TargetHeaderLowering(); 600*03ce13f7SAndroid Build Coastguard Worker lower()601*03ce13f7SAndroid Build Coastguard Worker virtual void lower() {} 602*03ce13f7SAndroid Build Coastguard Worker 603*03ce13f7SAndroid Build Coastguard Worker protected: TargetHeaderLowering(GlobalContext * Ctx)604*03ce13f7SAndroid Build Coastguard Worker explicit TargetHeaderLowering(GlobalContext *Ctx) : Ctx(Ctx) {} 605*03ce13f7SAndroid Build Coastguard Worker GlobalContext *Ctx; 606*03ce13f7SAndroid Build Coastguard Worker }; 607*03ce13f7SAndroid Build Coastguard Worker 608*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice 609*03ce13f7SAndroid Build Coastguard Worker 610*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICETARGETLOWERING_H 611