#pragma once #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #endif //===-- llvm/GlobalValue.h - Class to represent a global value --*- 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 // //===----------------------------------------------------------------------===// // // This file is a common base class of all globally definable objects. As such, // it is subclassed by GlobalVariable, GlobalAlias and by Function. This is // used because you can do certain things with these global objects that you // can't do to anything else. For example, use the address of one as a // constant. // //===----------------------------------------------------------------------===// #ifndef LLVM_IR_GLOBALVALUE_H #define LLVM_IR_GLOBALVALUE_H #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/Constant.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MD5.h" #include #include #include namespace llvm { class Comdat; class ConstantRange; class Error; class GlobalObject; class Module; namespace Intrinsic { typedef unsigned ID; } // end namespace Intrinsic class GlobalValue : public Constant { public: /// An enumeration for the kinds of linkage for global values. enum LinkageTypes { ExternalLinkage = 0,///< Externally visible function AvailableExternallyLinkage, ///< Available for inspection, not emission. LinkOnceAnyLinkage, ///< Keep one copy of function when linking (inline) LinkOnceODRLinkage, ///< Same, but only replaced by something equivalent. WeakAnyLinkage, ///< Keep one copy of named function when linking (weak) WeakODRLinkage, ///< Same, but only replaced by something equivalent. AppendingLinkage, ///< Special purpose, only applies to global arrays InternalLinkage, ///< Rename collisions when linking (static functions). PrivateLinkage, ///< Like Internal, but omit from symbol table. ExternalWeakLinkage,///< ExternalWeak linkage description. CommonLinkage ///< Tentative definitions. }; /// An enumeration for the kinds of visibility of global values. enum VisibilityTypes { DefaultVisibility = 0, ///< The GV is visible HiddenVisibility, ///< The GV is hidden ProtectedVisibility ///< The GV is protected }; /// Storage classes of global values for PE targets. enum DLLStorageClassTypes { DefaultStorageClass = 0, DLLImportStorageClass = 1, ///< Function to be imported from DLL DLLExportStorageClass = 2 ///< Function to be accessible from DLL. }; protected: GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace) : Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps), ValueType(Ty), Visibility(DefaultVisibility), UnnamedAddrVal(unsigned(UnnamedAddr::None)), DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), HasLLVMReservedName(false), IsDSOLocal(false), HasPartition(false), HasSanitizerMetadata(false) { setLinkage(Linkage); setName(Name); } Type *ValueType; static const unsigned GlobalValueSubClassDataBits = 15; // All bitfields use unsigned as the underlying type so that MSVC will pack // them. unsigned Linkage : 4; // The linkage of this global unsigned Visibility : 2; // The visibility style of this global unsigned UnnamedAddrVal : 2; // This value's address is not significant unsigned DllStorageClass : 2; // DLL storage class unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is // the desired model? /// True if the function's name starts with "llvm.". This corresponds to the /// value of Function::isIntrinsic(), which may be true even if /// Function::intrinsicID() returns Intrinsic::not_intrinsic. unsigned HasLLVMReservedName : 1; /// If true then there is a definition within the same linkage unit and that /// definition cannot be runtime preempted. unsigned IsDSOLocal : 1; /// True if this symbol has a partition name assigned (see /// https://lld.llvm.org/Partitions.html). unsigned HasPartition : 1; /// True if this symbol has sanitizer metadata available. Should only happen /// if sanitizers were enabled when building the translation unit which /// contains this GV. unsigned HasSanitizerMetadata : 1; private: // Give subclasses access to what otherwise would be wasted padding. // (15 + 4 + 2 + 2 + 2 + 3 + 1 + 1 + 1 + 1) == 32. unsigned SubClassData : GlobalValueSubClassDataBits; friend class Constant; void destroyConstantImpl(); Value *handleOperandChangeImpl(Value *From, Value *To); /// Returns true if the definition of this global may be replaced by a /// differently optimized variant of the same source level function at link /// time. bool mayBeDerefined() const { switch (getLinkage()) { case WeakODRLinkage: case LinkOnceODRLinkage: case AvailableExternallyLinkage: return true; case WeakAnyLinkage: case LinkOnceAnyLinkage: case CommonLinkage: case ExternalWeakLinkage: case ExternalLinkage: case AppendingLinkage: case InternalLinkage: case PrivateLinkage: // Optimizations may assume builtin semantics for functions defined as // nobuiltin due to attributes at call-sites. To avoid applying IPO based // on nobuiltin semantics, treat such function definitions as maybe // derefined. return isInterposable() || isNobuiltinFnDef(); } llvm_unreachable("Fully covered switch above!"); } /// Returns true if the global is a function definition with the nobuiltin /// attribute. bool isNobuiltinFnDef() const; protected: /// The intrinsic ID for this subclass (which must be a Function). /// /// This member is defined by this class, but not used for anything. /// Subclasses can use it to store their intrinsic ID, if they have one. /// /// This is stored here to save space in Function on 64-bit hosts. Intrinsic::ID IntID = (Intrinsic::ID)0U; unsigned getGlobalValueSubClassData() const { return SubClassData; } void setGlobalValueSubClassData(unsigned V) { assert(V < (1 << GlobalValueSubClassDataBits) && "It will not fit"); SubClassData = V; } Module *Parent = nullptr; // The containing module. // Used by SymbolTableListTraits. void setParent(Module *parent) { Parent = parent; } ~GlobalValue() { removeDeadConstantUsers(); // remove any dead constants using this. } public: enum ThreadLocalMode { NotThreadLocal = 0, GeneralDynamicTLSModel, LocalDynamicTLSModel, InitialExecTLSModel, LocalExecTLSModel }; GlobalValue(const GlobalValue &) = delete; unsigned getAddressSpace() const { return getType()->getAddressSpace(); } enum class UnnamedAddr { None, Local, Global, }; bool hasGlobalUnnamedAddr() const { return getUnnamedAddr() == UnnamedAddr::Global; } /// Returns true if this value's address is not significant in this module. /// This attribute is intended to be used only by the code generator and LTO /// to allow the linker to decide whether the global needs to be in the symbol /// table. It should probably not be used in optimizations, as the value may /// have uses outside the module; use hasGlobalUnnamedAddr() instead. bool hasAtLeastLocalUnnamedAddr() const { return getUnnamedAddr() != UnnamedAddr::None; } UnnamedAddr getUnnamedAddr() const { return UnnamedAddr(UnnamedAddrVal); } void setUnnamedAddr(UnnamedAddr Val) { UnnamedAddrVal = unsigned(Val); } static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) { if (A == UnnamedAddr::None || B == UnnamedAddr::None) return UnnamedAddr::None; if (A == UnnamedAddr::Local || B == UnnamedAddr::Local) return UnnamedAddr::Local; return UnnamedAddr::Global; } bool hasComdat() const { return getComdat() != nullptr; } const Comdat *getComdat() const; Comdat *getComdat() { return const_cast( static_cast(this)->getComdat()); } VisibilityTypes getVisibility() const { return VisibilityTypes(Visibility); } bool hasDefaultVisibility() const { return Visibility == DefaultVisibility; } bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } bool hasProtectedVisibility() const { return Visibility == ProtectedVisibility; } void setVisibility(VisibilityTypes V) { assert((!hasLocalLinkage() || V == DefaultVisibility) && "local linkage requires default visibility"); Visibility = V; if (isImplicitDSOLocal()) setDSOLocal(true); } /// If the value is "Thread Local", its value isn't shared by the threads. bool isThreadLocal() const { return getThreadLocalMode() != NotThreadLocal; } void setThreadLocal(bool Val) { setThreadLocalMode(Val ? GeneralDynamicTLSModel : NotThreadLocal); } void setThreadLocalMode(ThreadLocalMode Val) { assert(Val == NotThreadLocal || getValueID() != Value::FunctionVal); ThreadLocal = Val; } ThreadLocalMode getThreadLocalMode() const { return static_cast(ThreadLocal); } DLLStorageClassTypes getDLLStorageClass() const { return DLLStorageClassTypes(DllStorageClass); } bool hasDLLImportStorageClass() const { return DllStorageClass == DLLImportStorageClass; } bool hasDLLExportStorageClass() const { return DllStorageClass == DLLExportStorageClass; } void setDLLStorageClass(DLLStorageClassTypes C) { assert((!hasLocalLinkage() || C == DefaultStorageClass) && "local linkage requires DefaultStorageClass"); DllStorageClass = C; } bool hasSection() const { return !getSection().empty(); } StringRef getSection() const; /// Global values are always pointers. PointerType *getType() const { return cast(User::getType()); } Type *getValueType() const { return ValueType; } bool isImplicitDSOLocal() const { return hasLocalLinkage() || (!hasDefaultVisibility() && !hasExternalWeakLinkage()); } void setDSOLocal(bool Local) { IsDSOLocal = Local; } bool isDSOLocal() const { return IsDSOLocal; } bool hasPartition() const { return HasPartition; } StringRef getPartition() const; void setPartition(StringRef Part); // ASan, HWASan and Memtag sanitizers have some instrumentation that applies // specifically to global variables. struct SanitizerMetadata { SanitizerMetadata() : NoAddress(false), NoHWAddress(false), Memtag(false), IsDynInit(false) {} // For ASan and HWASan, this instrumentation is implicitly applied to all // global variables when built with -fsanitize=*. What we need is a way to // persist the information that a certain global variable should *not* have // sanitizers applied, which occurs if: // 1. The global variable is in the sanitizer ignore list, or // 2. The global variable is created by the sanitizers itself for internal // usage, or // 3. The global variable has __attribute__((no_sanitize("..."))) or // __attribute__((disable_sanitizer_instrumentation)). // // This is important, a some IR passes like GlobalMerge can delete global // variables and replace them with new ones. If the old variables were // marked to be unsanitized, then the new ones should also be. unsigned NoAddress : 1; unsigned NoHWAddress : 1; // Memtag sanitization works differently: sanitization is requested by clang // when `-fsanitize=memtag-globals` is provided, and the request can be // denied (and the attribute removed) by the AArch64 global tagging pass if // it can't be fulfilled (e.g. the global variable is a TLS variable). // Memtag sanitization has to interact with other parts of LLVM (like // supressing certain optimisations, emitting assembly directives, or // creating special relocation sections). // // Use `GlobalValue::isTagged()` to check whether tagging should be enabled // for a global variable. unsigned Memtag : 1; // ASan-specific metadata. Is this global variable dynamically initialized // (from a C++ language perspective), and should therefore be checked for // ODR violations. unsigned IsDynInit : 1; }; bool hasSanitizerMetadata() const { return HasSanitizerMetadata; } const SanitizerMetadata &getSanitizerMetadata() const; // Note: Not byref as it's a POD and otherwise it's too easy to call // G.setSanitizerMetadata(G2.getSanitizerMetadata()), and the argument becomes // dangling when the backing storage allocates the metadata for `G`, as the // storage is shared between `G1` and `G2`. void setSanitizerMetadata(SanitizerMetadata Meta); void removeSanitizerMetadata(); bool isTagged() const { return hasSanitizerMetadata() && getSanitizerMetadata().Memtag; } static LinkageTypes getLinkOnceLinkage(bool ODR) { return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; } static LinkageTypes getWeakLinkage(bool ODR) { return ODR ? WeakODRLinkage : WeakAnyLinkage; } static bool isExternalLinkage(LinkageTypes Linkage) { return Linkage == ExternalLinkage; } static bool isAvailableExternallyLinkage(LinkageTypes Linkage) { return Linkage == AvailableExternallyLinkage; } static bool isLinkOnceAnyLinkage(LinkageTypes Linkage) { return Linkage == LinkOnceAnyLinkage; } static bool isLinkOnceODRLinkage(LinkageTypes Linkage) { return Linkage == LinkOnceODRLinkage; } static bool isLinkOnceLinkage(LinkageTypes Linkage) { return isLinkOnceAnyLinkage(Linkage) || isLinkOnceODRLinkage(Linkage); } static bool isWeakAnyLinkage(LinkageTypes Linkage) { return Linkage == WeakAnyLinkage; } static bool isWeakODRLinkage(LinkageTypes Linkage) { return Linkage == WeakODRLinkage; } static bool isWeakLinkage(LinkageTypes Linkage) { return isWeakAnyLinkage(Linkage) || isWeakODRLinkage(Linkage); } static bool isAppendingLinkage(LinkageTypes Linkage) { return Linkage == AppendingLinkage; } static bool isInternalLinkage(LinkageTypes Linkage) { return Linkage == InternalLinkage; } static bool isPrivateLinkage(LinkageTypes Linkage) { return Linkage == PrivateLinkage; } static bool isLocalLinkage(LinkageTypes Linkage) { return isInternalLinkage(Linkage) || isPrivateLinkage(Linkage); } static bool isExternalWeakLinkage(LinkageTypes Linkage) { return Linkage == ExternalWeakLinkage; } static bool isCommonLinkage(LinkageTypes Linkage) { return Linkage == CommonLinkage; } static bool isValidDeclarationLinkage(LinkageTypes Linkage) { return isExternalWeakLinkage(Linkage) || isExternalLinkage(Linkage); } /// Whether the definition of this global may be replaced by something /// non-equivalent at link time. For example, if a function has weak linkage /// then the code defining it may be replaced by different code. static bool isInterposableLinkage(LinkageTypes Linkage) { switch (Linkage) { case WeakAnyLinkage: case LinkOnceAnyLinkage: case CommonLinkage: case ExternalWeakLinkage: return true; case AvailableExternallyLinkage: case LinkOnceODRLinkage: case WeakODRLinkage: // The above three cannot be overridden but can be de-refined. case ExternalLinkage: case AppendingLinkage: case InternalLinkage: case PrivateLinkage: return false; } llvm_unreachable("Fully covered switch above!"); } /// Whether the definition of this global may be discarded if it is not used /// in its compilation unit. static bool isDiscardableIfUnused(LinkageTypes Linkage) { return isLinkOnceLinkage(Linkage) || isLocalLinkage(Linkage) || isAvailableExternallyLinkage(Linkage); } /// Whether the definition of this global may be replaced at link time. NB: /// Using this method outside of the code generators is almost always a /// mistake: when working at the IR level use isInterposable instead as it /// knows about ODR semantics. static bool isWeakForLinker(LinkageTypes Linkage) { return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage || Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage || Linkage == CommonLinkage || Linkage == ExternalWeakLinkage; } /// Return true if the currently visible definition of this global (if any) is /// exactly the definition we will see at runtime. /// /// Non-exact linkage types inhibits most non-inlining IPO, since a /// differently optimized variant of the same function can have different /// observable or undefined behavior than in the variant currently visible. /// For instance, we could have started with /// /// void foo(int *v) { /// int t = 5 / v[0]; /// (void) t; /// } /// /// and "refined" it to /// /// void foo(int *v) { } /// /// However, we cannot infer readnone for `foo`, since that would justify /// DSE'ing a store to `v[0]` across a call to `foo`, which can cause /// undefined behavior if the linker replaces the actual call destination with /// the unoptimized `foo`. /// /// Inlining is okay across non-exact linkage types as long as they're not /// interposable (see \c isInterposable), since in such cases the currently /// visible variant is *a* correct implementation of the original source /// function; it just isn't the *only* correct implementation. bool isDefinitionExact() const { return !mayBeDerefined(); } /// Return true if this global has an exact defintion. bool hasExactDefinition() const { // While this computes exactly the same thing as // isStrongDefinitionForLinker, the intended uses are different. This // function is intended to help decide if specific inter-procedural // transforms are correct, while isStrongDefinitionForLinker's intended use // is in low level code generation. return !isDeclaration() && isDefinitionExact(); } /// Return true if this global's definition can be substituted with an /// *arbitrary* definition at link time or load time. We cannot do any IPO or /// inlining across interposable call edges, since the callee can be /// replaced with something arbitrary. bool isInterposable() const; bool canBenefitFromLocalAlias() const; bool hasExternalLinkage() const { return isExternalLinkage(getLinkage()); } bool hasAvailableExternallyLinkage() const { return isAvailableExternallyLinkage(getLinkage()); } bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(getLinkage()); } bool hasLinkOnceAnyLinkage() const { return isLinkOnceAnyLinkage(getLinkage()); } bool hasLinkOnceODRLinkage() const { return isLinkOnceODRLinkage(getLinkage()); } bool hasWeakLinkage() const { return isWeakLinkage(getLinkage()); } bool hasWeakAnyLinkage() const { return isWeakAnyLinkage(getLinkage()); } bool hasWeakODRLinkage() const { return isWeakODRLinkage(getLinkage()); } bool hasAppendingLinkage() const { return isAppendingLinkage(getLinkage()); } bool hasInternalLinkage() const { return isInternalLinkage(getLinkage()); } bool hasPrivateLinkage() const { return isPrivateLinkage(getLinkage()); } bool hasLocalLinkage() const { return isLocalLinkage(getLinkage()); } bool hasExternalWeakLinkage() const { return isExternalWeakLinkage(getLinkage()); } bool hasCommonLinkage() const { return isCommonLinkage(getLinkage()); } bool hasValidDeclarationLinkage() const { return isValidDeclarationLinkage(getLinkage()); } void setLinkage(LinkageTypes LT) { if (isLocalLinkage(LT)) { Visibility = DefaultVisibility; DllStorageClass = DefaultStorageClass; } Linkage = LT; if (isImplicitDSOLocal()) setDSOLocal(true); } LinkageTypes getLinkage() const { return LinkageTypes(Linkage); } bool isDiscardableIfUnused() const { return isDiscardableIfUnused(getLinkage()); } bool isWeakForLinker() const { return isWeakForLinker(getLinkage()); } protected: /// Copy all additional attributes (those not needed to create a GlobalValue) /// from the GlobalValue Src to this one. void copyAttributesFrom(const GlobalValue *Src); public: /// If the given string begins with the GlobalValue name mangling escape /// character '\1', drop it. /// /// This function applies a specific mangling that is used in PGO profiles, /// among other things. If you're trying to get a symbol name for an /// arbitrary GlobalValue, this is not the function you're looking for; see /// Mangler.h. static StringRef dropLLVMManglingEscape(StringRef Name) { if (!Name.empty() && Name[0] == '\1') return Name.substr(1); return Name; } /// Return the modified name for a global value suitable to be /// used as the key for a global lookup (e.g. profile or ThinLTO). /// The value's original name is \c Name and has linkage of type /// \c Linkage. The value is defined in module \c FileName. static std::string getGlobalIdentifier(StringRef Name, GlobalValue::LinkageTypes Linkage, StringRef FileName); /// Return the modified name for this global value suitable to be /// used as the key for a global lookup (e.g. profile or ThinLTO). std::string getGlobalIdentifier() const; /// Declare a type to represent a global unique identifier for a global value. /// This is a 64 bits hash that is used by PGO and ThinLTO to have a compact /// unique way to identify a symbol. using GUID = uint64_t; /// Return a 64-bit global unique ID constructed from global value name /// (i.e. returned by getGlobalIdentifier()). static GUID getGUID(StringRef GlobalName) { return MD5Hash(GlobalName); } /// Return a 64-bit global unique ID constructed from global value name /// (i.e. returned by getGlobalIdentifier()). GUID getGUID() const { return getGUID(getGlobalIdentifier()); } /// @name Materialization /// Materialization is used to construct functions only as they're needed. /// This /// is useful to reduce memory usage in LLVM or parsing work done by the /// BitcodeReader to load the Module. /// @{ /// If this function's Module is being lazily streamed in functions from disk /// or some other source, this method can be used to check to see if the /// function has been read in yet or not. bool isMaterializable() const; /// Make sure this GlobalValue is fully read. Error materialize(); /// @} /// Return true if the primary definition of this global value is outside of /// the current translation unit. bool isDeclaration() const; bool isDeclarationForLinker() const { if (hasAvailableExternallyLinkage()) return true; return isDeclaration(); } /// Returns true if this global's definition will be the one chosen by the /// linker. /// /// NB! Ideally this should not be used at the IR level at all. If you're /// interested in optimization constraints implied by the linker's ability to /// choose an implementation, prefer using \c hasExactDefinition. bool isStrongDefinitionForLinker() const { return !(isDeclarationForLinker() || isWeakForLinker()); } const GlobalObject *getAliaseeObject() const; GlobalObject *getAliaseeObject() { return const_cast( static_cast(this)->getAliaseeObject()); } /// Returns whether this is a reference to an absolute symbol. bool isAbsoluteSymbolRef() const; /// If this is an absolute symbol reference, returns the range of the symbol, /// otherwise returns std::nullopt. std::optional getAbsoluteSymbolRange() const; /// This method unlinks 'this' from the containing module, but does not delete /// it. void removeFromParent(); /// This method unlinks 'this' from the containing module and deletes it. void eraseFromParent(); /// Get the module that this global value is contained inside of... Module *getParent() { return Parent; } const Module *getParent() const { return Parent; } // Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || V->getValueID() == Value::GlobalVariableVal || V->getValueID() == Value::GlobalAliasVal || V->getValueID() == Value::GlobalIFuncVal; } /// True if GV can be left out of the object symbol table. This is the case /// for linkonce_odr values whose address is not significant. While legal, it /// is not normally profitable to omit them from the .o symbol table. Using /// this analysis makes sense when the information can be passed down to the /// linker or we are in LTO. bool canBeOmittedFromSymbolTable() const; }; } // end namespace llvm #endif // LLVM_IR_GLOBALVALUE_H #ifdef __GNUC__ #pragma GCC diagnostic pop #endif