1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// 2 // 3 // The Subzero Code Generator 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// \brief Declares the Inst class and its target-independent subclasses. 12 /// 13 /// These represent the high-level Vanilla ICE instructions and map roughly 1:1 14 /// to LLVM instructions. 15 /// 16 //===----------------------------------------------------------------------===// 17 18 #ifndef SUBZERO_SRC_ICEINST_H 19 #define SUBZERO_SRC_ICEINST_H 20 21 #include "IceCfg.h" 22 #include "IceDefs.h" 23 #include "IceInst.def" 24 #include "IceIntrinsics.h" 25 #include "IceOperand.h" 26 #include "IceSwitchLowering.h" 27 #include "IceTypes.h" 28 29 // TODO: The Cfg structure, and instructions in particular, need to be 30 // validated for things like valid operand types, valid branch targets, proper 31 // ordering of Phi and non-Phi instructions, etc. Most of the validity checking 32 // will be done in the bitcode reader. We need a list of everything that should 33 // be validated, and tests for each. 34 35 namespace Ice { 36 37 /// Base instruction class for ICE. Inst has two subclasses: InstHighLevel and 38 /// InstTarget. High-level ICE instructions inherit from InstHighLevel, and 39 /// low-level (target-specific) ICE instructions inherit from InstTarget. 40 class Inst : public llvm::ilist_node<Inst> { 41 Inst() = delete; 42 Inst(const Inst &) = delete; 43 Inst &operator=(const Inst &) = delete; 44 45 public: 46 enum InstKind { 47 // Arbitrary (alphabetical) order, except put Unreachable first. 48 Unreachable, 49 Alloca, 50 Arithmetic, 51 Br, 52 Call, 53 Cast, 54 ExtractElement, 55 Fcmp, 56 Icmp, 57 Intrinsic, 58 InsertElement, 59 Load, 60 Phi, 61 Ret, 62 Select, 63 Store, 64 Switch, 65 Assign, // not part of LLVM/PNaCl bitcode 66 Breakpoint, // not part of LLVM/PNaCl bitcode 67 FakeDef, // not part of LLVM/PNaCl bitcode 68 FakeUse, // not part of LLVM/PNaCl bitcode 69 FakeKill, // not part of LLVM/PNaCl bitcode 70 JumpTable, // not part of LLVM/PNaCl bitcode 71 ShuffleVector, // not part of LLVM/PNaCl bitcode 72 // Anything >= Target is an InstTarget subclass. Note that the value-spaces 73 // are shared across targets. To avoid confusion over the definition of 74 // shared values, an object specific to one target should never be passed 75 // to a different target. 76 Target, 77 Target_Max = std::numeric_limits<uint8_t>::max(), 78 }; 79 static_assert(Target <= Target_Max, "Must not be above max."); getKind()80 InstKind getKind() const { return Kind; } 81 virtual const char *getInstName() const; 82 getNumber()83 InstNumberT getNumber() const { return Number; } 84 void renumber(Cfg *Func); 85 enum { 86 NumberDeleted = -1, 87 NumberSentinel = 0, 88 NumberInitial = 2, 89 NumberExtended = NumberInitial - 1 90 }; 91 isDeleted()92 bool isDeleted() const { return Deleted; } setDeleted()93 void setDeleted() { Deleted = true; } 94 void setDead(bool Value = true) { Dead = Value; } 95 void deleteIfDead(); 96 hasSideEffects()97 bool hasSideEffects() const { return HasSideEffects; } 98 isDestRedefined()99 bool isDestRedefined() const { return IsDestRedefined; } setDestRedefined()100 void setDestRedefined() { IsDestRedefined = true; } 101 getDest()102 Variable *getDest() const { return Dest; } 103 getSrcSize()104 SizeT getSrcSize() const { return Srcs.size(); } getSrc(SizeT I)105 Operand *getSrc(SizeT I) const { 106 assert(I < getSrcSize()); 107 return Srcs[I]; 108 } replaceSource(SizeT Index,Operand * Replacement)109 void replaceSource(SizeT Index, Operand *Replacement) { 110 assert(Index < getSrcSize()); 111 assert(!isDeleted()); 112 Srcs[Index] = Replacement; 113 } 114 // Instructions which load data take their address in Src[0], while 115 // store instructions use Src[1] for the address and Src[0] for the data. getLoadAddress()116 Operand *getLoadAddress() const { return getSrc(0); } getStoreAddress()117 Operand *getStoreAddress() const { return getSrc(1); } getData()118 Operand *getData() const { return getSrc(0); } 119 120 bool isLastUse(const Operand *Src) const; 121 void spliceLivenessInfo(Inst *OrigInst, Inst *SpliceAssn); 122 123 /// Returns a list of out-edges corresponding to a terminator instruction, 124 /// which is the last instruction of the block. The list must not contain 125 /// duplicates. getTerminatorEdges()126 virtual NodeList getTerminatorEdges() const { 127 // All valid terminator instructions override this method. For the default 128 // implementation, we assert in case some CfgNode is constructed without a 129 // terminator instruction at the end. 130 llvm_unreachable( 131 "getTerminatorEdges() called on a non-terminator instruction"); 132 return NodeList(); 133 } isUnconditionalBranch()134 virtual bool isUnconditionalBranch() const { return false; } 135 /// If the instruction is a branch-type instruction with OldNode as a target, 136 /// repoint it to NewNode and return true, otherwise return false. Repoint all 137 /// instances of OldNode as a target. repointEdges(CfgNode * OldNode,CfgNode * NewNode)138 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { 139 (void)OldNode; 140 (void)NewNode; 141 return false; 142 } 143 144 /// Returns true if the instruction is equivalent to a simple 145 /// "var_dest=var_src" assignment where the dest and src are both variables. isVarAssign()146 virtual bool isVarAssign() const { return false; } 147 148 /// Returns true if the instruction has a possible side effect of changing 149 /// memory, in which case a memory load should not be reordered with respect 150 /// to this instruction. It should really be pure virtual, but we can't 151 /// because of g++ and llvm::ilist<>, so we implement it as 152 /// report_fatal_error(). 153 virtual bool isMemoryWrite() const; 154 155 /// Returns true if the (target-specific) instruction represents an 156 /// intra-block label, i.e. branch target. This is meant primarily for 157 /// Cfg::splitLocalVars(). isLabel()158 virtual bool isLabel() const { return false; } 159 /// If the (target-specific) instruction represents an intra-block branch to 160 /// some Label instruction, return that Label branch target instruction; 161 /// otherwise return nullptr. getIntraBlockBranchTarget()162 virtual const Inst *getIntraBlockBranchTarget() const { return nullptr; } 163 164 void livenessLightweight(Cfg *Func, LivenessBV &Live); 165 /// Calculates liveness for this instruction. Returns true if this instruction 166 /// is (tentatively) still live and should be retained, and false if this 167 /// instruction is (tentatively) dead and should be deleted. The decision is 168 /// tentative until the liveness dataflow algorithm has converged, and then a 169 /// separate pass permanently deletes dead instructions. 170 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, 171 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); 172 173 /// Get the number of native instructions that this instruction ultimately 174 /// emits. By default, high-level instructions don't result in any native 175 /// instructions, and a target-specific instruction results in a single native 176 /// instruction. getEmitInstCount()177 virtual uint32_t getEmitInstCount() const { return 0; } 178 // TODO(stichnot): Change Inst back to abstract once the g++ build issue is 179 // fixed. llvm::ilist<Ice::Inst> doesn't work under g++ because the 180 // resize(size_t, Ice::Inst) method is incorrectly declared and thus doesn't 181 // allow the abstract class Ice::Inst. The method should be declared 182 // resize(size_t, const Ice::Inst &). virtual void emit(const Cfg *Func) 183 // const = 0; virtual void emitIAS(const Cfg *Func) const = 0; emit(const Cfg *)184 virtual void emit(const Cfg *) const { 185 llvm_unreachable("emit on abstract class"); 186 } emitIAS(const Cfg * Func)187 virtual void emitIAS(const Cfg *Func) const { emit(Func); } 188 virtual void dump(const Cfg *Func) const; 189 virtual void dumpExtras(const Cfg *Func) const; 190 void dumpDecorated(const Cfg *Func) const; 191 void emitSources(const Cfg *Func) const; 192 void dumpSources(const Cfg *Func) const; 193 void dumpDest(const Cfg *Func) const; isRedundantAssign()194 virtual bool isRedundantAssign() const { return false; } 195 196 virtual ~Inst() = default; replaceDest(Variable * Var)197 void replaceDest(Variable *Var) { Dest = Var; } 198 delete(void * Ptr,std::size_t Size)199 void operator delete(void *Ptr, std::size_t Size) { 200 assert(CfgAllocatorTraits::current() != nullptr); 201 CfgAllocatorTraits::current()->Deallocate(Ptr, Size); 202 llvm::report_fatal_error("Inst unexpectedly deleted"); 203 } 204 getExternalData()205 inline void *getExternalData() const { return externalData; } setExternalData(void * data)206 inline void setExternalData(void *data) { externalData = data; } 207 208 protected: 209 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); addSource(Operand * Src)210 void addSource(Operand *Src) { 211 assert(Src); 212 Srcs.push_back(Src); 213 } setLastUse(SizeT VarIndex)214 void setLastUse(SizeT VarIndex) { 215 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) 216 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); 217 } resetLastUses()218 void resetLastUses() { LiveRangesEnded = 0; } 219 /// The destroy() method lets the instruction cleanly release any memory that 220 /// was allocated via the Cfg's allocator. destroy(Cfg *)221 virtual void destroy(Cfg *) {} 222 223 const InstKind Kind; 224 /// Number is the instruction number for describing live ranges. 225 InstNumberT Number; 226 /// Deleted means irrevocably deleted. 227 bool Deleted = false; 228 /// Dead means one of two things depending on context: (1) pending deletion 229 /// after liveness analysis converges, or (2) marked for deletion during 230 /// lowering due to a folded bool operation. 231 bool Dead = false; 232 /// HasSideEffects means the instruction is something like a function call or 233 /// a volatile load that can't be removed even if its Dest variable is not 234 /// live. 235 bool HasSideEffects = false; 236 /// IsDestRedefined indicates that this instruction is not the first 237 /// definition of Dest in the basic block. The effect is that liveness 238 /// analysis shouldn't consider this instruction to be the start of Dest's 239 /// live range; rather, there is some other instruction earlier in the basic 240 /// block with the same Dest. This is maintained because liveness analysis 241 /// has an invariant (primarily for performance reasons) that any Variable's 242 /// live range recorded in a basic block has at most one start and at most one 243 /// end. 244 bool IsDestRedefined = false; 245 /// External data can be set by an optimizer to compute and retain any 246 /// information related to the current instruction. All the memory used to 247 /// store this information must be managed by the optimizer. 248 void *externalData = nullptr; 249 250 Variable *Dest; 251 const SizeT MaxSrcs; // only used for assert 252 253 CfgVector<Operand *> Srcs; 254 255 /// LiveRangesEnded marks which Variables' live ranges end in this 256 /// instruction. An instruction can have an arbitrary number of source 257 /// operands (e.g. a call instruction), and each source operand can contain 0 258 /// or 1 Variable (and target-specific operands could contain more than 1 259 /// Variable). All the variables in an instruction are conceptually flattened 260 /// and each variable is mapped to one bit position of the LiveRangesEnded bit 261 /// vector. Only the first CHAR_BIT * sizeof(LREndedBits) variables are 262 /// tracked this way. 263 using LREndedBits = uint32_t; // only first 32 src operands tracked, sorry 264 LREndedBits LiveRangesEnded; 265 }; 266 267 class InstHighLevel : public Inst { 268 InstHighLevel() = delete; 269 InstHighLevel(const InstHighLevel &) = delete; 270 InstHighLevel &operator=(const InstHighLevel &) = delete; 271 272 protected: InstHighLevel(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)273 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 274 : Inst(Func, Kind, MaxSrcs, Dest) {} emit(const Cfg *)275 void emit(const Cfg * /*Func*/) const override { 276 llvm_unreachable("emit() called on a non-lowered instruction"); 277 } emitIAS(const Cfg *)278 void emitIAS(const Cfg * /*Func*/) const override { 279 llvm_unreachable("emitIAS() called on a non-lowered instruction"); 280 } 281 }; 282 283 /// Alloca instruction. This captures the size in bytes as getSrc(0), and the 284 /// required alignment in bytes. The alignment must be either 0 (no alignment 285 /// required) or a power of 2. 286 class InstAlloca : public InstHighLevel { 287 InstAlloca() = delete; 288 InstAlloca(const InstAlloca &) = delete; 289 InstAlloca &operator=(const InstAlloca &) = delete; 290 291 public: create(Cfg * Func,Variable * Dest,Operand * ByteCount,uint32_t AlignInBytes)292 static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount, 293 uint32_t AlignInBytes) { 294 return new (Func->allocate<InstAlloca>()) 295 InstAlloca(Func, Dest, ByteCount, AlignInBytes); 296 } getAlignInBytes()297 uint32_t getAlignInBytes() const { return AlignInBytes; } getSizeInBytes()298 Operand *getSizeInBytes() const { return getSrc(0); } getKnownFrameOffset()299 bool getKnownFrameOffset() const { return KnownFrameOffset; } setKnownFrameOffset()300 void setKnownFrameOffset() { KnownFrameOffset = true; } isMemoryWrite()301 bool isMemoryWrite() const override { return false; } 302 void dump(const Cfg *Func) const override; classof(const Inst * Instr)303 static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } 304 305 private: 306 InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount, 307 uint32_t AlignInBytes); 308 309 const uint32_t AlignInBytes; 310 bool KnownFrameOffset = false; 311 }; 312 313 /// Binary arithmetic instruction. The source operands are captured in getSrc(0) 314 /// and getSrc(1). 315 class InstArithmetic : public InstHighLevel { 316 InstArithmetic() = delete; 317 InstArithmetic(const InstArithmetic &) = delete; 318 InstArithmetic &operator=(const InstArithmetic &) = delete; 319 320 public: 321 enum OpKind { 322 #define X(tag, str, commutative) tag, 323 ICEINSTARITHMETIC_TABLE 324 #undef X 325 _num 326 }; 327 create(Cfg * Func,OpKind Op,Variable * Dest,Operand * Source1,Operand * Source2)328 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, 329 Operand *Source1, Operand *Source2) { 330 return new (Func->allocate<InstArithmetic>()) 331 InstArithmetic(Func, Op, Dest, Source1, Source2); 332 } getOp()333 OpKind getOp() const { return Op; } 334 335 virtual const char *getInstName() const override; 336 337 static const char *getOpName(OpKind Op); 338 bool isCommutative() const; isMemoryWrite()339 bool isMemoryWrite() const override { return false; } 340 void dump(const Cfg *Func) const override; classof(const Inst * Instr)341 static bool classof(const Inst *Instr) { 342 return Instr->getKind() == Arithmetic; 343 } 344 345 private: 346 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, 347 Operand *Source2); 348 349 const OpKind Op; 350 }; 351 352 /// Assignment instruction. The source operand is captured in getSrc(0). This is 353 /// not part of the LLVM bitcode, but is a useful abstraction for some of the 354 /// lowering. E.g., if Phi instruction lowering happens before target lowering, 355 /// or for representing an Inttoptr instruction, or as an intermediate step for 356 /// lowering a Load instruction. 357 class InstAssign : public InstHighLevel { 358 InstAssign() = delete; 359 InstAssign(const InstAssign &) = delete; 360 InstAssign &operator=(const InstAssign &) = delete; 361 362 public: create(Cfg * Func,Variable * Dest,Operand * Source)363 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { 364 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); 365 } 366 bool isVarAssign() const override; isMemoryWrite()367 bool isMemoryWrite() const override { return false; } 368 void dump(const Cfg *Func) const override; classof(const Inst * Instr)369 static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } 370 371 private: 372 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); 373 }; 374 375 /// Branch instruction. This represents both conditional and unconditional 376 /// branches. 377 class InstBr : public InstHighLevel { 378 InstBr() = delete; 379 InstBr(const InstBr &) = delete; 380 InstBr &operator=(const InstBr &) = delete; 381 382 public: 383 /// Create a conditional branch. If TargetTrue==TargetFalse, it is optimized 384 /// to an unconditional branch. create(Cfg * Func,Operand * Source,CfgNode * TargetTrue,CfgNode * TargetFalse)385 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, 386 CfgNode *TargetFalse) { 387 return new (Func->allocate<InstBr>()) 388 InstBr(Func, Source, TargetTrue, TargetFalse); 389 } 390 /// Create an unconditional branch. create(Cfg * Func,CfgNode * Target)391 static InstBr *create(Cfg *Func, CfgNode *Target) { 392 return new (Func->allocate<InstBr>()) InstBr(Func, Target); 393 } isUnconditional()394 bool isUnconditional() const { return getTargetTrue() == nullptr; } getCondition()395 Operand *getCondition() const { 396 assert(!isUnconditional()); 397 return getSrc(0); 398 } getTargetTrue()399 CfgNode *getTargetTrue() const { return TargetTrue; } getTargetFalse()400 CfgNode *getTargetFalse() const { return TargetFalse; } getTargetUnconditional()401 CfgNode *getTargetUnconditional() const { 402 assert(isUnconditional()); 403 return getTargetFalse(); 404 } 405 NodeList getTerminatorEdges() const override; isUnconditionalBranch()406 bool isUnconditionalBranch() const override { return isUnconditional(); } 407 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; isMemoryWrite()408 bool isMemoryWrite() const override { return false; } 409 void dump(const Cfg *Func) const override; classof(const Inst * Instr)410 static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } 411 412 private: 413 /// Conditional branch 414 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); 415 /// Unconditional branch 416 InstBr(Cfg *Func, CfgNode *Target); 417 418 CfgNode *TargetFalse; /// Doubles as unconditional branch target 419 CfgNode *TargetTrue; /// nullptr if unconditional branch 420 }; 421 422 /// Call instruction. The call target is captured as getSrc(0), and arg I is 423 /// captured as getSrc(I+1). 424 class InstCall : public InstHighLevel { 425 InstCall() = delete; 426 InstCall(const InstCall &) = delete; 427 InstCall &operator=(const InstCall &) = delete; 428 429 public: 430 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 431 Operand *CallTarget, bool HasTailCall, 432 bool IsTargetHelperCall = false, 433 bool IsVariadic = false) { 434 /// Set HasSideEffects to true so that the call instruction can't be 435 /// dead-code eliminated. 436 constexpr bool HasSideEffects = true; 437 constexpr InstKind Kind = Inst::Call; 438 return new (Func->allocate<InstCall>()) 439 InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall, 440 IsTargetHelperCall, IsVariadic, HasSideEffects, Kind); 441 } addArg(Operand * Arg)442 void addArg(Operand *Arg) { addSource(Arg); } getCallTarget()443 Operand *getCallTarget() const { return getSrc(0); } getArg(SizeT I)444 Operand *getArg(SizeT I) const { return getSrc(I + 1); } getNumArgs()445 SizeT getNumArgs() const { return getSrcSize() - 1; } isTailcall()446 bool isTailcall() const { return HasTailCall; } isTargetHelperCall()447 bool isTargetHelperCall() const { return IsTargetHelperCall; } isVariadic()448 bool isVariadic() const { return IsVariadic; } isMemoryWrite()449 bool isMemoryWrite() const override { return true; } 450 void dump(const Cfg *Func) const override; classof(const Inst * Instr)451 static bool classof(const Inst *Instr) { return Instr->getKind() == Call; } 452 Type getReturnType() const; 453 454 protected: InstCall(Cfg * Func,SizeT NumArgs,Variable * Dest,Operand * CallTarget,bool HasTailCall,bool IsTargetHelperCall,bool IsVariadic,bool HasSideEff,InstKind Kind)455 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, 456 bool HasTailCall, bool IsTargetHelperCall, bool IsVariadic, 457 bool HasSideEff, InstKind Kind) 458 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall), 459 IsTargetHelperCall(IsTargetHelperCall), IsVariadic(IsVariadic) { 460 HasSideEffects = HasSideEff; 461 addSource(CallTarget); 462 } 463 464 private: 465 const bool HasTailCall; 466 const bool IsTargetHelperCall; 467 const bool IsVariadic; 468 }; 469 470 /// Cast instruction (a.k.a. conversion operation). 471 class InstCast : public InstHighLevel { 472 InstCast() = delete; 473 InstCast(const InstCast &) = delete; 474 InstCast &operator=(const InstCast &) = delete; 475 476 public: 477 enum OpKind { 478 #define X(tag, str) tag, 479 ICEINSTCAST_TABLE 480 #undef X 481 _num 482 }; 483 484 static const char *getCastName(OpKind Kind); 485 create(Cfg * Func,OpKind CastKind,Variable * Dest,Operand * Source)486 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, 487 Operand *Source) { 488 return new (Func->allocate<InstCast>()) 489 InstCast(Func, CastKind, Dest, Source); 490 } getCastKind()491 OpKind getCastKind() const { return CastKind; } isMemoryWrite()492 bool isMemoryWrite() const override { return false; } 493 void dump(const Cfg *Func) const override; classof(const Inst * Instr)494 static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } 495 496 private: 497 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); 498 499 const OpKind CastKind; 500 }; 501 502 /// ExtractElement instruction. 503 class InstExtractElement : public InstHighLevel { 504 InstExtractElement() = delete; 505 InstExtractElement(const InstExtractElement &) = delete; 506 InstExtractElement &operator=(const InstExtractElement &) = delete; 507 508 public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2)509 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 510 Operand *Source2) { 511 return new (Func->allocate<InstExtractElement>()) 512 InstExtractElement(Func, Dest, Source1, Source2); 513 } 514 isMemoryWrite()515 bool isMemoryWrite() const override { return false; } 516 void dump(const Cfg *Func) const override; classof(const Inst * Instr)517 static bool classof(const Inst *Instr) { 518 return Instr->getKind() == ExtractElement; 519 } 520 521 private: 522 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, 523 Operand *Source2); 524 }; 525 526 /// Floating-point comparison instruction. The source operands are captured in 527 /// getSrc(0) and getSrc(1). 528 class InstFcmp : public InstHighLevel { 529 InstFcmp() = delete; 530 InstFcmp(const InstFcmp &) = delete; 531 InstFcmp &operator=(const InstFcmp &) = delete; 532 533 public: 534 enum FCond { 535 #define X(tag, str) tag, 536 ICEINSTFCMP_TABLE 537 #undef X 538 _num 539 }; 540 create(Cfg * Func,FCond Condition,Variable * Dest,Operand * Source1,Operand * Source2)541 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, 542 Operand *Source1, Operand *Source2) { 543 return new (Func->allocate<InstFcmp>()) 544 InstFcmp(Func, Condition, Dest, Source1, Source2); 545 } getCondition()546 FCond getCondition() const { return Condition; } isMemoryWrite()547 bool isMemoryWrite() const override { return false; } 548 void dump(const Cfg *Func) const override; classof(const Inst * Instr)549 static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } 550 551 private: 552 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, 553 Operand *Source2); 554 555 const FCond Condition; 556 }; 557 558 /// Integer comparison instruction. The source operands are captured in 559 /// getSrc(0) and getSrc(1). 560 class InstIcmp : public InstHighLevel { 561 InstIcmp() = delete; 562 InstIcmp(const InstIcmp &) = delete; 563 InstIcmp &operator=(const InstIcmp &) = delete; 564 565 public: 566 enum ICond { 567 #define X(tag, inverse, str) tag, 568 ICEINSTICMP_TABLE 569 #undef X 570 _num 571 }; 572 create(Cfg * Func,ICond Condition,Variable * Dest,Operand * Source1,Operand * Source2)573 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, 574 Operand *Source1, Operand *Source2) { 575 return new (Func->allocate<InstIcmp>()) 576 InstIcmp(Func, Condition, Dest, Source1, Source2); 577 } getCondition()578 ICond getCondition() const { return Condition; } 579 void reverseConditionAndOperands(); isMemoryWrite()580 bool isMemoryWrite() const override { return false; } 581 void dump(const Cfg *Func) const override; classof(const Inst * Instr)582 static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } 583 584 private: 585 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, 586 Operand *Source2); 587 588 ICond Condition; 589 }; 590 591 /// InsertElement instruction. 592 class InstInsertElement : public InstHighLevel { 593 InstInsertElement() = delete; 594 InstInsertElement(const InstInsertElement &) = delete; 595 InstInsertElement &operator=(const InstInsertElement &) = delete; 596 597 public: create(Cfg * Func,Variable * Dest,Operand * Source1,Operand * Source2,Operand * Source3)598 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 599 Operand *Source2, Operand *Source3) { 600 return new (Func->allocate<InstInsertElement>()) 601 InstInsertElement(Func, Dest, Source1, Source2, Source3); 602 } 603 isMemoryWrite()604 bool isMemoryWrite() const override { return false; } 605 void dump(const Cfg *Func) const override; classof(const Inst * Instr)606 static bool classof(const Inst *Instr) { 607 return Instr->getKind() == InsertElement; 608 } 609 610 private: 611 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, 612 Operand *Source2, Operand *Source3); 613 }; 614 615 /// An intrinsic operation, representing either a sequence of instructions, 616 /// or a single instruction. Availability of intrinsics is target-specific. 617 class InstIntrinsic : public InstHighLevel { 618 InstIntrinsic() = delete; 619 InstIntrinsic(const InstIntrinsic &) = delete; 620 InstIntrinsic &operator=(const InstIntrinsic &) = delete; 621 622 public: create(Cfg * Func,SizeT NumArgs,Variable * Dest,const Intrinsics::IntrinsicInfo & Info)623 static InstIntrinsic *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 624 const Intrinsics::IntrinsicInfo &Info) { 625 return new (Func->allocate<InstIntrinsic>()) 626 InstIntrinsic(Func, NumArgs, Dest, Info); 627 } addArg(Operand * Arg)628 void addArg(Operand *Arg) { addSource(Arg); } getArg(SizeT I)629 Operand *getArg(SizeT I) const { return getSrc(I); } getNumArgs()630 SizeT getNumArgs() const { return getSrcSize(); } classof(const Inst * Instr)631 static bool classof(const Inst *Instr) { 632 return Instr->getKind() == Intrinsic; 633 } 634 getIntrinsicInfo()635 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } getIntrinsicID()636 Intrinsics::IntrinsicID getIntrinsicID() const { return Info.ID; } isMemoryWrite()637 bool isMemoryWrite() const override { 638 return getIntrinsicInfo().IsMemoryWrite; 639 } 640 641 private: InstIntrinsic(Cfg * Func,SizeT NumArgs,Variable * Dest,const Intrinsics::IntrinsicInfo & Info)642 InstIntrinsic(Cfg *Func, SizeT NumArgs, Variable *Dest, 643 const Intrinsics::IntrinsicInfo &Info) 644 : InstHighLevel(Func, Inst::Intrinsic, NumArgs, Dest), Info(Info) {} 645 646 const Intrinsics::IntrinsicInfo Info; 647 }; 648 649 /// Load instruction. The source address is captured in getSrc(0). 650 class InstLoad : public InstHighLevel { 651 InstLoad() = delete; 652 InstLoad(const InstLoad &) = delete; 653 InstLoad &operator=(const InstLoad &) = delete; 654 655 public: 656 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, 657 uint32_t Align = 1) { 658 // TODO(kschimpf) Stop ignoring alignment specification. 659 (void)Align; 660 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); 661 } isMemoryWrite()662 bool isMemoryWrite() const override { return false; } 663 void dump(const Cfg *Func) const override; classof(const Inst * Instr)664 static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } 665 666 private: 667 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); 668 }; 669 670 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi 671 /// source operand is getSrc(I). 672 class InstPhi : public InstHighLevel { 673 InstPhi() = delete; 674 InstPhi(const InstPhi &) = delete; 675 InstPhi &operator=(const InstPhi &) = delete; 676 677 public: create(Cfg * Func,SizeT MaxSrcs,Variable * Dest)678 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { 679 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); 680 } 681 void addArgument(Operand *Source, CfgNode *Label); 682 Operand *getOperandForTarget(CfgNode *Target) const; 683 void clearOperandForTarget(CfgNode *Target); getLabel(SizeT Index)684 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } setLabel(SizeT Index,CfgNode * Label)685 void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; } 686 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 687 Liveness *Liveness); 688 Inst *lower(Cfg *Func); isMemoryWrite()689 bool isMemoryWrite() const override { return false; } 690 void dump(const Cfg *Func) const override; classof(const Inst * Instr)691 static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } 692 693 private: 694 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); destroy(Cfg * Func)695 void destroy(Cfg *Func) override { Inst::destroy(Func); } 696 697 /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode, 698 /// but the Phi instruction is created before InEdges[] is available, so it's 699 /// more complicated to share the list. 700 CfgVector<CfgNode *> Labels; 701 }; 702 703 /// Ret instruction. The return value is captured in getSrc(0), but if there is 704 /// no return value (void-type function), then getSrcSize()==0 and 705 /// hasRetValue()==false. 706 class InstRet : public InstHighLevel { 707 InstRet() = delete; 708 InstRet(const InstRet &) = delete; 709 InstRet &operator=(const InstRet &) = delete; 710 711 public: 712 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { 713 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); 714 } hasRetValue()715 bool hasRetValue() const { return getSrcSize(); } getRetValue()716 Operand *getRetValue() const { 717 assert(hasRetValue()); 718 return getSrc(0); 719 } getTerminatorEdges()720 NodeList getTerminatorEdges() const override { return NodeList(); } isMemoryWrite()721 bool isMemoryWrite() const override { return false; } 722 void dump(const Cfg *Func) const override; classof(const Inst * Instr)723 static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } 724 725 private: 726 InstRet(Cfg *Func, Operand *RetValue); 727 }; 728 729 /// Select instruction. The condition, true, and false operands are captured. 730 class InstSelect : public InstHighLevel { 731 InstSelect() = delete; 732 InstSelect(const InstSelect &) = delete; 733 InstSelect &operator=(const InstSelect &) = delete; 734 735 public: create(Cfg * Func,Variable * Dest,Operand * Condition,Operand * SourceTrue,Operand * SourceFalse)736 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, 737 Operand *SourceTrue, Operand *SourceFalse) { 738 return new (Func->allocate<InstSelect>()) 739 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); 740 } getCondition()741 Operand *getCondition() const { return getSrc(0); } getTrueOperand()742 Operand *getTrueOperand() const { return getSrc(1); } getFalseOperand()743 Operand *getFalseOperand() const { return getSrc(2); } isMemoryWrite()744 bool isMemoryWrite() const override { return false; } 745 void dump(const Cfg *Func) const override; classof(const Inst * Instr)746 static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } 747 748 private: 749 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, 750 Operand *Source2); 751 }; 752 753 /// Store instruction. The address operand is captured, along with the data 754 /// operand to be stored into the address. 755 class InstStore : public InstHighLevel { 756 InstStore() = delete; 757 InstStore(const InstStore &) = delete; 758 InstStore &operator=(const InstStore &) = delete; 759 760 public: 761 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, 762 uint32_t Align = 1) { 763 // TODO(kschimpf) Stop ignoring alignment specification. 764 (void)Align; 765 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); 766 } 767 Variable *getRmwBeacon() const; 768 void setRmwBeacon(Variable *Beacon); isMemoryWrite()769 bool isMemoryWrite() const override { return true; } 770 void dump(const Cfg *Func) const override; classof(const Inst * Instr)771 static bool classof(const Inst *Instr) { return Instr->getKind() == Store; } 772 773 private: 774 InstStore(Cfg *Func, Operand *Data, Operand *Addr); 775 }; 776 777 /// Switch instruction. The single source operand is captured as getSrc(0). 778 class InstSwitch : public InstHighLevel { 779 InstSwitch() = delete; 780 InstSwitch(const InstSwitch &) = delete; 781 InstSwitch &operator=(const InstSwitch &) = delete; 782 783 public: create(Cfg * Func,SizeT NumCases,Operand * Source,CfgNode * LabelDefault)784 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, 785 CfgNode *LabelDefault) { 786 return new (Func->allocate<InstSwitch>()) 787 InstSwitch(Func, NumCases, Source, LabelDefault); 788 } getComparison()789 Operand *getComparison() const { return getSrc(0); } getLabelDefault()790 CfgNode *getLabelDefault() const { return LabelDefault; } getNumCases()791 SizeT getNumCases() const { return NumCases; } getValue(SizeT I)792 uint64_t getValue(SizeT I) const { 793 assert(I < NumCases); 794 return Values[I]; 795 } getLabel(SizeT I)796 CfgNode *getLabel(SizeT I) const { 797 assert(I < NumCases); 798 return Labels[I]; 799 } 800 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); 801 NodeList getTerminatorEdges() const override; 802 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; isMemoryWrite()803 bool isMemoryWrite() const override { return false; } 804 void dump(const Cfg *Func) const override; classof(const Inst * Instr)805 static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } 806 807 private: 808 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); destroy(Cfg * Func)809 void destroy(Cfg *Func) override { 810 Func->deallocateArrayOf<uint64_t>(Values); 811 Func->deallocateArrayOf<CfgNode *>(Labels); 812 Inst::destroy(Func); 813 } 814 815 CfgNode *LabelDefault; 816 SizeT NumCases; /// not including the default case 817 uint64_t *Values; /// size is NumCases 818 CfgNode **Labels; /// size is NumCases 819 }; 820 821 /// Unreachable instruction. This is a terminator instruction with no operands. 822 class InstUnreachable : public InstHighLevel { 823 InstUnreachable() = delete; 824 InstUnreachable(const InstUnreachable &) = delete; 825 InstUnreachable &operator=(const InstUnreachable &) = delete; 826 827 public: create(Cfg * Func)828 static InstUnreachable *create(Cfg *Func) { 829 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); 830 } getTerminatorEdges()831 NodeList getTerminatorEdges() const override { return NodeList(); } isMemoryWrite()832 bool isMemoryWrite() const override { return false; } 833 void dump(const Cfg *Func) const override; classof(const Inst * Instr)834 static bool classof(const Inst *Instr) { 835 return Instr->getKind() == Unreachable; 836 } 837 838 private: 839 explicit InstUnreachable(Cfg *Func); 840 }; 841 842 /// FakeDef instruction. This creates a fake definition of a variable, which is 843 /// how we represent the case when an instruction produces multiple results. 844 /// This doesn't happen with high-level ICE instructions, but might with lowered 845 /// instructions. For example, this would be a way to represent condition flags 846 /// being modified by an instruction. 847 /// 848 /// It's generally useful to set the optional source operand to be the dest 849 /// variable of the instruction that actually produces the FakeDef dest. 850 /// Otherwise, the original instruction could be dead-code eliminated if its 851 /// dest operand is unused, and therefore the FakeDef dest wouldn't be properly 852 /// initialized. 853 class InstFakeDef : public InstHighLevel { 854 InstFakeDef() = delete; 855 InstFakeDef(const InstFakeDef &) = delete; 856 InstFakeDef &operator=(const InstFakeDef &) = delete; 857 858 public: 859 static InstFakeDef *create(Cfg *Func, Variable *Dest, 860 Variable *Src = nullptr) { 861 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); 862 } 863 void emit(const Cfg *Func) const override; emitIAS(const Cfg *)864 void emitIAS(const Cfg * /* Func */) const override {} isMemoryWrite()865 bool isMemoryWrite() const override { return false; } 866 void dump(const Cfg *Func) const override; classof(const Inst * Instr)867 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } 868 869 private: 870 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); 871 }; 872 873 /// FakeUse instruction. This creates a fake use of a variable, to keep the 874 /// instruction that produces that variable from being dead-code eliminated. 875 /// This is useful in a variety of lowering situations. The FakeUse instruction 876 /// has no dest, so it can itself never be dead-code eliminated. A weight can 877 /// be provided to provide extra bias to the register allocator - for simplicity 878 /// of implementation, weight=N is handled by holding N copies of the variable 879 /// as source operands. 880 class InstFakeUse : public InstHighLevel { 881 InstFakeUse() = delete; 882 InstFakeUse(const InstFakeUse &) = delete; 883 InstFakeUse &operator=(const InstFakeUse &) = delete; 884 885 public: 886 static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) { 887 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight); 888 } 889 void emit(const Cfg *Func) const override; emitIAS(const Cfg *)890 void emitIAS(const Cfg * /* Func */) const override {} isMemoryWrite()891 bool isMemoryWrite() const override { return false; } 892 void dump(const Cfg *Func) const override; classof(const Inst * Instr)893 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } 894 895 private: 896 InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight); 897 }; 898 899 /// FakeKill instruction. This "kills" a set of variables by modeling a trivial 900 /// live range at this instruction for each (implicit) variable. The primary use 901 /// is to indicate that scratch registers are killed after a call, so that the 902 /// register allocator won't assign a scratch register to a variable whose live 903 /// range spans a call. 904 /// 905 /// The FakeKill instruction also holds a pointer to the instruction that kills 906 /// the set of variables, so that if that linked instruction gets dead-code 907 /// eliminated, the FakeKill instruction will as well. 908 class InstFakeKill : public InstHighLevel { 909 InstFakeKill() = delete; 910 InstFakeKill(const InstFakeKill &) = delete; 911 InstFakeKill &operator=(const InstFakeKill &) = delete; 912 913 public: create(Cfg * Func,const Inst * Linked)914 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { 915 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); 916 } getLinked()917 const Inst *getLinked() const { return Linked; } 918 void emit(const Cfg *Func) const override; emitIAS(const Cfg *)919 void emitIAS(const Cfg * /* Func */) const override {} isMemoryWrite()920 bool isMemoryWrite() const override { return false; } 921 void dump(const Cfg *Func) const override; classof(const Inst * Instr)922 static bool classof(const Inst *Instr) { 923 return Instr->getKind() == FakeKill; 924 } 925 926 private: 927 InstFakeKill(Cfg *Func, const Inst *Linked); 928 929 /// This instruction is ignored if Linked->isDeleted() is true. 930 const Inst *Linked; 931 }; 932 933 /// ShuffleVector instruction. This represents a shuffle operation on vector 934 /// types. This instruction is not part of the PNaCl bitcode: it is generated 935 /// by Subzero when it matches the pattern used by pnacl-clang when compiling 936 /// to bitcode. 937 class InstShuffleVector : public InstHighLevel { 938 InstShuffleVector() = delete; 939 InstShuffleVector(const InstShuffleVector &) = delete; 940 InstShuffleVector &operator=(const InstShuffleVector &) = delete; 941 942 public: create(Cfg * Func,Variable * Dest,Operand * Src0,Operand * Src1)943 static InstShuffleVector *create(Cfg *Func, Variable *Dest, Operand *Src0, 944 Operand *Src1) { 945 return new (Func->allocate<InstShuffleVector>()) 946 InstShuffleVector(Func, Dest, Src0, Src1); 947 } 948 getNumIndexes()949 SizeT getNumIndexes() const { return NumIndexes; } 950 addIndex(ConstantInteger32 * Index)951 void addIndex(ConstantInteger32 *Index) { 952 assert(CurrentIndex < NumIndexes); 953 Indexes[CurrentIndex++] = Index; 954 } 955 getIndex(SizeT Pos)956 ConstantInteger32 *getIndex(SizeT Pos) const { 957 assert(Pos < NumIndexes); 958 return Indexes[Pos]; 959 } 960 getIndexValue(SizeT Pos)961 int32_t getIndexValue(SizeT Pos) const { return getIndex(Pos)->getValue(); } 962 indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3)963 bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3) const { 964 static constexpr SizeT ExpectedNumElements = 4; 965 assert(ExpectedNumElements == getNumIndexes()); 966 (void)ExpectedNumElements; 967 968 return getIndexValue(0) == i0 && getIndexValue(1) == i1 && 969 getIndexValue(2) == i2 && getIndexValue(3) == i3; 970 } 971 indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3,int32_t i4,int32_t i5,int32_t i6,int32_t i7)972 bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4, 973 int32_t i5, int32_t i6, int32_t i7) const { 974 static constexpr SizeT ExpectedNumElements = 8; 975 assert(ExpectedNumElements == getNumIndexes()); 976 (void)ExpectedNumElements; 977 978 return getIndexValue(0) == i0 && getIndexValue(1) == i1 && 979 getIndexValue(2) == i2 && getIndexValue(3) == i3 && 980 getIndexValue(4) == i4 && getIndexValue(5) == i5 && 981 getIndexValue(6) == i6 && getIndexValue(7) == i7; 982 } 983 indexesAre(int32_t i0,int32_t i1,int32_t i2,int32_t i3,int32_t i4,int32_t i5,int32_t i6,int32_t i7,int32_t i8,int32_t i9,int32_t i10,int32_t i11,int32_t i12,int32_t i13,int32_t i14,int32_t i15)984 bool indexesAre(int32_t i0, int32_t i1, int32_t i2, int32_t i3, int32_t i4, 985 int32_t i5, int32_t i6, int32_t i7, int32_t i8, int32_t i9, 986 int32_t i10, int32_t i11, int32_t i12, int32_t i13, 987 int32_t i14, int32_t i15) const { 988 static constexpr SizeT ExpectedNumElements = 16; 989 assert(ExpectedNumElements == getNumIndexes()); 990 (void)ExpectedNumElements; 991 992 return getIndexValue(0) == i0 && getIndexValue(1) == i1 && 993 getIndexValue(2) == i2 && getIndexValue(3) == i3 && 994 getIndexValue(4) == i4 && getIndexValue(5) == i5 && 995 getIndexValue(6) == i6 && getIndexValue(7) == i7 && 996 getIndexValue(8) == i8 && getIndexValue(9) == i9 && 997 getIndexValue(10) == i10 && getIndexValue(11) == i11 && 998 getIndexValue(12) == i12 && getIndexValue(13) == i13 && 999 getIndexValue(14) == i14 && getIndexValue(15) == i15; 1000 } 1001 isMemoryWrite()1002 bool isMemoryWrite() const override { return false; } 1003 void dump(const Cfg *Func) const override; classof(const Inst * Instr)1004 static bool classof(const Inst *Instr) { 1005 return Instr->getKind() == ShuffleVector; 1006 } 1007 1008 private: 1009 InstShuffleVector(Cfg *Func, Variable *Dest, Operand *Src0, Operand *Src1); 1010 destroy(Cfg * Func)1011 void destroy(Cfg *Func) override { 1012 Func->deallocateArrayOf<ConstantInteger32 *>(Indexes); 1013 Inst::destroy(Func); 1014 } 1015 1016 ConstantInteger32 **Indexes; 1017 SizeT CurrentIndex = 0; 1018 const SizeT NumIndexes; 1019 }; 1020 1021 /// JumpTable instruction. This represents a jump table that will be stored in 1022 /// the .rodata section. This is used to track and repoint the target CfgNodes 1023 /// which may change, for example due to splitting for phi lowering. 1024 class InstJumpTable : public InstHighLevel { 1025 InstJumpTable() = delete; 1026 InstJumpTable(const InstJumpTable &) = delete; 1027 InstJumpTable &operator=(const InstJumpTable &) = delete; 1028 1029 public: create(Cfg * Func,SizeT NumTargets,CfgNode * Default)1030 static InstJumpTable *create(Cfg *Func, SizeT NumTargets, CfgNode *Default) { 1031 return new (Func->allocate<InstJumpTable>()) 1032 InstJumpTable(Func, NumTargets, Default); 1033 } addTarget(SizeT TargetIndex,CfgNode * Target)1034 void addTarget(SizeT TargetIndex, CfgNode *Target) { 1035 assert(TargetIndex < NumTargets); 1036 Targets[TargetIndex] = Target; 1037 } 1038 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; getId()1039 SizeT getId() const { return Id; } getNumTargets()1040 SizeT getNumTargets() const { return NumTargets; } getTarget(SizeT I)1041 CfgNode *getTarget(SizeT I) const { 1042 assert(I < NumTargets); 1043 return Targets[I]; 1044 } isMemoryWrite()1045 bool isMemoryWrite() const override { return false; } 1046 void dump(const Cfg *Func) const override; classof(const Inst * Instr)1047 static bool classof(const Inst *Instr) { 1048 return Instr->getKind() == JumpTable; 1049 } 1050 // Creates a JumpTableData struct (used for ELF emission) that represents this 1051 // InstJumpTable. 1052 JumpTableData toJumpTableData(Assembler *Asm) const; 1053 1054 // InstJumpTable is just a placeholder for the switch targets, and it does not 1055 // need to emit any code, so we redefine emit and emitIAS to do nothing. emit(const Cfg *)1056 void emit(const Cfg *) const override {} emitIAS(const Cfg *)1057 void emitIAS(const Cfg * /* Func */) const override {} 1058 getName()1059 const std::string getName() const { 1060 assert(Name.hasStdString()); 1061 return Name.toString(); 1062 } 1063 getSectionName()1064 std::string getSectionName() const { 1065 return JumpTableData::createSectionName(FuncName); 1066 } 1067 1068 private: 1069 InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default); destroy(Cfg * Func)1070 void destroy(Cfg *Func) override { 1071 Func->deallocateArrayOf<CfgNode *>(Targets); 1072 Inst::destroy(Func); 1073 } 1074 1075 const SizeT Id; 1076 const SizeT NumTargets; 1077 CfgNode **Targets; 1078 GlobalString Name; // This JumpTable's name in the output. 1079 GlobalString FuncName; 1080 }; 1081 1082 /// This instruction inserts an unconditional breakpoint. 1083 /// 1084 /// On x86, this assembles into an INT 3 instruction. 1085 /// 1086 /// This instruction is primarily meant for debugging the code generator. 1087 class InstBreakpoint : public InstHighLevel { 1088 public: 1089 InstBreakpoint() = delete; 1090 InstBreakpoint(const InstBreakpoint &) = delete; 1091 InstBreakpoint &operator=(const InstBreakpoint &) = delete; 1092 1093 explicit InstBreakpoint(Cfg *Func); isMemoryWrite()1094 bool isMemoryWrite() const override { return false; } 1095 1096 public: create(Cfg * Func)1097 static InstBreakpoint *create(Cfg *Func) { 1098 return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func); 1099 } 1100 classof(const Inst * Instr)1101 static bool classof(const Inst *Instr) { 1102 return Instr->getKind() == Breakpoint; 1103 } 1104 }; 1105 1106 /// The Target instruction is the base class for all target-specific 1107 /// instructions. 1108 class InstTarget : public Inst { 1109 InstTarget() = delete; 1110 InstTarget(const InstTarget &) = delete; 1111 InstTarget &operator=(const InstTarget &) = delete; 1112 1113 public: getEmitInstCount()1114 uint32_t getEmitInstCount() const override { return 1; } isMemoryWrite()1115 bool isMemoryWrite() const override { 1116 return true; // conservative answer 1117 } 1118 void dump(const Cfg *Func) const override; classof(const Inst * Instr)1119 static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; } 1120 1121 protected: InstTarget(Cfg * Func,InstKind Kind,SizeT MaxSrcs,Variable * Dest)1122 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 1123 : Inst(Func, Kind, MaxSrcs, Dest) { 1124 assert(Kind >= Target); 1125 assert(Kind <= Target_Max); 1126 } 1127 }; 1128 1129 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); 1130 1131 } // end of namespace Ice 1132 1133 #ifdef PNACL_LLVM 1134 namespace llvm { 1135 1136 /// Override the default ilist traits so that Inst's private ctor and deleted 1137 /// dtor aren't invoked. 1138 template <> 1139 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { 1140 Ice::Inst *createSentinel() const { 1141 return static_cast<Ice::Inst *>(&Sentinel); 1142 } 1143 static void destroySentinel(Ice::Inst *) {} 1144 Ice::Inst *provideInitialHead() const { return createSentinel(); } 1145 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } 1146 static void noteHead(Ice::Inst *, Ice::Inst *) {} 1147 void deleteNode(Ice::Inst *) {} 1148 1149 private: 1150 mutable ilist_half_node<Ice::Inst> Sentinel; 1151 }; 1152 1153 } // end of namespace llvm 1154 #endif // PNACL_LLVM 1155 1156 namespace Ice { 1157 1158 inline InstList::iterator instToIterator(Inst *Instr) { 1159 #ifdef PNACL_LLVM 1160 return Instr; 1161 #else // !PNACL_LLVM 1162 return Instr->getIterator(); 1163 #endif // !PNACL_LLVM 1164 } 1165 1166 inline Inst *iteratorToInst(InstList::iterator Iter) { return &*Iter; } 1167 1168 inline const Inst *iteratorToInst(InstList::const_iterator Iter) { 1169 return &*Iter; 1170 } 1171 1172 inline InstList::iterator 1173 reverseToForwardIterator(InstList::reverse_iterator RI) { 1174 #ifdef PNACL_LLVM 1175 return RI.base(); 1176 #else // !PNACL_LLVM 1177 return ++RI.getReverse(); 1178 #endif // !PNACL_LLVM 1179 } 1180 1181 } // end of namespace Ice 1182 1183 #endif // SUBZERO_SRC_ICEINST_H 1184