//===- Value.h --------------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_SANDBOXIR_VALUE_H #define LLVM_SANDBOXIR_VALUE_H #include "llvm/IR/Metadata.h" #include "llvm/IR/Value.h" #include "llvm/SandboxIR/Use.h" #include "llvm/Support/Compiler.h" namespace llvm::sandboxir { // Forward declare all classes to avoid some MSVC build errors. #define DEF_INSTR(ID, OPC, CLASS) class CLASS; #define DEF_CONST(ID, CLASS) class CLASS; #define DEF_USER(ID, CLASS) class CLASS; #include "llvm/SandboxIR/Values.def" class Context; class FuncletPadInst; class Type; class GlobalValue; class GlobalObject; class Module; class UnaryInstruction; class CmpInst; class IntrinsicInst; class Operator; class OverflowingBinaryOperator; class FPMathOperator; class Region; /// Iterator for the `Use` edges of a Value's users. /// \Returns a `Use` when dereferenced. class UserUseIterator { sandboxir::Use Use; /// Don't let the user create a non-empty UserUseIterator. UserUseIterator(const class Use &Use) : Use(Use) {} friend class Value; // For constructor public: using difference_type = std::ptrdiff_t; using value_type = sandboxir::Use; using pointer = value_type *; using reference = value_type &; using iterator_category = std::input_iterator_tag; UserUseIterator() = default; value_type operator*() const { return Use; } LLVM_ABI UserUseIterator &operator++(); bool operator==(const UserUseIterator &Other) const { return Use == Other.Use; } bool operator!=(const UserUseIterator &Other) const { return !(*this == Other); } const sandboxir::Use &getUse() const { return Use; } }; /// A SandboxIR Value has users. This is the base class. class Value { public: enum class ClassID : unsigned { #define DEF_VALUE(ID, CLASS) ID, #define DEF_USER(ID, CLASS) ID, #define DEF_CONST(ID, CLASS) ID, #define DEF_INSTR(ID, OPC, CLASS) ID, #include "llvm/SandboxIR/Values.def" }; protected: static const char *getSubclassIDStr(ClassID ID) { switch (ID) { #define DEF_VALUE(ID, CLASS) \ case ClassID::ID: \ return #ID; #define DEF_USER(ID, CLASS) \ case ClassID::ID: \ return #ID; #define DEF_CONST(ID, CLASS) \ case ClassID::ID: \ return #ID; #define DEF_INSTR(ID, OPC, CLASS) \ case ClassID::ID: \ return #ID; #include "llvm/SandboxIR/Values.def" } llvm_unreachable("Unimplemented ID"); } /// For isa/dyn_cast. ClassID SubclassID; #ifndef NDEBUG /// A unique ID used for forming the name (used for debugging). unsigned UID; #endif /// The LLVM Value that corresponds to this SandboxIR Value. /// NOTE: Some sandboxir Instructions, like Packs, may include more than one /// value and in these cases `Val` points to the last instruction in program /// order. llvm::Value *Val = nullptr; friend class Context; // For getting `Val`. friend class User; // For getting `Val`. friend class Use; // For getting `Val`. friend class VAArgInst; // For getting `Val`. friend class FreezeInst; // For getting `Val`. friend class FenceInst; // For getting `Val`. friend class SelectInst; // For getting `Val`. friend class ExtractElementInst; // For getting `Val`. friend class InsertElementInst; // For getting `Val`. friend class ShuffleVectorInst; // For getting `Val`. friend class ExtractValueInst; // For getting `Val`. friend class InsertValueInst; // For getting `Val`. friend class BranchInst; // For getting `Val`. friend class LoadInst; // For getting `Val`. friend class StoreInst; // For getting `Val`. friend class ReturnInst; // For getting `Val`. friend class CallBase; // For getting `Val`. friend class CallInst; // For getting `Val`. friend class InvokeInst; // For getting `Val`. friend class CallBrInst; // For getting `Val`. friend class LandingPadInst; // For getting `Val`. friend class FuncletPadInst; // For getting `Val`. friend class CatchPadInst; // For getting `Val`. friend class CleanupPadInst; // For getting `Val`. friend class CatchReturnInst; // For getting `Val`. friend class GetElementPtrInst; // For getting `Val`. friend class ResumeInst; // For getting `Val`. friend class CatchSwitchInst; // For getting `Val`. friend class CleanupReturnInst; // For getting `Val`. friend class SwitchInst; // For getting `Val`. friend class UnaryOperator; // For getting `Val`. friend class BinaryOperator; // For getting `Val`. friend class AtomicRMWInst; // For getting `Val`. friend class AtomicCmpXchgInst; // For getting `Val`. friend class AllocaInst; // For getting `Val`. friend class CastInst; // For getting `Val`. friend class PHINode; // For getting `Val`. friend class UnreachableInst; // For getting `Val`. friend class CatchSwitchAddHandler; // For `Val`. friend class CmpInst; // For getting `Val`. friend class ConstantArray; // For `Val`. friend class ConstantStruct; // For `Val`. friend class ConstantVector; // For `Val`. friend class ConstantAggregateZero; // For `Val`. friend class ConstantPointerNull; // For `Val`. friend class UndefValue; // For `Val`. friend class PoisonValue; // For `Val`. friend class BlockAddress; // For `Val`. friend class GlobalValue; // For `Val`. friend class DSOLocalEquivalent; // For `Val`. friend class GlobalObject; // For `Val`. friend class GlobalIFunc; // For `Val`. friend class GlobalVariable; // For `Val`. friend class GlobalAlias; // For `Val`. friend class NoCFIValue; // For `Val`. friend class ConstantPtrAuth; // For `Val`. friend class ConstantExpr; // For `Val`. friend class Utils; // For `Val`. friend class Module; // For `Val`. friend class IntrinsicInst; // For `Val`. friend class Operator; // For `Val`. friend class OverflowingBinaryOperator; // For `Val`. friend class FPMathOperator; // For `Val`. // Region needs to manipulate metadata in the underlying LLVM Value, we don't // expose metadata in sandboxir. friend class Region; friend class ScoreBoard; // Needs access to `Val` for the instruction cost. friend class ConstantDataArray; // For `Val` friend class ConstantDataVector; // For `Val` /// All values point to the context. Context &Ctx; // This is used by eraseFromParent(). void clearValue() { Val = nullptr; } template friend class LLVMOpUserItToSBTy; LLVM_ABI Value(ClassID SubclassID, llvm::Value *Val, Context &Ctx); /// Disable copies. Value(const Value &) = delete; Value &operator=(const Value &) = delete; public: virtual ~Value() = default; ClassID getSubclassID() const { return SubclassID; } using use_iterator = UserUseIterator; using const_use_iterator = UserUseIterator; LLVM_ABI use_iterator use_begin(); const_use_iterator use_begin() const { return const_cast(this)->use_begin(); } use_iterator use_end() { return use_iterator(Use(nullptr, nullptr, Ctx)); } const_use_iterator use_end() const { return const_cast(this)->use_end(); } iterator_range uses() { return make_range(use_begin(), use_end()); } iterator_range uses() const { return make_range(use_begin(), use_end()); } /// Helper for mapped_iterator. struct UseToUser { User *operator()(const Use &Use) const { return &*Use.getUser(); } }; using user_iterator = mapped_iterator; using const_user_iterator = user_iterator; LLVM_ABI user_iterator user_begin(); user_iterator user_end() { return user_iterator(Use(nullptr, nullptr, Ctx), UseToUser()); } const_user_iterator user_begin() const { return const_cast(this)->user_begin(); } const_user_iterator user_end() const { return const_cast(this)->user_end(); } iterator_range users() { return make_range(user_begin(), user_end()); } iterator_range users() const { return make_range(user_begin(), user_end()); } /// \Returns the number of user edges (not necessarily to unique users). /// WARNING: This is a linear-time operation. LLVM_ABI unsigned getNumUses() const; /// Return true if this value has N uses or more. /// This is logically equivalent to getNumUses() >= N. /// WARNING: This can be expensive, as it is linear to the number of users. bool hasNUsesOrMore(unsigned Num) const { unsigned Cnt = 0; for (auto It = use_begin(), ItE = use_end(); It != ItE; ++It) { if (++Cnt >= Num) return true; } return false; } /// Return true if this Value has exactly N uses. bool hasNUses(unsigned Num) const { unsigned Cnt = 0; for (auto It = use_begin(), ItE = use_end(); It != ItE; ++It) { if (++Cnt > Num) return false; } return Cnt == Num; } LLVM_ABI Type *getType() const; Context &getContext() const { return Ctx; } LLVM_ABI void replaceUsesWithIf(Value *OtherV, llvm::function_ref ShouldReplace); LLVM_ABI void replaceAllUsesWith(Value *Other); /// \Returns the LLVM IR name of the bottom-most LLVM value. StringRef getName() const { return Val->getName(); } #ifndef NDEBUG /// Should crash if there is something wrong with the instruction. virtual void verify() const = 0; /// Returns the unique id in the form 'SB.' like 'SB1.' std::string getUid() const; virtual void dumpCommonHeader(raw_ostream &OS) const; void dumpCommonFooter(raw_ostream &OS) const; void dumpCommonPrefix(raw_ostream &OS) const; void dumpCommonSuffix(raw_ostream &OS) const; void printAsOperandCommon(raw_ostream &OS) const; friend raw_ostream &operator<<(raw_ostream &OS, const sandboxir::Value &V) { V.dumpOS(OS); return OS; } virtual void dumpOS(raw_ostream &OS) const = 0; LLVM_DUMP_METHOD void dump() const; #endif }; class OpaqueValue : public Value { protected: OpaqueValue(llvm::Value *V, Context &Ctx) : Value(ClassID::OpaqueValue, V, Ctx) {} friend class Context; // For constructor. public: static bool classof(const Value *From) { return From->getSubclassID() == ClassID::OpaqueValue; } #ifndef NDEBUG void verify() const override { assert((isa(Val) || isa(Val)) && "Expected Metadata or InlineAssembly!"); } void dumpOS(raw_ostream &OS) const override { dumpCommonPrefix(OS); dumpCommonSuffix(OS); } #endif // NDEBUG }; } // namespace llvm::sandboxir #endif // LLVM_SANDBOXIR_VALUE_H