| 1 | //===- Module.cpp - Implement the Module class ----------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file implements the Module class for the IR library. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "llvm/IR/Module.h" |
| 14 | #include "SymbolTableListTraitsImpl.h" |
| 15 | #include "llvm/ADT/SmallString.h" |
| 16 | #include "llvm/ADT/SmallVector.h" |
| 17 | #include "llvm/ADT/StringMap.h" |
| 18 | #include "llvm/ADT/StringRef.h" |
| 19 | #include "llvm/ADT/Twine.h" |
| 20 | #include "llvm/IR/Attributes.h" |
| 21 | #include "llvm/IR/Comdat.h" |
| 22 | #include "llvm/IR/Constants.h" |
| 23 | #include "llvm/IR/DataLayout.h" |
| 24 | #include "llvm/IR/DebugInfoMetadata.h" |
| 25 | #include "llvm/IR/DerivedTypes.h" |
| 26 | #include "llvm/IR/Function.h" |
| 27 | #include "llvm/IR/GVMaterializer.h" |
| 28 | #include "llvm/IR/GlobalAlias.h" |
| 29 | #include "llvm/IR/GlobalIFunc.h" |
| 30 | #include "llvm/IR/GlobalValue.h" |
| 31 | #include "llvm/IR/GlobalVariable.h" |
| 32 | #include "llvm/IR/LLVMContext.h" |
| 33 | #include "llvm/IR/Metadata.h" |
| 34 | #include "llvm/IR/ModuleSummaryIndex.h" |
| 35 | #include "llvm/IR/SymbolTableListTraits.h" |
| 36 | #include "llvm/IR/Type.h" |
| 37 | #include "llvm/IR/TypeFinder.h" |
| 38 | #include "llvm/IR/Value.h" |
| 39 | #include "llvm/IR/ValueSymbolTable.h" |
| 40 | #include "llvm/Support/Casting.h" |
| 41 | #include "llvm/Support/CodeGen.h" |
| 42 | #include "llvm/Support/Compiler.h" |
| 43 | #include "llvm/Support/Error.h" |
| 44 | #include "llvm/Support/MemoryBuffer.h" |
| 45 | #include "llvm/Support/Path.h" |
| 46 | #include "llvm/Support/RandomNumberGenerator.h" |
| 47 | #include "llvm/Support/VersionTuple.h" |
| 48 | #include <cassert> |
| 49 | #include <cstdint> |
| 50 | #include <memory> |
| 51 | #include <optional> |
| 52 | #include <utility> |
| 53 | #include <vector> |
| 54 | |
| 55 | using namespace llvm; |
| 56 | |
| 57 | //===----------------------------------------------------------------------===// |
| 58 | // Methods to implement the globals and functions lists. |
| 59 | // |
| 60 | |
| 61 | // Explicit instantiations of SymbolTableListTraits since some of the methods |
| 62 | // are not in the public header file. |
| 63 | template class LLVM_EXPORT_TEMPLATE llvm::SymbolTableListTraits<Function>; |
| 64 | template class LLVM_EXPORT_TEMPLATE llvm::SymbolTableListTraits<GlobalVariable>; |
| 65 | template class LLVM_EXPORT_TEMPLATE llvm::SymbolTableListTraits<GlobalAlias>; |
| 66 | template class LLVM_EXPORT_TEMPLATE llvm::SymbolTableListTraits<GlobalIFunc>; |
| 67 | |
| 68 | //===----------------------------------------------------------------------===// |
| 69 | // Primitive Module methods. |
| 70 | // |
| 71 | |
| 72 | Module::Module(StringRef MID, LLVMContext &C) |
| 73 | : Context(C), ValSymTab(std::make_unique<ValueSymbolTable>(args: -1)), |
| 74 | ModuleID(std::string(MID)), SourceFileName(std::string(MID)) { |
| 75 | Context.addModule(this); |
| 76 | } |
| 77 | |
| 78 | Module &Module::operator=(Module &&Other) { |
| 79 | assert(&Context == &Other.Context && "Module must be in the same Context" ); |
| 80 | |
| 81 | dropAllReferences(); |
| 82 | |
| 83 | ModuleID = std::move(Other.ModuleID); |
| 84 | SourceFileName = std::move(Other.SourceFileName); |
| 85 | |
| 86 | GlobalList.clear(); |
| 87 | GlobalList.splice(where: GlobalList.begin(), L2&: Other.GlobalList); |
| 88 | |
| 89 | FunctionList.clear(); |
| 90 | FunctionList.splice(where: FunctionList.begin(), L2&: Other.FunctionList); |
| 91 | |
| 92 | AliasList.clear(); |
| 93 | AliasList.splice(where: AliasList.begin(), L2&: Other.AliasList); |
| 94 | |
| 95 | IFuncList.clear(); |
| 96 | IFuncList.splice(where: IFuncList.begin(), L2&: Other.IFuncList); |
| 97 | |
| 98 | NamedMDList.clear(); |
| 99 | NamedMDList.splice(where: NamedMDList.begin(), L2&: Other.NamedMDList); |
| 100 | GlobalScopeAsm = std::move(Other.GlobalScopeAsm); |
| 101 | OwnedMemoryBuffer = std::move(Other.OwnedMemoryBuffer); |
| 102 | Materializer = std::move(Other.Materializer); |
| 103 | TargetTriple = std::move(Other.TargetTriple); |
| 104 | DL = std::move(Other.DL); |
| 105 | CurrentIntrinsicIds = std::move(Other.CurrentIntrinsicIds); |
| 106 | UniquedIntrinsicNames = std::move(Other.UniquedIntrinsicNames); |
| 107 | ModuleFlags = std::move(Other.ModuleFlags); |
| 108 | Context.addModule(this); |
| 109 | return *this; |
| 110 | } |
| 111 | |
| 112 | Module::~Module() { |
| 113 | Context.removeModule(this); |
| 114 | dropAllReferences(); |
| 115 | GlobalList.clear(); |
| 116 | FunctionList.clear(); |
| 117 | AliasList.clear(); |
| 118 | IFuncList.clear(); |
| 119 | } |
| 120 | |
| 121 | void Module::removeDebugIntrinsicDeclarations() { |
| 122 | if (auto *DeclareIntrinsicFn = |
| 123 | Intrinsic::getDeclarationIfExists(M: this, id: Intrinsic::dbg_declare)) { |
| 124 | assert((!isMaterialized() || DeclareIntrinsicFn->hasZeroLiveUses()) && |
| 125 | "Debug declare intrinsic should have had uses removed." ); |
| 126 | DeclareIntrinsicFn->eraseFromParent(); |
| 127 | } |
| 128 | if (auto *ValueIntrinsicFn = |
| 129 | Intrinsic::getDeclarationIfExists(M: this, id: Intrinsic::dbg_value)) { |
| 130 | assert((!isMaterialized() || ValueIntrinsicFn->hasZeroLiveUses()) && |
| 131 | "Debug value intrinsic should have had uses removed." ); |
| 132 | ValueIntrinsicFn->eraseFromParent(); |
| 133 | } |
| 134 | if (auto *AssignIntrinsicFn = |
| 135 | Intrinsic::getDeclarationIfExists(M: this, id: Intrinsic::dbg_assign)) { |
| 136 | assert((!isMaterialized() || AssignIntrinsicFn->hasZeroLiveUses()) && |
| 137 | "Debug assign intrinsic should have had uses removed." ); |
| 138 | AssignIntrinsicFn->eraseFromParent(); |
| 139 | } |
| 140 | if (auto *LabelntrinsicFn = |
| 141 | Intrinsic::getDeclarationIfExists(M: this, id: Intrinsic::dbg_label)) { |
| 142 | assert((!isMaterialized() || LabelntrinsicFn->hasZeroLiveUses()) && |
| 143 | "Debug label intrinsic should have had uses removed." ); |
| 144 | LabelntrinsicFn->eraseFromParent(); |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | std::unique_ptr<RandomNumberGenerator> |
| 149 | Module::createRNG(const StringRef Name) const { |
| 150 | SmallString<32> Salt(Name); |
| 151 | |
| 152 | // This RNG is guaranteed to produce the same random stream only |
| 153 | // when the Module ID and thus the input filename is the same. This |
| 154 | // might be problematic if the input filename extension changes |
| 155 | // (e.g. from .c to .bc or .ll). |
| 156 | // |
| 157 | // We could store this salt in NamedMetadata, but this would make |
| 158 | // the parameter non-const. This would unfortunately make this |
| 159 | // interface unusable by any Machine passes, since they only have a |
| 160 | // const reference to their IR Module. Alternatively we can always |
| 161 | // store salt metadata from the Module constructor. |
| 162 | Salt += sys::path::filename(path: getModuleIdentifier()); |
| 163 | |
| 164 | return std::unique_ptr<RandomNumberGenerator>( |
| 165 | new RandomNumberGenerator(Salt)); |
| 166 | } |
| 167 | |
| 168 | /// getNamedValue - Return the first global value in the module with |
| 169 | /// the specified name, of arbitrary type. This method returns null |
| 170 | /// if a global with the specified name is not found. |
| 171 | GlobalValue *Module::getNamedValue(StringRef Name) const { |
| 172 | return cast_or_null<GlobalValue>(Val: getValueSymbolTable().lookup(Name)); |
| 173 | } |
| 174 | |
| 175 | unsigned Module::getNumNamedValues() const { |
| 176 | return getValueSymbolTable().size(); |
| 177 | } |
| 178 | |
| 179 | /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. |
| 180 | /// This ID is uniqued across modules in the current LLVMContext. |
| 181 | unsigned Module::getMDKindID(StringRef Name) const { |
| 182 | return Context.getMDKindID(Name); |
| 183 | } |
| 184 | |
| 185 | /// getMDKindNames - Populate client supplied SmallVector with the name for |
| 186 | /// custom metadata IDs registered in this LLVMContext. ID #0 is not used, |
| 187 | /// so it is filled in as an empty string. |
| 188 | void Module::getMDKindNames(SmallVectorImpl<StringRef> &Result) const { |
| 189 | return Context.getMDKindNames(Result); |
| 190 | } |
| 191 | |
| 192 | void Module::getOperandBundleTags(SmallVectorImpl<StringRef> &Result) const { |
| 193 | return Context.getOperandBundleTags(Result); |
| 194 | } |
| 195 | |
| 196 | //===----------------------------------------------------------------------===// |
| 197 | // Methods for easy access to the functions in the module. |
| 198 | // |
| 199 | |
| 200 | // getOrInsertFunction - Look up the specified function in the module symbol |
| 201 | // table. If it does not exist, add a prototype for the function and return |
| 202 | // it. This is nice because it allows most passes to get away with not handling |
| 203 | // the symbol table directly for this common task. |
| 204 | // |
| 205 | FunctionCallee Module::getOrInsertFunction(StringRef Name, FunctionType *Ty, |
| 206 | AttributeList AttributeList) { |
| 207 | // See if we have a definition for the specified function already. |
| 208 | GlobalValue *F = getNamedValue(Name); |
| 209 | if (!F) { |
| 210 | // Nope, add it |
| 211 | Function *New = Function::Create(Ty, Linkage: GlobalVariable::ExternalLinkage, |
| 212 | AddrSpace: DL.getProgramAddressSpace(), N: Name, M: this); |
| 213 | if (!New->isIntrinsic()) // Intrinsics get attrs set on construction |
| 214 | New->setAttributes(AttributeList); |
| 215 | return {Ty, New}; // Return the new prototype. |
| 216 | } |
| 217 | |
| 218 | // Otherwise, we just found the existing function or a prototype. |
| 219 | return {Ty, F}; |
| 220 | } |
| 221 | |
| 222 | FunctionCallee Module::getOrInsertFunction(StringRef Name, FunctionType *Ty) { |
| 223 | return getOrInsertFunction(Name, Ty, AttributeList: AttributeList()); |
| 224 | } |
| 225 | |
| 226 | // getFunction - Look up the specified function in the module symbol table. |
| 227 | // If it does not exist, return null. |
| 228 | // |
| 229 | Function *Module::getFunction(StringRef Name) const { |
| 230 | return dyn_cast_or_null<Function>(Val: getNamedValue(Name)); |
| 231 | } |
| 232 | |
| 233 | //===----------------------------------------------------------------------===// |
| 234 | // Methods for easy access to the global variables in the module. |
| 235 | // |
| 236 | |
| 237 | /// getGlobalVariable - Look up the specified global variable in the module |
| 238 | /// symbol table. If it does not exist, return null. The type argument |
| 239 | /// should be the underlying type of the global, i.e., it should not have |
| 240 | /// the top-level PointerType, which represents the address of the global. |
| 241 | /// If AllowLocal is set to true, this function will return types that |
| 242 | /// have an local. By default, these types are not returned. |
| 243 | /// |
| 244 | GlobalVariable *Module::getGlobalVariable(StringRef Name, |
| 245 | bool AllowLocal) const { |
| 246 | if (GlobalVariable *Result = |
| 247 | dyn_cast_or_null<GlobalVariable>(Val: getNamedValue(Name))) |
| 248 | if (AllowLocal || !Result->hasLocalLinkage()) |
| 249 | return Result; |
| 250 | return nullptr; |
| 251 | } |
| 252 | |
| 253 | /// getOrInsertGlobal - Look up the specified global in the module symbol table. |
| 254 | /// If it does not exist, add a declaration of the global and return it. |
| 255 | /// Otherwise, return the existing global. |
| 256 | GlobalVariable *Module::getOrInsertGlobal( |
| 257 | StringRef Name, Type *Ty, |
| 258 | function_ref<GlobalVariable *()> CreateGlobalCallback) { |
| 259 | // See if we have a definition for the specified global already. |
| 260 | GlobalVariable *GV = dyn_cast_or_null<GlobalVariable>(Val: getNamedValue(Name)); |
| 261 | if (!GV) |
| 262 | GV = CreateGlobalCallback(); |
| 263 | assert(GV && "The CreateGlobalCallback is expected to create a global" ); |
| 264 | |
| 265 | // Otherwise, we just found the existing function or a prototype. |
| 266 | return GV; |
| 267 | } |
| 268 | |
| 269 | // Overload to construct a global variable using its constructor's defaults. |
| 270 | GlobalVariable *Module::getOrInsertGlobal(StringRef Name, Type *Ty) { |
| 271 | return getOrInsertGlobal(Name, Ty, CreateGlobalCallback: [&] { |
| 272 | return new GlobalVariable(*this, Ty, false, GlobalVariable::ExternalLinkage, |
| 273 | nullptr, Name); |
| 274 | }); |
| 275 | } |
| 276 | |
| 277 | //===----------------------------------------------------------------------===// |
| 278 | // Methods for easy access to the global variables in the module. |
| 279 | // |
| 280 | |
| 281 | // getNamedAlias - Look up the specified global in the module symbol table. |
| 282 | // If it does not exist, return null. |
| 283 | // |
| 284 | GlobalAlias *Module::getNamedAlias(StringRef Name) const { |
| 285 | return dyn_cast_or_null<GlobalAlias>(Val: getNamedValue(Name)); |
| 286 | } |
| 287 | |
| 288 | GlobalIFunc *Module::getNamedIFunc(StringRef Name) const { |
| 289 | return dyn_cast_or_null<GlobalIFunc>(Val: getNamedValue(Name)); |
| 290 | } |
| 291 | |
| 292 | /// getNamedMetadata - Return the first NamedMDNode in the module with the |
| 293 | /// specified name. This method returns null if a NamedMDNode with the |
| 294 | /// specified name is not found. |
| 295 | NamedMDNode *Module::getNamedMetadata(StringRef Name) const { |
| 296 | return NamedMDSymTab.lookup(Key: Name); |
| 297 | } |
| 298 | |
| 299 | /// getOrInsertNamedMetadata - Return the first named MDNode in the module |
| 300 | /// with the specified name. This method returns a new NamedMDNode if a |
| 301 | /// NamedMDNode with the specified name is not found. |
| 302 | NamedMDNode *Module::getOrInsertNamedMetadata(StringRef Name) { |
| 303 | NamedMDNode *&NMD = NamedMDSymTab[Name]; |
| 304 | if (!NMD) { |
| 305 | NMD = new NamedMDNode(Name); |
| 306 | NMD->setParent(this); |
| 307 | insertNamedMDNode(MDNode: NMD); |
| 308 | if (Name == "llvm.module.flags" ) |
| 309 | ModuleFlags = NMD; |
| 310 | } |
| 311 | return NMD; |
| 312 | } |
| 313 | |
| 314 | /// eraseNamedMetadata - Remove the given NamedMDNode from this module and |
| 315 | /// delete it. |
| 316 | void Module::eraseNamedMetadata(NamedMDNode *NMD) { |
| 317 | NamedMDSymTab.erase(Key: NMD->getName()); |
| 318 | if (NMD == ModuleFlags) |
| 319 | ModuleFlags = nullptr; |
| 320 | eraseNamedMDNode(MDNode: NMD); |
| 321 | } |
| 322 | |
| 323 | bool Module::isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB) { |
| 324 | if (ConstantInt *Behavior = mdconst::dyn_extract_or_null<ConstantInt>(MD)) { |
| 325 | uint64_t Val = Behavior->getLimitedValue(); |
| 326 | if (Val >= ModFlagBehaviorFirstVal && Val <= ModFlagBehaviorLastVal) { |
| 327 | MFB = static_cast<ModFlagBehavior>(Val); |
| 328 | return true; |
| 329 | } |
| 330 | } |
| 331 | return false; |
| 332 | } |
| 333 | |
| 334 | /// getModuleFlagsMetadata - Returns the module flags in the provided vector. |
| 335 | void Module:: |
| 336 | getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const { |
| 337 | const NamedMDNode *ModFlags = getModuleFlagsMetadata(); |
| 338 | if (!ModFlags) return; |
| 339 | |
| 340 | for (const MDNode *Flag : ModFlags->operands()) { |
| 341 | // The verifier will catch errors, so no need to check them here. |
| 342 | auto *MFBConstant = mdconst::extract<ConstantInt>(MD: Flag->getOperand(I: 0)); |
| 343 | auto MFB = static_cast<ModFlagBehavior>(MFBConstant->getLimitedValue()); |
| 344 | MDString *Key = cast<MDString>(Val: Flag->getOperand(I: 1)); |
| 345 | Metadata *Val = Flag->getOperand(I: 2); |
| 346 | Flags.push_back(Elt: ModuleFlagEntry(MFB, Key, Val)); |
| 347 | } |
| 348 | } |
| 349 | |
| 350 | /// Return the corresponding value if Key appears in module flags, otherwise |
| 351 | /// return null. |
| 352 | Metadata *Module::getModuleFlag(StringRef Key) const { |
| 353 | const NamedMDNode *ModFlags = getModuleFlagsMetadata(); |
| 354 | if (!ModFlags) |
| 355 | return nullptr; |
| 356 | for (const MDNode *Flag : ModFlags->operands()) { |
| 357 | if (Key == cast<MDString>(Val: Flag->getOperand(I: 1))->getString()) |
| 358 | return Flag->getOperand(I: 2); |
| 359 | } |
| 360 | return nullptr; |
| 361 | } |
| 362 | |
| 363 | /// getOrInsertModuleFlagsMetadata - Returns the NamedMDNode in the module that |
| 364 | /// represents module-level flags. If module-level flags aren't found, it |
| 365 | /// creates the named metadata that contains them. |
| 366 | NamedMDNode *Module::getOrInsertModuleFlagsMetadata() { |
| 367 | if (ModuleFlags) |
| 368 | return ModuleFlags; |
| 369 | return getOrInsertNamedMetadata(Name: "llvm.module.flags" ); |
| 370 | } |
| 371 | |
| 372 | /// addModuleFlag - Add a module-level flag to the module-level flags |
| 373 | /// metadata. It will create the module-level flags named metadata if it doesn't |
| 374 | /// already exist. |
| 375 | void Module::addModuleFlag(ModFlagBehavior Behavior, StringRef Key, |
| 376 | Metadata *Val) { |
| 377 | Type *Int32Ty = Type::getInt32Ty(C&: Context); |
| 378 | Metadata *Ops[3] = { |
| 379 | ConstantAsMetadata::get(C: ConstantInt::get(Ty: Int32Ty, V: Behavior)), |
| 380 | MDString::get(Context, Str: Key), Val}; |
| 381 | getOrInsertModuleFlagsMetadata()->addOperand(M: MDNode::get(Context, MDs: Ops)); |
| 382 | } |
| 383 | void Module::addModuleFlag(ModFlagBehavior Behavior, StringRef Key, |
| 384 | Constant *Val) { |
| 385 | addModuleFlag(Behavior, Key, Val: ConstantAsMetadata::get(C: Val)); |
| 386 | } |
| 387 | void Module::addModuleFlag(ModFlagBehavior Behavior, StringRef Key, |
| 388 | uint32_t Val) { |
| 389 | Type *Int32Ty = Type::getInt32Ty(C&: Context); |
| 390 | addModuleFlag(Behavior, Key, Val: ConstantInt::get(Ty: Int32Ty, V: Val)); |
| 391 | } |
| 392 | void Module::addModuleFlag(MDNode *Node) { |
| 393 | assert(Node->getNumOperands() == 3 && |
| 394 | "Invalid number of operands for module flag!" ); |
| 395 | assert(mdconst::hasa<ConstantInt>(Node->getOperand(0)) && |
| 396 | isa<MDString>(Node->getOperand(1)) && |
| 397 | "Invalid operand types for module flag!" ); |
| 398 | getOrInsertModuleFlagsMetadata()->addOperand(M: Node); |
| 399 | } |
| 400 | |
| 401 | void Module::setModuleFlag(ModFlagBehavior Behavior, StringRef Key, |
| 402 | Metadata *Val) { |
| 403 | NamedMDNode *ModFlags = getOrInsertModuleFlagsMetadata(); |
| 404 | // Replace the flag if it already exists. |
| 405 | for (MDNode *Flag : ModFlags->operands()) { |
| 406 | if (cast<MDString>(Val: Flag->getOperand(I: 1))->getString() == Key) { |
| 407 | Flag->replaceOperandWith(I: 2, New: Val); |
| 408 | return; |
| 409 | } |
| 410 | } |
| 411 | addModuleFlag(Behavior, Key, Val); |
| 412 | } |
| 413 | void Module::setModuleFlag(ModFlagBehavior Behavior, StringRef Key, |
| 414 | Constant *Val) { |
| 415 | setModuleFlag(Behavior, Key, Val: ConstantAsMetadata::get(C: Val)); |
| 416 | } |
| 417 | void Module::setModuleFlag(ModFlagBehavior Behavior, StringRef Key, |
| 418 | uint32_t Val) { |
| 419 | Type *Int32Ty = Type::getInt32Ty(C&: Context); |
| 420 | setModuleFlag(Behavior, Key, Val: ConstantInt::get(Ty: Int32Ty, V: Val)); |
| 421 | } |
| 422 | |
| 423 | void Module::setDataLayout(StringRef Desc) { DL = DataLayout(Desc); } |
| 424 | |
| 425 | void Module::setDataLayout(const DataLayout &Other) { DL = Other; } |
| 426 | |
| 427 | DICompileUnit *Module::debug_compile_units_iterator::operator*() const { |
| 428 | return cast<DICompileUnit>(Val: CUs->getOperand(i: Idx)); |
| 429 | } |
| 430 | DICompileUnit *Module::debug_compile_units_iterator::operator->() const { |
| 431 | return cast<DICompileUnit>(Val: CUs->getOperand(i: Idx)); |
| 432 | } |
| 433 | |
| 434 | void Module::debug_compile_units_iterator::SkipNoDebugCUs() { |
| 435 | while (CUs && (Idx < CUs->getNumOperands()) && |
| 436 | ((*this)->getEmissionKind() == DICompileUnit::NoDebug)) |
| 437 | ++Idx; |
| 438 | } |
| 439 | |
| 440 | iterator_range<Module::global_object_iterator> Module::global_objects() { |
| 441 | return concat<GlobalObject>(Ranges: functions(), Ranges: globals()); |
| 442 | } |
| 443 | iterator_range<Module::const_global_object_iterator> |
| 444 | Module::global_objects() const { |
| 445 | return concat<const GlobalObject>(Ranges: functions(), Ranges: globals()); |
| 446 | } |
| 447 | |
| 448 | iterator_range<Module::global_value_iterator> Module::global_values() { |
| 449 | return concat<GlobalValue>(Ranges: functions(), Ranges: globals(), Ranges: aliases(), Ranges: ifuncs()); |
| 450 | } |
| 451 | iterator_range<Module::const_global_value_iterator> |
| 452 | Module::global_values() const { |
| 453 | return concat<const GlobalValue>(Ranges: functions(), Ranges: globals(), Ranges: aliases(), Ranges: ifuncs()); |
| 454 | } |
| 455 | |
| 456 | //===----------------------------------------------------------------------===// |
| 457 | // Methods to control the materialization of GlobalValues in the Module. |
| 458 | // |
| 459 | void Module::setMaterializer(GVMaterializer *GVM) { |
| 460 | assert(!Materializer && |
| 461 | "Module already has a GVMaterializer. Call materializeAll" |
| 462 | " to clear it out before setting another one." ); |
| 463 | Materializer.reset(p: GVM); |
| 464 | } |
| 465 | |
| 466 | Error Module::materialize(GlobalValue *GV) { |
| 467 | if (!Materializer) |
| 468 | return Error::success(); |
| 469 | |
| 470 | return Materializer->materialize(GV); |
| 471 | } |
| 472 | |
| 473 | Error Module::materializeAll() { |
| 474 | if (!Materializer) |
| 475 | return Error::success(); |
| 476 | std::unique_ptr<GVMaterializer> M = std::move(Materializer); |
| 477 | return M->materializeModule(); |
| 478 | } |
| 479 | |
| 480 | Error Module::materializeMetadata() { |
| 481 | if (!Materializer) |
| 482 | return Error::success(); |
| 483 | return Materializer->materializeMetadata(); |
| 484 | } |
| 485 | |
| 486 | //===----------------------------------------------------------------------===// |
| 487 | // Other module related stuff. |
| 488 | // |
| 489 | |
| 490 | std::vector<StructType *> Module::getIdentifiedStructTypes() const { |
| 491 | // If we have a materializer, it is possible that some unread function |
| 492 | // uses a type that is currently not visible to a TypeFinder, so ask |
| 493 | // the materializer which types it created. |
| 494 | if (Materializer) |
| 495 | return Materializer->getIdentifiedStructTypes(); |
| 496 | |
| 497 | std::vector<StructType *> Ret; |
| 498 | TypeFinder SrcStructTypes; |
| 499 | SrcStructTypes.run(M: *this, onlyNamed: true); |
| 500 | Ret.assign(first: SrcStructTypes.begin(), last: SrcStructTypes.end()); |
| 501 | return Ret; |
| 502 | } |
| 503 | |
| 504 | std::string Module::getUniqueIntrinsicName(StringRef BaseName, Intrinsic::ID Id, |
| 505 | const FunctionType *Proto) { |
| 506 | auto Encode = [&BaseName](unsigned Suffix) { |
| 507 | return (Twine(BaseName) + "." + Twine(Suffix)).str(); |
| 508 | }; |
| 509 | |
| 510 | { |
| 511 | // fast path - the prototype is already known |
| 512 | auto UinItInserted = UniquedIntrinsicNames.insert(KV: {{Id, Proto}, 0}); |
| 513 | if (!UinItInserted.second) |
| 514 | return Encode(UinItInserted.first->second); |
| 515 | } |
| 516 | |
| 517 | // Not known yet. A new entry was created with index 0. Check if there already |
| 518 | // exists a matching declaration, or select a new entry. |
| 519 | |
| 520 | // Start looking for names with the current known maximum count (or 0). |
| 521 | auto NiidItInserted = CurrentIntrinsicIds.insert(KV: {BaseName, 0}); |
| 522 | unsigned Count = NiidItInserted.first->second; |
| 523 | |
| 524 | // This might be slow if a whole population of intrinsics already existed, but |
| 525 | // we cache the values for later usage. |
| 526 | std::string NewName; |
| 527 | while (true) { |
| 528 | NewName = Encode(Count); |
| 529 | GlobalValue *F = getNamedValue(Name: NewName); |
| 530 | if (!F) { |
| 531 | // Reserve this entry for the new proto |
| 532 | UniquedIntrinsicNames[{Id, Proto}] = Count; |
| 533 | break; |
| 534 | } |
| 535 | |
| 536 | // A declaration with this name already exists. Remember it. |
| 537 | FunctionType *FT = dyn_cast<FunctionType>(Val: F->getValueType()); |
| 538 | auto UinItInserted = UniquedIntrinsicNames.insert(KV: {{Id, FT}, Count}); |
| 539 | if (FT == Proto) { |
| 540 | // It was a declaration for our prototype. This entry was allocated in the |
| 541 | // beginning. Update the count to match the existing declaration. |
| 542 | UinItInserted.first->second = Count; |
| 543 | break; |
| 544 | } |
| 545 | |
| 546 | ++Count; |
| 547 | } |
| 548 | |
| 549 | NiidItInserted.first->second = Count + 1; |
| 550 | |
| 551 | return NewName; |
| 552 | } |
| 553 | |
| 554 | // dropAllReferences() - This function causes all the subelements to "let go" |
| 555 | // of all references that they are maintaining. This allows one to 'delete' a |
| 556 | // whole module at a time, even though there may be circular references... first |
| 557 | // all references are dropped, and all use counts go to zero. Then everything |
| 558 | // is deleted for real. Note that no operations are valid on an object that |
| 559 | // has "dropped all references", except operator delete. |
| 560 | // |
| 561 | void Module::dropAllReferences() { |
| 562 | for (Function &F : *this) |
| 563 | F.dropAllReferences(); |
| 564 | |
| 565 | for (GlobalVariable &GV : globals()) |
| 566 | GV.dropAllReferences(); |
| 567 | |
| 568 | for (GlobalAlias &GA : aliases()) |
| 569 | GA.dropAllReferences(); |
| 570 | |
| 571 | for (GlobalIFunc &GIF : ifuncs()) |
| 572 | GIF.dropAllReferences(); |
| 573 | } |
| 574 | |
| 575 | unsigned Module::getNumberRegisterParameters() const { |
| 576 | auto *Val = |
| 577 | cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "NumRegisterParameters" )); |
| 578 | if (!Val) |
| 579 | return 0; |
| 580 | return cast<ConstantInt>(Val: Val->getValue())->getZExtValue(); |
| 581 | } |
| 582 | |
| 583 | unsigned Module::getDwarfVersion() const { |
| 584 | auto *Val = cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "Dwarf Version" )); |
| 585 | if (!Val) |
| 586 | return 0; |
| 587 | return cast<ConstantInt>(Val: Val->getValue())->getZExtValue(); |
| 588 | } |
| 589 | |
| 590 | bool Module::isDwarf64() const { |
| 591 | auto *Val = cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "DWARF64" )); |
| 592 | return Val && cast<ConstantInt>(Val: Val->getValue())->isOne(); |
| 593 | } |
| 594 | |
| 595 | unsigned Module::getCodeViewFlag() const { |
| 596 | auto *Val = cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "CodeView" )); |
| 597 | if (!Val) |
| 598 | return 0; |
| 599 | return cast<ConstantInt>(Val: Val->getValue())->getZExtValue(); |
| 600 | } |
| 601 | |
| 602 | unsigned Module::getInstructionCount() const { |
| 603 | unsigned NumInstrs = 0; |
| 604 | for (const Function &F : FunctionList) |
| 605 | NumInstrs += F.getInstructionCount(); |
| 606 | return NumInstrs; |
| 607 | } |
| 608 | |
| 609 | Comdat *Module::getOrInsertComdat(StringRef Name) { |
| 610 | auto &Entry = *ComdatSymTab.insert(KV: std::make_pair(x&: Name, y: Comdat())).first; |
| 611 | Entry.second.Name = &Entry; |
| 612 | return &Entry.second; |
| 613 | } |
| 614 | |
| 615 | PICLevel::Level Module::getPICLevel() const { |
| 616 | auto *Val = cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "PIC Level" )); |
| 617 | |
| 618 | if (!Val) |
| 619 | return PICLevel::NotPIC; |
| 620 | |
| 621 | return static_cast<PICLevel::Level>( |
| 622 | cast<ConstantInt>(Val: Val->getValue())->getZExtValue()); |
| 623 | } |
| 624 | |
| 625 | void Module::setPICLevel(PICLevel::Level PL) { |
| 626 | // The merge result of a non-PIC object and a PIC object can only be reliably |
| 627 | // used as a non-PIC object, so use the Min merge behavior. |
| 628 | addModuleFlag(Behavior: ModFlagBehavior::Min, Key: "PIC Level" , Val: PL); |
| 629 | } |
| 630 | |
| 631 | PIELevel::Level Module::getPIELevel() const { |
| 632 | auto *Val = cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "PIE Level" )); |
| 633 | |
| 634 | if (!Val) |
| 635 | return PIELevel::Default; |
| 636 | |
| 637 | return static_cast<PIELevel::Level>( |
| 638 | cast<ConstantInt>(Val: Val->getValue())->getZExtValue()); |
| 639 | } |
| 640 | |
| 641 | void Module::setPIELevel(PIELevel::Level PL) { |
| 642 | addModuleFlag(Behavior: ModFlagBehavior::Max, Key: "PIE Level" , Val: PL); |
| 643 | } |
| 644 | |
| 645 | std::optional<CodeModel::Model> Module::getCodeModel() const { |
| 646 | auto *Val = cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "Code Model" )); |
| 647 | |
| 648 | if (!Val) |
| 649 | return std::nullopt; |
| 650 | |
| 651 | return static_cast<CodeModel::Model>( |
| 652 | cast<ConstantInt>(Val: Val->getValue())->getZExtValue()); |
| 653 | } |
| 654 | |
| 655 | void Module::setCodeModel(CodeModel::Model CL) { |
| 656 | // Linking object files with different code models is undefined behavior |
| 657 | // because the compiler would have to generate additional code (to span |
| 658 | // longer jumps) if a larger code model is used with a smaller one. |
| 659 | // Therefore we will treat attempts to mix code models as an error. |
| 660 | addModuleFlag(Behavior: ModFlagBehavior::Error, Key: "Code Model" , Val: CL); |
| 661 | } |
| 662 | |
| 663 | std::optional<uint64_t> Module::getLargeDataThreshold() const { |
| 664 | auto *Val = |
| 665 | cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "Large Data Threshold" )); |
| 666 | |
| 667 | if (!Val) |
| 668 | return std::nullopt; |
| 669 | |
| 670 | return cast<ConstantInt>(Val: Val->getValue())->getZExtValue(); |
| 671 | } |
| 672 | |
| 673 | void Module::setLargeDataThreshold(uint64_t Threshold) { |
| 674 | // Since the large data threshold goes along with the code model, the merge |
| 675 | // behavior is the same. |
| 676 | addModuleFlag(Behavior: ModFlagBehavior::Error, Key: "Large Data Threshold" , |
| 677 | Val: ConstantInt::get(Ty: Type::getInt64Ty(C&: Context), V: Threshold)); |
| 678 | } |
| 679 | |
| 680 | void Module::setProfileSummary(Metadata *M, ProfileSummary::Kind Kind) { |
| 681 | if (Kind == ProfileSummary::PSK_CSInstr) |
| 682 | setModuleFlag(Behavior: ModFlagBehavior::Error, Key: "CSProfileSummary" , Val: M); |
| 683 | else |
| 684 | setModuleFlag(Behavior: ModFlagBehavior::Error, Key: "ProfileSummary" , Val: M); |
| 685 | } |
| 686 | |
| 687 | Metadata *Module::getProfileSummary(bool IsCS) const { |
| 688 | return (IsCS ? getModuleFlag(Key: "CSProfileSummary" ) |
| 689 | : getModuleFlag(Key: "ProfileSummary" )); |
| 690 | } |
| 691 | |
| 692 | bool Module::getSemanticInterposition() const { |
| 693 | Metadata *MF = getModuleFlag(Key: "SemanticInterposition" ); |
| 694 | |
| 695 | auto *Val = cast_or_null<ConstantAsMetadata>(Val: MF); |
| 696 | if (!Val) |
| 697 | return false; |
| 698 | |
| 699 | return cast<ConstantInt>(Val: Val->getValue())->getZExtValue(); |
| 700 | } |
| 701 | |
| 702 | void Module::setSemanticInterposition(bool SI) { |
| 703 | addModuleFlag(Behavior: ModFlagBehavior::Error, Key: "SemanticInterposition" , Val: SI); |
| 704 | } |
| 705 | |
| 706 | void Module::setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB) { |
| 707 | OwnedMemoryBuffer = std::move(MB); |
| 708 | } |
| 709 | |
| 710 | bool Module::getRtLibUseGOT() const { |
| 711 | auto *Val = cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "RtLibUseGOT" )); |
| 712 | return Val && (cast<ConstantInt>(Val: Val->getValue())->getZExtValue() > 0); |
| 713 | } |
| 714 | |
| 715 | void Module::setRtLibUseGOT() { |
| 716 | addModuleFlag(Behavior: ModFlagBehavior::Max, Key: "RtLibUseGOT" , Val: 1); |
| 717 | } |
| 718 | |
| 719 | bool Module::getDirectAccessExternalData() const { |
| 720 | auto *Val = cast_or_null<ConstantAsMetadata>( |
| 721 | Val: getModuleFlag(Key: "direct-access-external-data" )); |
| 722 | if (Val) |
| 723 | return cast<ConstantInt>(Val: Val->getValue())->getZExtValue() > 0; |
| 724 | return getPICLevel() == PICLevel::NotPIC; |
| 725 | } |
| 726 | |
| 727 | void Module::setDirectAccessExternalData(bool Value) { |
| 728 | addModuleFlag(Behavior: ModFlagBehavior::Max, Key: "direct-access-external-data" , Val: Value); |
| 729 | } |
| 730 | |
| 731 | UWTableKind Module::getUwtable() const { |
| 732 | if (auto *Val = cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "uwtable" ))) |
| 733 | return UWTableKind(cast<ConstantInt>(Val: Val->getValue())->getZExtValue()); |
| 734 | return UWTableKind::None; |
| 735 | } |
| 736 | |
| 737 | void Module::setUwtable(UWTableKind Kind) { |
| 738 | addModuleFlag(Behavior: ModFlagBehavior::Max, Key: "uwtable" , Val: uint32_t(Kind)); |
| 739 | } |
| 740 | |
| 741 | FramePointerKind Module::getFramePointer() const { |
| 742 | auto *Val = cast_or_null<ConstantAsMetadata>(Val: getModuleFlag(Key: "frame-pointer" )); |
| 743 | return static_cast<FramePointerKind>( |
| 744 | Val ? cast<ConstantInt>(Val: Val->getValue())->getZExtValue() : 0); |
| 745 | } |
| 746 | |
| 747 | void Module::setFramePointer(FramePointerKind Kind) { |
| 748 | addModuleFlag(Behavior: ModFlagBehavior::Max, Key: "frame-pointer" , Val: static_cast<int>(Kind)); |
| 749 | } |
| 750 | |
| 751 | StringRef Module::getStackProtectorGuard() const { |
| 752 | Metadata *MD = getModuleFlag(Key: "stack-protector-guard" ); |
| 753 | if (auto *MDS = dyn_cast_or_null<MDString>(Val: MD)) |
| 754 | return MDS->getString(); |
| 755 | return {}; |
| 756 | } |
| 757 | |
| 758 | void Module::setStackProtectorGuard(StringRef Kind) { |
| 759 | MDString *ID = MDString::get(Context&: getContext(), Str: Kind); |
| 760 | addModuleFlag(Behavior: ModFlagBehavior::Error, Key: "stack-protector-guard" , Val: ID); |
| 761 | } |
| 762 | |
| 763 | StringRef Module::getStackProtectorGuardReg() const { |
| 764 | Metadata *MD = getModuleFlag(Key: "stack-protector-guard-reg" ); |
| 765 | if (auto *MDS = dyn_cast_or_null<MDString>(Val: MD)) |
| 766 | return MDS->getString(); |
| 767 | return {}; |
| 768 | } |
| 769 | |
| 770 | void Module::setStackProtectorGuardReg(StringRef Reg) { |
| 771 | MDString *ID = MDString::get(Context&: getContext(), Str: Reg); |
| 772 | addModuleFlag(Behavior: ModFlagBehavior::Error, Key: "stack-protector-guard-reg" , Val: ID); |
| 773 | } |
| 774 | |
| 775 | StringRef Module::getStackProtectorGuardSymbol() const { |
| 776 | Metadata *MD = getModuleFlag(Key: "stack-protector-guard-symbol" ); |
| 777 | if (auto *MDS = dyn_cast_or_null<MDString>(Val: MD)) |
| 778 | return MDS->getString(); |
| 779 | return {}; |
| 780 | } |
| 781 | |
| 782 | void Module::setStackProtectorGuardSymbol(StringRef Symbol) { |
| 783 | MDString *ID = MDString::get(Context&: getContext(), Str: Symbol); |
| 784 | addModuleFlag(Behavior: ModFlagBehavior::Error, Key: "stack-protector-guard-symbol" , Val: ID); |
| 785 | } |
| 786 | |
| 787 | int Module::getStackProtectorGuardOffset() const { |
| 788 | Metadata *MD = getModuleFlag(Key: "stack-protector-guard-offset" ); |
| 789 | if (auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(MD)) |
| 790 | return CI->getSExtValue(); |
| 791 | return INT_MAX; |
| 792 | } |
| 793 | |
| 794 | void Module::setStackProtectorGuardOffset(int Offset) { |
| 795 | addModuleFlag(Behavior: ModFlagBehavior::Error, Key: "stack-protector-guard-offset" , Val: Offset); |
| 796 | } |
| 797 | |
| 798 | unsigned Module::getOverrideStackAlignment() const { |
| 799 | Metadata *MD = getModuleFlag(Key: "override-stack-alignment" ); |
| 800 | if (auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(MD)) |
| 801 | return CI->getZExtValue(); |
| 802 | return 0; |
| 803 | } |
| 804 | |
| 805 | unsigned Module::getMaxTLSAlignment() const { |
| 806 | Metadata *MD = getModuleFlag(Key: "MaxTLSAlign" ); |
| 807 | if (auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(MD)) |
| 808 | return CI->getZExtValue(); |
| 809 | return 0; |
| 810 | } |
| 811 | |
| 812 | void Module::setOverrideStackAlignment(unsigned Align) { |
| 813 | addModuleFlag(Behavior: ModFlagBehavior::Error, Key: "override-stack-alignment" , Val: Align); |
| 814 | } |
| 815 | |
| 816 | static void addSDKVersionMD(const VersionTuple &V, Module &M, StringRef Name) { |
| 817 | SmallVector<unsigned, 3> Entries; |
| 818 | Entries.push_back(Elt: V.getMajor()); |
| 819 | if (auto Minor = V.getMinor()) { |
| 820 | Entries.push_back(Elt: *Minor); |
| 821 | if (auto Subminor = V.getSubminor()) |
| 822 | Entries.push_back(Elt: *Subminor); |
| 823 | // Ignore the 'build' component as it can't be represented in the object |
| 824 | // file. |
| 825 | } |
| 826 | M.addModuleFlag(Behavior: Module::ModFlagBehavior::Warning, Key: Name, |
| 827 | Val: ConstantDataArray::get(Context&: M.getContext(), Elts&: Entries)); |
| 828 | } |
| 829 | |
| 830 | void Module::setSDKVersion(const VersionTuple &V) { |
| 831 | addSDKVersionMD(V, M&: *this, Name: "SDK Version" ); |
| 832 | } |
| 833 | |
| 834 | static VersionTuple getSDKVersionMD(Metadata *MD) { |
| 835 | auto *CM = dyn_cast_or_null<ConstantAsMetadata>(Val: MD); |
| 836 | if (!CM) |
| 837 | return {}; |
| 838 | auto *Arr = dyn_cast_or_null<ConstantDataArray>(Val: CM->getValue()); |
| 839 | if (!Arr) |
| 840 | return {}; |
| 841 | auto getVersionComponent = [&](unsigned Index) -> std::optional<unsigned> { |
| 842 | if (Index >= Arr->getNumElements()) |
| 843 | return std::nullopt; |
| 844 | return (unsigned)Arr->getElementAsInteger(i: Index); |
| 845 | }; |
| 846 | auto Major = getVersionComponent(0); |
| 847 | if (!Major) |
| 848 | return {}; |
| 849 | VersionTuple Result = VersionTuple(*Major); |
| 850 | if (auto Minor = getVersionComponent(1)) { |
| 851 | Result = VersionTuple(*Major, *Minor); |
| 852 | if (auto Subminor = getVersionComponent(2)) { |
| 853 | Result = VersionTuple(*Major, *Minor, *Subminor); |
| 854 | } |
| 855 | } |
| 856 | return Result; |
| 857 | } |
| 858 | |
| 859 | VersionTuple Module::getSDKVersion() const { |
| 860 | return getSDKVersionMD(MD: getModuleFlag(Key: "SDK Version" )); |
| 861 | } |
| 862 | |
| 863 | GlobalVariable *llvm::collectUsedGlobalVariables( |
| 864 | const Module &M, SmallVectorImpl<GlobalValue *> &Vec, bool CompilerUsed) { |
| 865 | const char *Name = CompilerUsed ? "llvm.compiler.used" : "llvm.used" ; |
| 866 | GlobalVariable *GV = M.getGlobalVariable(Name); |
| 867 | if (!GV || !GV->hasInitializer()) |
| 868 | return GV; |
| 869 | |
| 870 | const ConstantArray *Init = cast<ConstantArray>(Val: GV->getInitializer()); |
| 871 | for (Value *Op : Init->operands()) { |
| 872 | GlobalValue *G = cast<GlobalValue>(Val: Op->stripPointerCasts()); |
| 873 | Vec.push_back(Elt: G); |
| 874 | } |
| 875 | return GV; |
| 876 | } |
| 877 | |
| 878 | void Module::setPartialSampleProfileRatio(const ModuleSummaryIndex &Index) { |
| 879 | if (auto *SummaryMD = getProfileSummary(/*IsCS*/ false)) { |
| 880 | std::unique_ptr<ProfileSummary> ProfileSummary( |
| 881 | ProfileSummary::getFromMD(MD: SummaryMD)); |
| 882 | if (ProfileSummary) { |
| 883 | if (ProfileSummary->getKind() != ProfileSummary::PSK_Sample || |
| 884 | !ProfileSummary->isPartialProfile()) |
| 885 | return; |
| 886 | uint64_t BlockCount = Index.getBlockCount(); |
| 887 | uint32_t NumCounts = ProfileSummary->getNumCounts(); |
| 888 | if (!NumCounts) |
| 889 | return; |
| 890 | double Ratio = (double)BlockCount / NumCounts; |
| 891 | ProfileSummary->setPartialProfileRatio(Ratio); |
| 892 | setProfileSummary(M: ProfileSummary->getMD(Context&: getContext()), |
| 893 | Kind: ProfileSummary::PSK_Sample); |
| 894 | } |
| 895 | } |
| 896 | } |
| 897 | |
| 898 | StringRef Module::getDarwinTargetVariantTriple() const { |
| 899 | if (const auto *MD = getModuleFlag(Key: "darwin.target_variant.triple" )) |
| 900 | return cast<MDString>(Val: MD)->getString(); |
| 901 | return "" ; |
| 902 | } |
| 903 | |
| 904 | void Module::setDarwinTargetVariantTriple(StringRef T) { |
| 905 | addModuleFlag(Behavior: ModFlagBehavior::Warning, Key: "darwin.target_variant.triple" , |
| 906 | Val: MDString::get(Context&: getContext(), Str: T)); |
| 907 | } |
| 908 | |
| 909 | VersionTuple Module::getDarwinTargetVariantSDKVersion() const { |
| 910 | return getSDKVersionMD(MD: getModuleFlag(Key: "darwin.target_variant.SDK Version" )); |
| 911 | } |
| 912 | |
| 913 | void Module::setDarwinTargetVariantSDKVersion(VersionTuple Version) { |
| 914 | addSDKVersionMD(V: Version, M&: *this, Name: "darwin.target_variant.SDK Version" ); |
| 915 | } |
| 916 | |
| 917 | StringRef Module::getTargetABIFromMD() { |
| 918 | StringRef TargetABI; |
| 919 | if (auto *TargetABIMD = |
| 920 | dyn_cast_or_null<MDString>(Val: getModuleFlag(Key: "target-abi" ))) |
| 921 | TargetABI = TargetABIMD->getString(); |
| 922 | return TargetABI; |
| 923 | } |
| 924 | |
| 925 | WinX64EHUnwindV2Mode Module::getWinX64EHUnwindV2Mode() const { |
| 926 | Metadata *MD = getModuleFlag(Key: "winx64-eh-unwindv2" ); |
| 927 | if (auto *CI = mdconst::dyn_extract_or_null<ConstantInt>(MD)) |
| 928 | return static_cast<WinX64EHUnwindV2Mode>(CI->getZExtValue()); |
| 929 | return WinX64EHUnwindV2Mode::Disabled; |
| 930 | } |
| 931 | |