10b57cec5SDimitry Andric //===-- llvm/GlobalVariable.h - GlobalVariable class ------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the declaration of the GlobalVariable class, which 100b57cec5SDimitry Andric // represents a single global variable (or constant) in the VM. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric // Global variables are constant pointers that refer to hunks of space that are 130b57cec5SDimitry Andric // allocated by either the VM, or by the linker in a static compiler. A global 140b57cec5SDimitry Andric // variable may have an initial value, which is copied into the executables .data 150b57cec5SDimitry Andric // area. Global Constants are required to have initializers. 160b57cec5SDimitry Andric // 170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #ifndef LLVM_IR_GLOBALVARIABLE_H 200b57cec5SDimitry Andric #define LLVM_IR_GLOBALVARIABLE_H 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric #include "llvm/ADT/Twine.h" 230b57cec5SDimitry Andric #include "llvm/ADT/ilist_node.h" 240b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 250b57cec5SDimitry Andric #include "llvm/IR/GlobalObject.h" 260b57cec5SDimitry Andric #include "llvm/IR/OperandTraits.h" 270b57cec5SDimitry Andric #include "llvm/IR/Value.h" 280b57cec5SDimitry Andric #include <cassert> 290b57cec5SDimitry Andric #include <cstddef> 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric namespace llvm { 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric class Constant; 340b57cec5SDimitry Andric class Module; 350b57cec5SDimitry Andric 36*5f757f3fSDimitry Andric template <typename ValueSubClass, typename... Args> class SymbolTableListTraits; 370b57cec5SDimitry Andric class DIGlobalVariableExpression; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> { 400b57cec5SDimitry Andric friend class SymbolTableListTraits<GlobalVariable>; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric AttributeSet Attrs; 43*5f757f3fSDimitry Andric 44*5f757f3fSDimitry Andric // Is this a global constant? 45*5f757f3fSDimitry Andric bool isConstantGlobal : 1; 46*5f757f3fSDimitry Andric // Is this a global whose value can change from its initial value before 47*5f757f3fSDimitry Andric // global initializers are run? 48*5f757f3fSDimitry Andric bool isExternallyInitializedConstant : 1; 49*5f757f3fSDimitry Andric 50*5f757f3fSDimitry Andric private: 51*5f757f3fSDimitry Andric static const unsigned CodeModelBits = LastCodeModelBit - LastAlignmentBit; 52*5f757f3fSDimitry Andric static const unsigned CodeModelMask = (1 << CodeModelBits) - 1; 53*5f757f3fSDimitry Andric static const unsigned CodeModelShift = LastAlignmentBit + 1; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric public: 560b57cec5SDimitry Andric /// GlobalVariable ctor - If a parent module is specified, the global is 570b57cec5SDimitry Andric /// automatically inserted into the end of the specified modules global list. 580b57cec5SDimitry Andric GlobalVariable(Type *Ty, bool isConstant, LinkageTypes Linkage, 590b57cec5SDimitry Andric Constant *Initializer = nullptr, const Twine &Name = "", 600b57cec5SDimitry Andric ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, 610b57cec5SDimitry Andric bool isExternallyInitialized = false); 620b57cec5SDimitry Andric /// GlobalVariable ctor - This creates a global and inserts it before the 630b57cec5SDimitry Andric /// specified other global. 64e8d8bef9SDimitry Andric GlobalVariable(Module &M, Type *Ty, bool isConstant, LinkageTypes Linkage, 65e8d8bef9SDimitry Andric Constant *Initializer, const Twine &Name = "", 66e8d8bef9SDimitry Andric GlobalVariable *InsertBefore = nullptr, 67e8d8bef9SDimitry Andric ThreadLocalMode = NotThreadLocal, 68bdd1243dSDimitry Andric std::optional<unsigned> AddressSpace = std::nullopt, 690b57cec5SDimitry Andric bool isExternallyInitialized = false); 700b57cec5SDimitry Andric GlobalVariable(const GlobalVariable &) = delete; 710b57cec5SDimitry Andric GlobalVariable &operator=(const GlobalVariable &) = delete; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric ~GlobalVariable() { 740b57cec5SDimitry Andric dropAllReferences(); 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric // allocate space for exactly one operand 780b57cec5SDimitry Andric void *operator new(size_t s) { 790b57cec5SDimitry Andric return User::operator new(s, 1); 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric // delete space for exactly one operand as created in the corresponding new operator 830b57cec5SDimitry Andric void operator delete(void *ptr){ 840b57cec5SDimitry Andric assert(ptr != nullptr && "must not be nullptr"); 850b57cec5SDimitry Andric User *Obj = static_cast<User *>(ptr); 860b57cec5SDimitry Andric // Number of operands can be set to 0 after construction and initialization. Make sure 870b57cec5SDimitry Andric // that number of operands is reset to 1, as this is needed in User::operator delete 880b57cec5SDimitry Andric Obj->setGlobalVariableNumOperands(1); 890b57cec5SDimitry Andric User::operator delete(Obj); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric /// Provide fast operand accessors 930b57cec5SDimitry Andric DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric /// Definitions have initializers, declarations don't. 960b57cec5SDimitry Andric /// 970b57cec5SDimitry Andric inline bool hasInitializer() const { return !isDeclaration(); } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric /// hasDefinitiveInitializer - Whether the global variable has an initializer, 1000b57cec5SDimitry Andric /// and any other instances of the global (this can happen due to weak 1010b57cec5SDimitry Andric /// linkage) are guaranteed to have the same initializer. 1020b57cec5SDimitry Andric /// 1030b57cec5SDimitry Andric /// Note that if you want to transform a global, you must use 1040b57cec5SDimitry Andric /// hasUniqueInitializer() instead, because of the *_odr linkage type. 1050b57cec5SDimitry Andric /// 1060b57cec5SDimitry Andric /// Example: 1070b57cec5SDimitry Andric /// 1080b57cec5SDimitry Andric /// @a = global SomeType* null - Initializer is both definitive and unique. 1090b57cec5SDimitry Andric /// 1100b57cec5SDimitry Andric /// @b = global weak SomeType* null - Initializer is neither definitive nor 1110b57cec5SDimitry Andric /// unique. 1120b57cec5SDimitry Andric /// 1130b57cec5SDimitry Andric /// @c = global weak_odr SomeType* null - Initializer is definitive, but not 1140b57cec5SDimitry Andric /// unique. 1150b57cec5SDimitry Andric inline bool hasDefinitiveInitializer() const { 1160b57cec5SDimitry Andric return hasInitializer() && 1170b57cec5SDimitry Andric // The initializer of a global variable may change to something arbitrary 1180b57cec5SDimitry Andric // at link time. 1190b57cec5SDimitry Andric !isInterposable() && 1200b57cec5SDimitry Andric // The initializer of a global variable with the externally_initialized 1210b57cec5SDimitry Andric // marker may change at runtime before C++ initializers are evaluated. 1220b57cec5SDimitry Andric !isExternallyInitialized(); 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric /// hasUniqueInitializer - Whether the global variable has an initializer, and 1260b57cec5SDimitry Andric /// any changes made to the initializer will turn up in the final executable. 1270b57cec5SDimitry Andric inline bool hasUniqueInitializer() const { 1280b57cec5SDimitry Andric return 1290b57cec5SDimitry Andric // We need to be sure this is the definition that will actually be used 1300b57cec5SDimitry Andric isStrongDefinitionForLinker() && 1310b57cec5SDimitry Andric // It is not safe to modify initializers of global variables with the 1320b57cec5SDimitry Andric // external_initializer marker since the value may be changed at runtime 1330b57cec5SDimitry Andric // before C++ initializers are evaluated. 1340b57cec5SDimitry Andric !isExternallyInitialized(); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric /// getInitializer - Return the initializer for this global variable. It is 1380b57cec5SDimitry Andric /// illegal to call this method if the global is external, because we cannot 1390b57cec5SDimitry Andric /// tell what the value is initialized to! 1400b57cec5SDimitry Andric /// 1410b57cec5SDimitry Andric inline const Constant *getInitializer() const { 1420b57cec5SDimitry Andric assert(hasInitializer() && "GV doesn't have initializer!"); 1430b57cec5SDimitry Andric return static_cast<Constant*>(Op<0>().get()); 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric inline Constant *getInitializer() { 1460b57cec5SDimitry Andric assert(hasInitializer() && "GV doesn't have initializer!"); 1470b57cec5SDimitry Andric return static_cast<Constant*>(Op<0>().get()); 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric /// setInitializer - Sets the initializer for this global variable, removing 1500b57cec5SDimitry Andric /// any existing initializer if InitVal==NULL. If this GV has type T*, the 1510b57cec5SDimitry Andric /// initializer must have type T. 1520b57cec5SDimitry Andric void setInitializer(Constant *InitVal); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric /// If the value is a global constant, its value is immutable throughout the 1550b57cec5SDimitry Andric /// runtime execution of the program. Assigning a value into the constant 1560b57cec5SDimitry Andric /// leads to undefined behavior. 1570b57cec5SDimitry Andric /// 1580b57cec5SDimitry Andric bool isConstant() const { return isConstantGlobal; } 1590b57cec5SDimitry Andric void setConstant(bool Val) { isConstantGlobal = Val; } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric bool isExternallyInitialized() const { 1620b57cec5SDimitry Andric return isExternallyInitializedConstant; 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric void setExternallyInitialized(bool Val) { 1650b57cec5SDimitry Andric isExternallyInitializedConstant = Val; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric /// copyAttributesFrom - copy all additional attributes (those not needed to 1690b57cec5SDimitry Andric /// create a GlobalVariable) from the GlobalVariable Src to this one. 1700b57cec5SDimitry Andric void copyAttributesFrom(const GlobalVariable *Src); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric /// removeFromParent - This method unlinks 'this' from the containing module, 1730b57cec5SDimitry Andric /// but does not delete it. 1740b57cec5SDimitry Andric /// 1750b57cec5SDimitry Andric void removeFromParent(); 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric /// eraseFromParent - This method unlinks 'this' from the containing module 1780b57cec5SDimitry Andric /// and deletes it. 1790b57cec5SDimitry Andric /// 1800b57cec5SDimitry Andric void eraseFromParent(); 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric /// Drop all references in preparation to destroy the GlobalVariable. This 1830b57cec5SDimitry Andric /// drops not only the reference to the initializer but also to any metadata. 1840b57cec5SDimitry Andric void dropAllReferences(); 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric /// Attach a DIGlobalVariableExpression. 1870b57cec5SDimitry Andric void addDebugInfo(DIGlobalVariableExpression *GV); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric /// Fill the vector with all debug info attachements. 1900b57cec5SDimitry Andric void getDebugInfo(SmallVectorImpl<DIGlobalVariableExpression *> &GVs) const; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric /// Add attribute to this global. 1930b57cec5SDimitry Andric void addAttribute(Attribute::AttrKind Kind) { 1940b57cec5SDimitry Andric Attrs = Attrs.addAttribute(getContext(), Kind); 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric /// Add attribute to this global. 1980b57cec5SDimitry Andric void addAttribute(StringRef Kind, StringRef Val = StringRef()) { 1990b57cec5SDimitry Andric Attrs = Attrs.addAttribute(getContext(), Kind, Val); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric /// Return true if the attribute exists. 2030b57cec5SDimitry Andric bool hasAttribute(Attribute::AttrKind Kind) const { 2040b57cec5SDimitry Andric return Attrs.hasAttribute(Kind); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric /// Return true if the attribute exists. 2080b57cec5SDimitry Andric bool hasAttribute(StringRef Kind) const { 2090b57cec5SDimitry Andric return Attrs.hasAttribute(Kind); 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric /// Return true if any attributes exist. 2130b57cec5SDimitry Andric bool hasAttributes() const { 2140b57cec5SDimitry Andric return Attrs.hasAttributes(); 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric /// Return the attribute object. 2180b57cec5SDimitry Andric Attribute getAttribute(Attribute::AttrKind Kind) const { 2190b57cec5SDimitry Andric return Attrs.getAttribute(Kind); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric /// Return the attribute object. 2230b57cec5SDimitry Andric Attribute getAttribute(StringRef Kind) const { 2240b57cec5SDimitry Andric return Attrs.getAttribute(Kind); 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric /// Return the attribute set for this global 2280b57cec5SDimitry Andric AttributeSet getAttributes() const { 2290b57cec5SDimitry Andric return Attrs; 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric /// Return attribute set as list with index. 2330b57cec5SDimitry Andric /// FIXME: This may not be required once ValueEnumerators 2340b57cec5SDimitry Andric /// in bitcode-writer can enumerate attribute-set. 2350b57cec5SDimitry Andric AttributeList getAttributesAsList(unsigned index) const { 2360b57cec5SDimitry Andric if (!hasAttributes()) 2370b57cec5SDimitry Andric return AttributeList(); 2380b57cec5SDimitry Andric std::pair<unsigned, AttributeSet> AS[1] = {{index, Attrs}}; 2390b57cec5SDimitry Andric return AttributeList::get(getContext(), AS); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric /// Set attribute list for this global 2430b57cec5SDimitry Andric void setAttributes(AttributeSet A) { 2440b57cec5SDimitry Andric Attrs = A; 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric /// Check if section name is present 2480b57cec5SDimitry Andric bool hasImplicitSection() const { 2490b57cec5SDimitry Andric return getAttributes().hasAttribute("bss-section") || 2500b57cec5SDimitry Andric getAttributes().hasAttribute("data-section") || 2518bcb0991SDimitry Andric getAttributes().hasAttribute("relro-section") || 2520b57cec5SDimitry Andric getAttributes().hasAttribute("rodata-section"); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 255*5f757f3fSDimitry Andric /// Get the custom code model raw value of this global. 256*5f757f3fSDimitry Andric /// 257*5f757f3fSDimitry Andric unsigned getCodeModelRaw() const { 258*5f757f3fSDimitry Andric unsigned Data = getGlobalValueSubClassData(); 259*5f757f3fSDimitry Andric return (Data >> CodeModelShift) & CodeModelMask; 260*5f757f3fSDimitry Andric } 261*5f757f3fSDimitry Andric 262*5f757f3fSDimitry Andric /// Get the custom code model of this global if it has one. 263*5f757f3fSDimitry Andric /// 264*5f757f3fSDimitry Andric /// If this global does not have a custom code model, the empty instance 265*5f757f3fSDimitry Andric /// will be returned. 266*5f757f3fSDimitry Andric std::optional<CodeModel::Model> getCodeModel() const { 267*5f757f3fSDimitry Andric unsigned CodeModelData = getCodeModelRaw(); 268*5f757f3fSDimitry Andric if (CodeModelData > 0) 269*5f757f3fSDimitry Andric return static_cast<CodeModel::Model>(CodeModelData - 1); 270*5f757f3fSDimitry Andric return {}; 271*5f757f3fSDimitry Andric } 272*5f757f3fSDimitry Andric 273*5f757f3fSDimitry Andric /// Change the code model for this global. 274*5f757f3fSDimitry Andric /// 275*5f757f3fSDimitry Andric void setCodeModel(CodeModel::Model CM); 276*5f757f3fSDimitry Andric 2770b57cec5SDimitry Andric // Methods for support type inquiry through isa, cast, and dyn_cast: 2780b57cec5SDimitry Andric static bool classof(const Value *V) { 2790b57cec5SDimitry Andric return V->getValueID() == Value::GlobalVariableVal; 2800b57cec5SDimitry Andric } 2810b57cec5SDimitry Andric }; 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric template <> 2840b57cec5SDimitry Andric struct OperandTraits<GlobalVariable> : 2850b57cec5SDimitry Andric public OptionalOperandTraits<GlobalVariable> { 2860b57cec5SDimitry Andric }; 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GlobalVariable, Value) 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric } // end namespace llvm 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric #endif // LLVM_IR_GLOBALVARIABLE_H 293