17330f729Sjoerg //===- AsmWriter.cpp - Printing LLVM as an assembly file ------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This library implements `print` family of functions in classes like
107330f729Sjoerg // Module, Function, Value, etc. In-memory representation of those classes is
117330f729Sjoerg // converted to IR strings.
127330f729Sjoerg //
137330f729Sjoerg // Note that these routines must be extremely tolerant of various errors in the
147330f729Sjoerg // LLVM code, because it can be used for debugging transformations.
157330f729Sjoerg //
167330f729Sjoerg //===----------------------------------------------------------------------===//
177330f729Sjoerg
187330f729Sjoerg #include "llvm/ADT/APFloat.h"
197330f729Sjoerg #include "llvm/ADT/APInt.h"
207330f729Sjoerg #include "llvm/ADT/ArrayRef.h"
217330f729Sjoerg #include "llvm/ADT/DenseMap.h"
227330f729Sjoerg #include "llvm/ADT/None.h"
237330f729Sjoerg #include "llvm/ADT/Optional.h"
247330f729Sjoerg #include "llvm/ADT/STLExtras.h"
257330f729Sjoerg #include "llvm/ADT/SetVector.h"
267330f729Sjoerg #include "llvm/ADT/SmallString.h"
277330f729Sjoerg #include "llvm/ADT/SmallVector.h"
287330f729Sjoerg #include "llvm/ADT/StringExtras.h"
297330f729Sjoerg #include "llvm/ADT/StringRef.h"
307330f729Sjoerg #include "llvm/ADT/iterator_range.h"
317330f729Sjoerg #include "llvm/BinaryFormat/Dwarf.h"
327330f729Sjoerg #include "llvm/Config/llvm-config.h"
337330f729Sjoerg #include "llvm/IR/Argument.h"
347330f729Sjoerg #include "llvm/IR/AssemblyAnnotationWriter.h"
357330f729Sjoerg #include "llvm/IR/Attributes.h"
367330f729Sjoerg #include "llvm/IR/BasicBlock.h"
377330f729Sjoerg #include "llvm/IR/CFG.h"
387330f729Sjoerg #include "llvm/IR/CallingConv.h"
397330f729Sjoerg #include "llvm/IR/Comdat.h"
407330f729Sjoerg #include "llvm/IR/Constant.h"
417330f729Sjoerg #include "llvm/IR/Constants.h"
427330f729Sjoerg #include "llvm/IR/DebugInfoMetadata.h"
437330f729Sjoerg #include "llvm/IR/DerivedTypes.h"
447330f729Sjoerg #include "llvm/IR/Function.h"
457330f729Sjoerg #include "llvm/IR/GlobalAlias.h"
467330f729Sjoerg #include "llvm/IR/GlobalIFunc.h"
477330f729Sjoerg #include "llvm/IR/GlobalIndirectSymbol.h"
487330f729Sjoerg #include "llvm/IR/GlobalObject.h"
497330f729Sjoerg #include "llvm/IR/GlobalValue.h"
507330f729Sjoerg #include "llvm/IR/GlobalVariable.h"
517330f729Sjoerg #include "llvm/IR/IRPrintingPasses.h"
527330f729Sjoerg #include "llvm/IR/InlineAsm.h"
537330f729Sjoerg #include "llvm/IR/InstrTypes.h"
547330f729Sjoerg #include "llvm/IR/Instruction.h"
557330f729Sjoerg #include "llvm/IR/Instructions.h"
56*82d56013Sjoerg #include "llvm/IR/IntrinsicInst.h"
577330f729Sjoerg #include "llvm/IR/LLVMContext.h"
587330f729Sjoerg #include "llvm/IR/Metadata.h"
597330f729Sjoerg #include "llvm/IR/Module.h"
607330f729Sjoerg #include "llvm/IR/ModuleSlotTracker.h"
617330f729Sjoerg #include "llvm/IR/ModuleSummaryIndex.h"
627330f729Sjoerg #include "llvm/IR/Operator.h"
637330f729Sjoerg #include "llvm/IR/Type.h"
647330f729Sjoerg #include "llvm/IR/TypeFinder.h"
657330f729Sjoerg #include "llvm/IR/Use.h"
667330f729Sjoerg #include "llvm/IR/UseListOrder.h"
677330f729Sjoerg #include "llvm/IR/User.h"
687330f729Sjoerg #include "llvm/IR/Value.h"
697330f729Sjoerg #include "llvm/Support/AtomicOrdering.h"
707330f729Sjoerg #include "llvm/Support/Casting.h"
717330f729Sjoerg #include "llvm/Support/Compiler.h"
727330f729Sjoerg #include "llvm/Support/Debug.h"
737330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
747330f729Sjoerg #include "llvm/Support/Format.h"
757330f729Sjoerg #include "llvm/Support/FormattedStream.h"
767330f729Sjoerg #include "llvm/Support/raw_ostream.h"
777330f729Sjoerg #include <algorithm>
787330f729Sjoerg #include <cassert>
797330f729Sjoerg #include <cctype>
807330f729Sjoerg #include <cstddef>
817330f729Sjoerg #include <cstdint>
827330f729Sjoerg #include <iterator>
837330f729Sjoerg #include <memory>
847330f729Sjoerg #include <string>
857330f729Sjoerg #include <tuple>
867330f729Sjoerg #include <utility>
877330f729Sjoerg #include <vector>
887330f729Sjoerg
897330f729Sjoerg using namespace llvm;
907330f729Sjoerg
917330f729Sjoerg // Make virtual table appear in this compilation unit.
927330f729Sjoerg AssemblyAnnotationWriter::~AssemblyAnnotationWriter() = default;
937330f729Sjoerg
947330f729Sjoerg //===----------------------------------------------------------------------===//
957330f729Sjoerg // Helper Functions
967330f729Sjoerg //===----------------------------------------------------------------------===//
977330f729Sjoerg
987330f729Sjoerg namespace {
997330f729Sjoerg
1007330f729Sjoerg struct OrderMap {
1017330f729Sjoerg DenseMap<const Value *, std::pair<unsigned, bool>> IDs;
1027330f729Sjoerg
size__anonf93afd230111::OrderMap1037330f729Sjoerg unsigned size() const { return IDs.size(); }
operator []__anonf93afd230111::OrderMap1047330f729Sjoerg std::pair<unsigned, bool> &operator[](const Value *V) { return IDs[V]; }
1057330f729Sjoerg
lookup__anonf93afd230111::OrderMap1067330f729Sjoerg std::pair<unsigned, bool> lookup(const Value *V) const {
1077330f729Sjoerg return IDs.lookup(V);
1087330f729Sjoerg }
1097330f729Sjoerg
index__anonf93afd230111::OrderMap1107330f729Sjoerg void index(const Value *V) {
1117330f729Sjoerg // Explicitly sequence get-size and insert-value operations to avoid UB.
1127330f729Sjoerg unsigned ID = IDs.size() + 1;
1137330f729Sjoerg IDs[V].first = ID;
1147330f729Sjoerg }
1157330f729Sjoerg };
1167330f729Sjoerg
1177330f729Sjoerg } // end anonymous namespace
1187330f729Sjoerg
119*82d56013Sjoerg /// Look for a value that might be wrapped as metadata, e.g. a value in a
120*82d56013Sjoerg /// metadata operand. Returns the input value as-is if it is not wrapped.
skipMetadataWrapper(const Value * V)121*82d56013Sjoerg static const Value *skipMetadataWrapper(const Value *V) {
122*82d56013Sjoerg if (const auto *MAV = dyn_cast<MetadataAsValue>(V))
123*82d56013Sjoerg if (const auto *VAM = dyn_cast<ValueAsMetadata>(MAV->getMetadata()))
124*82d56013Sjoerg return VAM->getValue();
125*82d56013Sjoerg return V;
126*82d56013Sjoerg }
127*82d56013Sjoerg
orderValue(const Value * V,OrderMap & OM)1287330f729Sjoerg static void orderValue(const Value *V, OrderMap &OM) {
1297330f729Sjoerg if (OM.lookup(V).first)
1307330f729Sjoerg return;
1317330f729Sjoerg
1327330f729Sjoerg if (const Constant *C = dyn_cast<Constant>(V))
1337330f729Sjoerg if (C->getNumOperands() && !isa<GlobalValue>(C))
1347330f729Sjoerg for (const Value *Op : C->operands())
1357330f729Sjoerg if (!isa<BasicBlock>(Op) && !isa<GlobalValue>(Op))
1367330f729Sjoerg orderValue(Op, OM);
1377330f729Sjoerg
1387330f729Sjoerg // Note: we cannot cache this lookup above, since inserting into the map
1397330f729Sjoerg // changes the map's size, and thus affects the other IDs.
1407330f729Sjoerg OM.index(V);
1417330f729Sjoerg }
1427330f729Sjoerg
orderModule(const Module * M)1437330f729Sjoerg static OrderMap orderModule(const Module *M) {
1447330f729Sjoerg OrderMap OM;
1457330f729Sjoerg
1467330f729Sjoerg for (const GlobalVariable &G : M->globals()) {
1477330f729Sjoerg if (G.hasInitializer())
1487330f729Sjoerg if (!isa<GlobalValue>(G.getInitializer()))
1497330f729Sjoerg orderValue(G.getInitializer(), OM);
1507330f729Sjoerg orderValue(&G, OM);
1517330f729Sjoerg }
1527330f729Sjoerg for (const GlobalAlias &A : M->aliases()) {
1537330f729Sjoerg if (!isa<GlobalValue>(A.getAliasee()))
1547330f729Sjoerg orderValue(A.getAliasee(), OM);
1557330f729Sjoerg orderValue(&A, OM);
1567330f729Sjoerg }
1577330f729Sjoerg for (const GlobalIFunc &I : M->ifuncs()) {
1587330f729Sjoerg if (!isa<GlobalValue>(I.getResolver()))
1597330f729Sjoerg orderValue(I.getResolver(), OM);
1607330f729Sjoerg orderValue(&I, OM);
1617330f729Sjoerg }
1627330f729Sjoerg for (const Function &F : *M) {
1637330f729Sjoerg for (const Use &U : F.operands())
1647330f729Sjoerg if (!isa<GlobalValue>(U.get()))
1657330f729Sjoerg orderValue(U.get(), OM);
1667330f729Sjoerg
1677330f729Sjoerg orderValue(&F, OM);
1687330f729Sjoerg
1697330f729Sjoerg if (F.isDeclaration())
1707330f729Sjoerg continue;
1717330f729Sjoerg
1727330f729Sjoerg for (const Argument &A : F.args())
1737330f729Sjoerg orderValue(&A, OM);
1747330f729Sjoerg for (const BasicBlock &BB : F) {
1757330f729Sjoerg orderValue(&BB, OM);
1767330f729Sjoerg for (const Instruction &I : BB) {
177*82d56013Sjoerg for (const Value *Op : I.operands()) {
178*82d56013Sjoerg Op = skipMetadataWrapper(Op);
1797330f729Sjoerg if ((isa<Constant>(*Op) && !isa<GlobalValue>(*Op)) ||
1807330f729Sjoerg isa<InlineAsm>(*Op))
1817330f729Sjoerg orderValue(Op, OM);
182*82d56013Sjoerg }
1837330f729Sjoerg orderValue(&I, OM);
1847330f729Sjoerg }
1857330f729Sjoerg }
1867330f729Sjoerg }
1877330f729Sjoerg return OM;
1887330f729Sjoerg }
1897330f729Sjoerg
predictValueUseListOrderImpl(const Value * V,const Function * F,unsigned ID,const OrderMap & OM,UseListOrderStack & Stack)1907330f729Sjoerg static void predictValueUseListOrderImpl(const Value *V, const Function *F,
1917330f729Sjoerg unsigned ID, const OrderMap &OM,
1927330f729Sjoerg UseListOrderStack &Stack) {
1937330f729Sjoerg // Predict use-list order for this one.
1947330f729Sjoerg using Entry = std::pair<const Use *, unsigned>;
1957330f729Sjoerg SmallVector<Entry, 64> List;
1967330f729Sjoerg for (const Use &U : V->uses())
1977330f729Sjoerg // Check if this user will be serialized.
1987330f729Sjoerg if (OM.lookup(U.getUser()).first)
1997330f729Sjoerg List.push_back(std::make_pair(&U, List.size()));
2007330f729Sjoerg
2017330f729Sjoerg if (List.size() < 2)
2027330f729Sjoerg // We may have lost some users.
2037330f729Sjoerg return;
2047330f729Sjoerg
2057330f729Sjoerg bool GetsReversed =
2067330f729Sjoerg !isa<GlobalVariable>(V) && !isa<Function>(V) && !isa<BasicBlock>(V);
2077330f729Sjoerg if (auto *BA = dyn_cast<BlockAddress>(V))
2087330f729Sjoerg ID = OM.lookup(BA->getBasicBlock()).first;
2097330f729Sjoerg llvm::sort(List, [&](const Entry &L, const Entry &R) {
2107330f729Sjoerg const Use *LU = L.first;
2117330f729Sjoerg const Use *RU = R.first;
2127330f729Sjoerg if (LU == RU)
2137330f729Sjoerg return false;
2147330f729Sjoerg
2157330f729Sjoerg auto LID = OM.lookup(LU->getUser()).first;
2167330f729Sjoerg auto RID = OM.lookup(RU->getUser()).first;
2177330f729Sjoerg
2187330f729Sjoerg // If ID is 4, then expect: 7 6 5 1 2 3.
2197330f729Sjoerg if (LID < RID) {
2207330f729Sjoerg if (GetsReversed)
2217330f729Sjoerg if (RID <= ID)
2227330f729Sjoerg return true;
2237330f729Sjoerg return false;
2247330f729Sjoerg }
2257330f729Sjoerg if (RID < LID) {
2267330f729Sjoerg if (GetsReversed)
2277330f729Sjoerg if (LID <= ID)
2287330f729Sjoerg return false;
2297330f729Sjoerg return true;
2307330f729Sjoerg }
2317330f729Sjoerg
2327330f729Sjoerg // LID and RID are equal, so we have different operands of the same user.
2337330f729Sjoerg // Assume operands are added in order for all instructions.
2347330f729Sjoerg if (GetsReversed)
2357330f729Sjoerg if (LID <= ID)
2367330f729Sjoerg return LU->getOperandNo() < RU->getOperandNo();
2377330f729Sjoerg return LU->getOperandNo() > RU->getOperandNo();
2387330f729Sjoerg });
2397330f729Sjoerg
240*82d56013Sjoerg if (llvm::is_sorted(List, [](const Entry &L, const Entry &R) {
241*82d56013Sjoerg return L.second < R.second;
242*82d56013Sjoerg }))
2437330f729Sjoerg // Order is already correct.
2447330f729Sjoerg return;
2457330f729Sjoerg
2467330f729Sjoerg // Store the shuffle.
2477330f729Sjoerg Stack.emplace_back(V, F, List.size());
2487330f729Sjoerg assert(List.size() == Stack.back().Shuffle.size() && "Wrong size");
2497330f729Sjoerg for (size_t I = 0, E = List.size(); I != E; ++I)
2507330f729Sjoerg Stack.back().Shuffle[I] = List[I].second;
2517330f729Sjoerg }
2527330f729Sjoerg
predictValueUseListOrder(const Value * V,const Function * F,OrderMap & OM,UseListOrderStack & Stack)2537330f729Sjoerg static void predictValueUseListOrder(const Value *V, const Function *F,
2547330f729Sjoerg OrderMap &OM, UseListOrderStack &Stack) {
2557330f729Sjoerg auto &IDPair = OM[V];
2567330f729Sjoerg assert(IDPair.first && "Unmapped value");
2577330f729Sjoerg if (IDPair.second)
2587330f729Sjoerg // Already predicted.
2597330f729Sjoerg return;
2607330f729Sjoerg
2617330f729Sjoerg // Do the actual prediction.
2627330f729Sjoerg IDPair.second = true;
2637330f729Sjoerg if (!V->use_empty() && std::next(V->use_begin()) != V->use_end())
2647330f729Sjoerg predictValueUseListOrderImpl(V, F, IDPair.first, OM, Stack);
2657330f729Sjoerg
2667330f729Sjoerg // Recursive descent into constants.
2677330f729Sjoerg if (const Constant *C = dyn_cast<Constant>(V))
2687330f729Sjoerg if (C->getNumOperands()) // Visit GlobalValues.
2697330f729Sjoerg for (const Value *Op : C->operands())
2707330f729Sjoerg if (isa<Constant>(Op)) // Visit GlobalValues.
2717330f729Sjoerg predictValueUseListOrder(Op, F, OM, Stack);
2727330f729Sjoerg }
2737330f729Sjoerg
predictUseListOrder(const Module * M)2747330f729Sjoerg static UseListOrderStack predictUseListOrder(const Module *M) {
2757330f729Sjoerg OrderMap OM = orderModule(M);
2767330f729Sjoerg
2777330f729Sjoerg // Use-list orders need to be serialized after all the users have been added
2787330f729Sjoerg // to a value, or else the shuffles will be incomplete. Store them per
2797330f729Sjoerg // function in a stack.
2807330f729Sjoerg //
2817330f729Sjoerg // Aside from function order, the order of values doesn't matter much here.
2827330f729Sjoerg UseListOrderStack Stack;
2837330f729Sjoerg
2847330f729Sjoerg // We want to visit the functions backward now so we can list function-local
2857330f729Sjoerg // constants in the last Function they're used in. Module-level constants
2867330f729Sjoerg // have already been visited above.
2877330f729Sjoerg for (const Function &F : make_range(M->rbegin(), M->rend())) {
2887330f729Sjoerg if (F.isDeclaration())
2897330f729Sjoerg continue;
2907330f729Sjoerg for (const BasicBlock &BB : F)
2917330f729Sjoerg predictValueUseListOrder(&BB, &F, OM, Stack);
2927330f729Sjoerg for (const Argument &A : F.args())
2937330f729Sjoerg predictValueUseListOrder(&A, &F, OM, Stack);
2947330f729Sjoerg for (const BasicBlock &BB : F)
2957330f729Sjoerg for (const Instruction &I : BB)
296*82d56013Sjoerg for (const Value *Op : I.operands()) {
297*82d56013Sjoerg Op = skipMetadataWrapper(Op);
2987330f729Sjoerg if (isa<Constant>(*Op) || isa<InlineAsm>(*Op)) // Visit GlobalValues.
2997330f729Sjoerg predictValueUseListOrder(Op, &F, OM, Stack);
300*82d56013Sjoerg }
3017330f729Sjoerg for (const BasicBlock &BB : F)
3027330f729Sjoerg for (const Instruction &I : BB)
3037330f729Sjoerg predictValueUseListOrder(&I, &F, OM, Stack);
3047330f729Sjoerg }
3057330f729Sjoerg
3067330f729Sjoerg // Visit globals last.
3077330f729Sjoerg for (const GlobalVariable &G : M->globals())
3087330f729Sjoerg predictValueUseListOrder(&G, nullptr, OM, Stack);
3097330f729Sjoerg for (const Function &F : *M)
3107330f729Sjoerg predictValueUseListOrder(&F, nullptr, OM, Stack);
3117330f729Sjoerg for (const GlobalAlias &A : M->aliases())
3127330f729Sjoerg predictValueUseListOrder(&A, nullptr, OM, Stack);
3137330f729Sjoerg for (const GlobalIFunc &I : M->ifuncs())
3147330f729Sjoerg predictValueUseListOrder(&I, nullptr, OM, Stack);
3157330f729Sjoerg for (const GlobalVariable &G : M->globals())
3167330f729Sjoerg if (G.hasInitializer())
3177330f729Sjoerg predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack);
3187330f729Sjoerg for (const GlobalAlias &A : M->aliases())
3197330f729Sjoerg predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack);
3207330f729Sjoerg for (const GlobalIFunc &I : M->ifuncs())
3217330f729Sjoerg predictValueUseListOrder(I.getResolver(), nullptr, OM, Stack);
3227330f729Sjoerg for (const Function &F : *M)
3237330f729Sjoerg for (const Use &U : F.operands())
3247330f729Sjoerg predictValueUseListOrder(U.get(), nullptr, OM, Stack);
3257330f729Sjoerg
3267330f729Sjoerg return Stack;
3277330f729Sjoerg }
3287330f729Sjoerg
getModuleFromVal(const Value * V)3297330f729Sjoerg static const Module *getModuleFromVal(const Value *V) {
3307330f729Sjoerg if (const Argument *MA = dyn_cast<Argument>(V))
3317330f729Sjoerg return MA->getParent() ? MA->getParent()->getParent() : nullptr;
3327330f729Sjoerg
3337330f729Sjoerg if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
3347330f729Sjoerg return BB->getParent() ? BB->getParent()->getParent() : nullptr;
3357330f729Sjoerg
3367330f729Sjoerg if (const Instruction *I = dyn_cast<Instruction>(V)) {
3377330f729Sjoerg const Function *M = I->getParent() ? I->getParent()->getParent() : nullptr;
3387330f729Sjoerg return M ? M->getParent() : nullptr;
3397330f729Sjoerg }
3407330f729Sjoerg
3417330f729Sjoerg if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
3427330f729Sjoerg return GV->getParent();
3437330f729Sjoerg
3447330f729Sjoerg if (const auto *MAV = dyn_cast<MetadataAsValue>(V)) {
3457330f729Sjoerg for (const User *U : MAV->users())
3467330f729Sjoerg if (isa<Instruction>(U))
3477330f729Sjoerg if (const Module *M = getModuleFromVal(U))
3487330f729Sjoerg return M;
3497330f729Sjoerg return nullptr;
3507330f729Sjoerg }
3517330f729Sjoerg
3527330f729Sjoerg return nullptr;
3537330f729Sjoerg }
3547330f729Sjoerg
PrintCallingConv(unsigned cc,raw_ostream & Out)3557330f729Sjoerg static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
3567330f729Sjoerg switch (cc) {
3577330f729Sjoerg default: Out << "cc" << cc; break;
3587330f729Sjoerg case CallingConv::Fast: Out << "fastcc"; break;
3597330f729Sjoerg case CallingConv::Cold: Out << "coldcc"; break;
3607330f729Sjoerg case CallingConv::WebKit_JS: Out << "webkit_jscc"; break;
3617330f729Sjoerg case CallingConv::AnyReg: Out << "anyregcc"; break;
3627330f729Sjoerg case CallingConv::PreserveMost: Out << "preserve_mostcc"; break;
3637330f729Sjoerg case CallingConv::PreserveAll: Out << "preserve_allcc"; break;
3647330f729Sjoerg case CallingConv::CXX_FAST_TLS: Out << "cxx_fast_tlscc"; break;
3657330f729Sjoerg case CallingConv::GHC: Out << "ghccc"; break;
3667330f729Sjoerg case CallingConv::Tail: Out << "tailcc"; break;
3677330f729Sjoerg case CallingConv::CFGuard_Check: Out << "cfguard_checkcc"; break;
3687330f729Sjoerg case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break;
3697330f729Sjoerg case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break;
3707330f729Sjoerg case CallingConv::X86_ThisCall: Out << "x86_thiscallcc"; break;
3717330f729Sjoerg case CallingConv::X86_RegCall: Out << "x86_regcallcc"; break;
3727330f729Sjoerg case CallingConv::X86_VectorCall:Out << "x86_vectorcallcc"; break;
3737330f729Sjoerg case CallingConv::Intel_OCL_BI: Out << "intel_ocl_bicc"; break;
3747330f729Sjoerg case CallingConv::ARM_APCS: Out << "arm_apcscc"; break;
3757330f729Sjoerg case CallingConv::ARM_AAPCS: Out << "arm_aapcscc"; break;
3767330f729Sjoerg case CallingConv::ARM_AAPCS_VFP: Out << "arm_aapcs_vfpcc"; break;
3777330f729Sjoerg case CallingConv::AArch64_VectorCall: Out << "aarch64_vector_pcs"; break;
378*82d56013Sjoerg case CallingConv::AArch64_SVE_VectorCall:
379*82d56013Sjoerg Out << "aarch64_sve_vector_pcs";
380*82d56013Sjoerg break;
3817330f729Sjoerg case CallingConv::MSP430_INTR: Out << "msp430_intrcc"; break;
3827330f729Sjoerg case CallingConv::AVR_INTR: Out << "avr_intrcc "; break;
3837330f729Sjoerg case CallingConv::AVR_SIGNAL: Out << "avr_signalcc "; break;
3847330f729Sjoerg case CallingConv::PTX_Kernel: Out << "ptx_kernel"; break;
3857330f729Sjoerg case CallingConv::PTX_Device: Out << "ptx_device"; break;
3867330f729Sjoerg case CallingConv::X86_64_SysV: Out << "x86_64_sysvcc"; break;
3877330f729Sjoerg case CallingConv::Win64: Out << "win64cc"; break;
3887330f729Sjoerg case CallingConv::SPIR_FUNC: Out << "spir_func"; break;
3897330f729Sjoerg case CallingConv::SPIR_KERNEL: Out << "spir_kernel"; break;
3907330f729Sjoerg case CallingConv::Swift: Out << "swiftcc"; break;
391*82d56013Sjoerg case CallingConv::SwiftTail: Out << "swifttailcc"; break;
3927330f729Sjoerg case CallingConv::X86_INTR: Out << "x86_intrcc"; break;
3937330f729Sjoerg case CallingConv::HHVM: Out << "hhvmcc"; break;
3947330f729Sjoerg case CallingConv::HHVM_C: Out << "hhvm_ccc"; break;
3957330f729Sjoerg case CallingConv::AMDGPU_VS: Out << "amdgpu_vs"; break;
3967330f729Sjoerg case CallingConv::AMDGPU_LS: Out << "amdgpu_ls"; break;
3977330f729Sjoerg case CallingConv::AMDGPU_HS: Out << "amdgpu_hs"; break;
3987330f729Sjoerg case CallingConv::AMDGPU_ES: Out << "amdgpu_es"; break;
3997330f729Sjoerg case CallingConv::AMDGPU_GS: Out << "amdgpu_gs"; break;
4007330f729Sjoerg case CallingConv::AMDGPU_PS: Out << "amdgpu_ps"; break;
4017330f729Sjoerg case CallingConv::AMDGPU_CS: Out << "amdgpu_cs"; break;
4027330f729Sjoerg case CallingConv::AMDGPU_KERNEL: Out << "amdgpu_kernel"; break;
403*82d56013Sjoerg case CallingConv::AMDGPU_Gfx: Out << "amdgpu_gfx"; break;
4047330f729Sjoerg }
4057330f729Sjoerg }
4067330f729Sjoerg
4077330f729Sjoerg enum PrefixType {
4087330f729Sjoerg GlobalPrefix,
4097330f729Sjoerg ComdatPrefix,
4107330f729Sjoerg LabelPrefix,
4117330f729Sjoerg LocalPrefix,
4127330f729Sjoerg NoPrefix
4137330f729Sjoerg };
4147330f729Sjoerg
printLLVMNameWithoutPrefix(raw_ostream & OS,StringRef Name)4157330f729Sjoerg void llvm::printLLVMNameWithoutPrefix(raw_ostream &OS, StringRef Name) {
4167330f729Sjoerg assert(!Name.empty() && "Cannot get empty name!");
4177330f729Sjoerg
4187330f729Sjoerg // Scan the name to see if it needs quotes first.
4197330f729Sjoerg bool NeedsQuotes = isdigit(static_cast<unsigned char>(Name[0]));
4207330f729Sjoerg if (!NeedsQuotes) {
4217330f729Sjoerg for (unsigned i = 0, e = Name.size(); i != e; ++i) {
4227330f729Sjoerg // By making this unsigned, the value passed in to isalnum will always be
4237330f729Sjoerg // in the range 0-255. This is important when building with MSVC because
4247330f729Sjoerg // its implementation will assert. This situation can arise when dealing
4257330f729Sjoerg // with UTF-8 multibyte characters.
4267330f729Sjoerg unsigned char C = Name[i];
4277330f729Sjoerg if (!isalnum(static_cast<unsigned char>(C)) && C != '-' && C != '.' &&
4287330f729Sjoerg C != '_') {
4297330f729Sjoerg NeedsQuotes = true;
4307330f729Sjoerg break;
4317330f729Sjoerg }
4327330f729Sjoerg }
4337330f729Sjoerg }
4347330f729Sjoerg
4357330f729Sjoerg // If we didn't need any quotes, just write out the name in one blast.
4367330f729Sjoerg if (!NeedsQuotes) {
4377330f729Sjoerg OS << Name;
4387330f729Sjoerg return;
4397330f729Sjoerg }
4407330f729Sjoerg
4417330f729Sjoerg // Okay, we need quotes. Output the quotes and escape any scary characters as
4427330f729Sjoerg // needed.
4437330f729Sjoerg OS << '"';
4447330f729Sjoerg printEscapedString(Name, OS);
4457330f729Sjoerg OS << '"';
4467330f729Sjoerg }
4477330f729Sjoerg
4487330f729Sjoerg /// Turn the specified name into an 'LLVM name', which is either prefixed with %
4497330f729Sjoerg /// (if the string only contains simple characters) or is surrounded with ""'s
4507330f729Sjoerg /// (if it has special chars in it). Print it out.
PrintLLVMName(raw_ostream & OS,StringRef Name,PrefixType Prefix)4517330f729Sjoerg static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) {
4527330f729Sjoerg switch (Prefix) {
4537330f729Sjoerg case NoPrefix:
4547330f729Sjoerg break;
4557330f729Sjoerg case GlobalPrefix:
4567330f729Sjoerg OS << '@';
4577330f729Sjoerg break;
4587330f729Sjoerg case ComdatPrefix:
4597330f729Sjoerg OS << '$';
4607330f729Sjoerg break;
4617330f729Sjoerg case LabelPrefix:
4627330f729Sjoerg break;
4637330f729Sjoerg case LocalPrefix:
4647330f729Sjoerg OS << '%';
4657330f729Sjoerg break;
4667330f729Sjoerg }
4677330f729Sjoerg printLLVMNameWithoutPrefix(OS, Name);
4687330f729Sjoerg }
4697330f729Sjoerg
4707330f729Sjoerg /// Turn the specified name into an 'LLVM name', which is either prefixed with %
4717330f729Sjoerg /// (if the string only contains simple characters) or is surrounded with ""'s
4727330f729Sjoerg /// (if it has special chars in it). Print it out.
PrintLLVMName(raw_ostream & OS,const Value * V)4737330f729Sjoerg static void PrintLLVMName(raw_ostream &OS, const Value *V) {
4747330f729Sjoerg PrintLLVMName(OS, V->getName(),
4757330f729Sjoerg isa<GlobalValue>(V) ? GlobalPrefix : LocalPrefix);
4767330f729Sjoerg }
4777330f729Sjoerg
PrintShuffleMask(raw_ostream & Out,Type * Ty,ArrayRef<int> Mask)478*82d56013Sjoerg static void PrintShuffleMask(raw_ostream &Out, Type *Ty, ArrayRef<int> Mask) {
479*82d56013Sjoerg Out << ", <";
480*82d56013Sjoerg if (isa<ScalableVectorType>(Ty))
481*82d56013Sjoerg Out << "vscale x ";
482*82d56013Sjoerg Out << Mask.size() << " x i32> ";
483*82d56013Sjoerg bool FirstElt = true;
484*82d56013Sjoerg if (all_of(Mask, [](int Elt) { return Elt == 0; })) {
485*82d56013Sjoerg Out << "zeroinitializer";
486*82d56013Sjoerg } else if (all_of(Mask, [](int Elt) { return Elt == UndefMaskElem; })) {
487*82d56013Sjoerg Out << "undef";
488*82d56013Sjoerg } else {
489*82d56013Sjoerg Out << "<";
490*82d56013Sjoerg for (int Elt : Mask) {
491*82d56013Sjoerg if (FirstElt)
492*82d56013Sjoerg FirstElt = false;
493*82d56013Sjoerg else
494*82d56013Sjoerg Out << ", ";
495*82d56013Sjoerg Out << "i32 ";
496*82d56013Sjoerg if (Elt == UndefMaskElem)
497*82d56013Sjoerg Out << "undef";
498*82d56013Sjoerg else
499*82d56013Sjoerg Out << Elt;
500*82d56013Sjoerg }
501*82d56013Sjoerg Out << ">";
502*82d56013Sjoerg }
503*82d56013Sjoerg }
504*82d56013Sjoerg
5057330f729Sjoerg namespace {
5067330f729Sjoerg
5077330f729Sjoerg class TypePrinting {
5087330f729Sjoerg public:
TypePrinting(const Module * M=nullptr)5097330f729Sjoerg TypePrinting(const Module *M = nullptr) : DeferredM(M) {}
5107330f729Sjoerg
5117330f729Sjoerg TypePrinting(const TypePrinting &) = delete;
5127330f729Sjoerg TypePrinting &operator=(const TypePrinting &) = delete;
5137330f729Sjoerg
5147330f729Sjoerg /// The named types that are used by the current module.
5157330f729Sjoerg TypeFinder &getNamedTypes();
5167330f729Sjoerg
5177330f729Sjoerg /// The numbered types, number to type mapping.
5187330f729Sjoerg std::vector<StructType *> &getNumberedTypes();
5197330f729Sjoerg
5207330f729Sjoerg bool empty();
5217330f729Sjoerg
5227330f729Sjoerg void print(Type *Ty, raw_ostream &OS);
5237330f729Sjoerg
5247330f729Sjoerg void printStructBody(StructType *Ty, raw_ostream &OS);
5257330f729Sjoerg
5267330f729Sjoerg private:
5277330f729Sjoerg void incorporateTypes();
5287330f729Sjoerg
5297330f729Sjoerg /// A module to process lazily when needed. Set to nullptr as soon as used.
5307330f729Sjoerg const Module *DeferredM;
5317330f729Sjoerg
5327330f729Sjoerg TypeFinder NamedTypes;
5337330f729Sjoerg
5347330f729Sjoerg // The numbered types, along with their value.
5357330f729Sjoerg DenseMap<StructType *, unsigned> Type2Number;
5367330f729Sjoerg
5377330f729Sjoerg std::vector<StructType *> NumberedTypes;
5387330f729Sjoerg };
5397330f729Sjoerg
5407330f729Sjoerg } // end anonymous namespace
5417330f729Sjoerg
getNamedTypes()5427330f729Sjoerg TypeFinder &TypePrinting::getNamedTypes() {
5437330f729Sjoerg incorporateTypes();
5447330f729Sjoerg return NamedTypes;
5457330f729Sjoerg }
5467330f729Sjoerg
getNumberedTypes()5477330f729Sjoerg std::vector<StructType *> &TypePrinting::getNumberedTypes() {
5487330f729Sjoerg incorporateTypes();
5497330f729Sjoerg
5507330f729Sjoerg // We know all the numbers that each type is used and we know that it is a
5517330f729Sjoerg // dense assignment. Convert the map to an index table, if it's not done
5527330f729Sjoerg // already (judging from the sizes):
5537330f729Sjoerg if (NumberedTypes.size() == Type2Number.size())
5547330f729Sjoerg return NumberedTypes;
5557330f729Sjoerg
5567330f729Sjoerg NumberedTypes.resize(Type2Number.size());
5577330f729Sjoerg for (const auto &P : Type2Number) {
5587330f729Sjoerg assert(P.second < NumberedTypes.size() && "Didn't get a dense numbering?");
5597330f729Sjoerg assert(!NumberedTypes[P.second] && "Didn't get a unique numbering?");
5607330f729Sjoerg NumberedTypes[P.second] = P.first;
5617330f729Sjoerg }
5627330f729Sjoerg return NumberedTypes;
5637330f729Sjoerg }
5647330f729Sjoerg
empty()5657330f729Sjoerg bool TypePrinting::empty() {
5667330f729Sjoerg incorporateTypes();
5677330f729Sjoerg return NamedTypes.empty() && Type2Number.empty();
5687330f729Sjoerg }
5697330f729Sjoerg
incorporateTypes()5707330f729Sjoerg void TypePrinting::incorporateTypes() {
5717330f729Sjoerg if (!DeferredM)
5727330f729Sjoerg return;
5737330f729Sjoerg
5747330f729Sjoerg NamedTypes.run(*DeferredM, false);
5757330f729Sjoerg DeferredM = nullptr;
5767330f729Sjoerg
5777330f729Sjoerg // The list of struct types we got back includes all the struct types, split
5787330f729Sjoerg // the unnamed ones out to a numbering and remove the anonymous structs.
5797330f729Sjoerg unsigned NextNumber = 0;
5807330f729Sjoerg
5817330f729Sjoerg std::vector<StructType*>::iterator NextToUse = NamedTypes.begin(), I, E;
5827330f729Sjoerg for (I = NamedTypes.begin(), E = NamedTypes.end(); I != E; ++I) {
5837330f729Sjoerg StructType *STy = *I;
5847330f729Sjoerg
5857330f729Sjoerg // Ignore anonymous types.
5867330f729Sjoerg if (STy->isLiteral())
5877330f729Sjoerg continue;
5887330f729Sjoerg
5897330f729Sjoerg if (STy->getName().empty())
5907330f729Sjoerg Type2Number[STy] = NextNumber++;
5917330f729Sjoerg else
5927330f729Sjoerg *NextToUse++ = STy;
5937330f729Sjoerg }
5947330f729Sjoerg
5957330f729Sjoerg NamedTypes.erase(NextToUse, NamedTypes.end());
5967330f729Sjoerg }
5977330f729Sjoerg
5987330f729Sjoerg /// Write the specified type to the specified raw_ostream, making use of type
5997330f729Sjoerg /// names or up references to shorten the type name where possible.
print(Type * Ty,raw_ostream & OS)6007330f729Sjoerg void TypePrinting::print(Type *Ty, raw_ostream &OS) {
6017330f729Sjoerg switch (Ty->getTypeID()) {
6027330f729Sjoerg case Type::VoidTyID: OS << "void"; return;
6037330f729Sjoerg case Type::HalfTyID: OS << "half"; return;
604*82d56013Sjoerg case Type::BFloatTyID: OS << "bfloat"; return;
6057330f729Sjoerg case Type::FloatTyID: OS << "float"; return;
6067330f729Sjoerg case Type::DoubleTyID: OS << "double"; return;
6077330f729Sjoerg case Type::X86_FP80TyID: OS << "x86_fp80"; return;
6087330f729Sjoerg case Type::FP128TyID: OS << "fp128"; return;
6097330f729Sjoerg case Type::PPC_FP128TyID: OS << "ppc_fp128"; return;
6107330f729Sjoerg case Type::LabelTyID: OS << "label"; return;
6117330f729Sjoerg case Type::MetadataTyID: OS << "metadata"; return;
6127330f729Sjoerg case Type::X86_MMXTyID: OS << "x86_mmx"; return;
613*82d56013Sjoerg case Type::X86_AMXTyID: OS << "x86_amx"; return;
6147330f729Sjoerg case Type::TokenTyID: OS << "token"; return;
6157330f729Sjoerg case Type::IntegerTyID:
6167330f729Sjoerg OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
6177330f729Sjoerg return;
6187330f729Sjoerg
6197330f729Sjoerg case Type::FunctionTyID: {
6207330f729Sjoerg FunctionType *FTy = cast<FunctionType>(Ty);
6217330f729Sjoerg print(FTy->getReturnType(), OS);
6227330f729Sjoerg OS << " (";
6237330f729Sjoerg for (FunctionType::param_iterator I = FTy->param_begin(),
6247330f729Sjoerg E = FTy->param_end(); I != E; ++I) {
6257330f729Sjoerg if (I != FTy->param_begin())
6267330f729Sjoerg OS << ", ";
6277330f729Sjoerg print(*I, OS);
6287330f729Sjoerg }
6297330f729Sjoerg if (FTy->isVarArg()) {
6307330f729Sjoerg if (FTy->getNumParams()) OS << ", ";
6317330f729Sjoerg OS << "...";
6327330f729Sjoerg }
6337330f729Sjoerg OS << ')';
6347330f729Sjoerg return;
6357330f729Sjoerg }
6367330f729Sjoerg case Type::StructTyID: {
6377330f729Sjoerg StructType *STy = cast<StructType>(Ty);
6387330f729Sjoerg
6397330f729Sjoerg if (STy->isLiteral())
6407330f729Sjoerg return printStructBody(STy, OS);
6417330f729Sjoerg
6427330f729Sjoerg if (!STy->getName().empty())
6437330f729Sjoerg return PrintLLVMName(OS, STy->getName(), LocalPrefix);
6447330f729Sjoerg
6457330f729Sjoerg incorporateTypes();
6467330f729Sjoerg const auto I = Type2Number.find(STy);
6477330f729Sjoerg if (I != Type2Number.end())
6487330f729Sjoerg OS << '%' << I->second;
6497330f729Sjoerg else // Not enumerated, print the hex address.
6507330f729Sjoerg OS << "%\"type " << STy << '\"';
6517330f729Sjoerg return;
6527330f729Sjoerg }
6537330f729Sjoerg case Type::PointerTyID: {
6547330f729Sjoerg PointerType *PTy = cast<PointerType>(Ty);
655*82d56013Sjoerg if (PTy->isOpaque()) {
656*82d56013Sjoerg OS << "ptr";
657*82d56013Sjoerg if (unsigned AddressSpace = PTy->getAddressSpace())
658*82d56013Sjoerg OS << " addrspace(" << AddressSpace << ')';
659*82d56013Sjoerg return;
660*82d56013Sjoerg }
6617330f729Sjoerg print(PTy->getElementType(), OS);
6627330f729Sjoerg if (unsigned AddressSpace = PTy->getAddressSpace())
6637330f729Sjoerg OS << " addrspace(" << AddressSpace << ')';
6647330f729Sjoerg OS << '*';
6657330f729Sjoerg return;
6667330f729Sjoerg }
6677330f729Sjoerg case Type::ArrayTyID: {
6687330f729Sjoerg ArrayType *ATy = cast<ArrayType>(Ty);
6697330f729Sjoerg OS << '[' << ATy->getNumElements() << " x ";
6707330f729Sjoerg print(ATy->getElementType(), OS);
6717330f729Sjoerg OS << ']';
6727330f729Sjoerg return;
6737330f729Sjoerg }
674*82d56013Sjoerg case Type::FixedVectorTyID:
675*82d56013Sjoerg case Type::ScalableVectorTyID: {
6767330f729Sjoerg VectorType *PTy = cast<VectorType>(Ty);
677*82d56013Sjoerg ElementCount EC = PTy->getElementCount();
6787330f729Sjoerg OS << "<";
679*82d56013Sjoerg if (EC.isScalable())
6807330f729Sjoerg OS << "vscale x ";
681*82d56013Sjoerg OS << EC.getKnownMinValue() << " x ";
6827330f729Sjoerg print(PTy->getElementType(), OS);
6837330f729Sjoerg OS << '>';
6847330f729Sjoerg return;
6857330f729Sjoerg }
6867330f729Sjoerg }
6877330f729Sjoerg llvm_unreachable("Invalid TypeID");
6887330f729Sjoerg }
6897330f729Sjoerg
printStructBody(StructType * STy,raw_ostream & OS)6907330f729Sjoerg void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) {
6917330f729Sjoerg if (STy->isOpaque()) {
6927330f729Sjoerg OS << "opaque";
6937330f729Sjoerg return;
6947330f729Sjoerg }
6957330f729Sjoerg
6967330f729Sjoerg if (STy->isPacked())
6977330f729Sjoerg OS << '<';
6987330f729Sjoerg
6997330f729Sjoerg if (STy->getNumElements() == 0) {
7007330f729Sjoerg OS << "{}";
7017330f729Sjoerg } else {
7027330f729Sjoerg StructType::element_iterator I = STy->element_begin();
7037330f729Sjoerg OS << "{ ";
7047330f729Sjoerg print(*I++, OS);
7057330f729Sjoerg for (StructType::element_iterator E = STy->element_end(); I != E; ++I) {
7067330f729Sjoerg OS << ", ";
7077330f729Sjoerg print(*I, OS);
7087330f729Sjoerg }
7097330f729Sjoerg
7107330f729Sjoerg OS << " }";
7117330f729Sjoerg }
7127330f729Sjoerg if (STy->isPacked())
7137330f729Sjoerg OS << '>';
7147330f729Sjoerg }
7157330f729Sjoerg
7167330f729Sjoerg namespace llvm {
7177330f729Sjoerg
7187330f729Sjoerg //===----------------------------------------------------------------------===//
7197330f729Sjoerg // SlotTracker Class: Enumerate slot numbers for unnamed values
7207330f729Sjoerg //===----------------------------------------------------------------------===//
7217330f729Sjoerg /// This class provides computation of slot numbers for LLVM Assembly writing.
7227330f729Sjoerg ///
7237330f729Sjoerg class SlotTracker {
7247330f729Sjoerg public:
7257330f729Sjoerg /// ValueMap - A mapping of Values to slot numbers.
7267330f729Sjoerg using ValueMap = DenseMap<const Value *, unsigned>;
7277330f729Sjoerg
7287330f729Sjoerg private:
7297330f729Sjoerg /// TheModule - The module for which we are holding slot numbers.
7307330f729Sjoerg const Module* TheModule;
7317330f729Sjoerg
7327330f729Sjoerg /// TheFunction - The function for which we are holding slot numbers.
7337330f729Sjoerg const Function* TheFunction = nullptr;
7347330f729Sjoerg bool FunctionProcessed = false;
7357330f729Sjoerg bool ShouldInitializeAllMetadata;
7367330f729Sjoerg
7377330f729Sjoerg /// The summary index for which we are holding slot numbers.
7387330f729Sjoerg const ModuleSummaryIndex *TheIndex = nullptr;
7397330f729Sjoerg
7407330f729Sjoerg /// mMap - The slot map for the module level data.
7417330f729Sjoerg ValueMap mMap;
7427330f729Sjoerg unsigned mNext = 0;
7437330f729Sjoerg
7447330f729Sjoerg /// fMap - The slot map for the function level data.
7457330f729Sjoerg ValueMap fMap;
7467330f729Sjoerg unsigned fNext = 0;
7477330f729Sjoerg
7487330f729Sjoerg /// mdnMap - Map for MDNodes.
7497330f729Sjoerg DenseMap<const MDNode*, unsigned> mdnMap;
7507330f729Sjoerg unsigned mdnNext = 0;
7517330f729Sjoerg
7527330f729Sjoerg /// asMap - The slot map for attribute sets.
7537330f729Sjoerg DenseMap<AttributeSet, unsigned> asMap;
7547330f729Sjoerg unsigned asNext = 0;
7557330f729Sjoerg
7567330f729Sjoerg /// ModulePathMap - The slot map for Module paths used in the summary index.
7577330f729Sjoerg StringMap<unsigned> ModulePathMap;
7587330f729Sjoerg unsigned ModulePathNext = 0;
7597330f729Sjoerg
7607330f729Sjoerg /// GUIDMap - The slot map for GUIDs used in the summary index.
7617330f729Sjoerg DenseMap<GlobalValue::GUID, unsigned> GUIDMap;
7627330f729Sjoerg unsigned GUIDNext = 0;
7637330f729Sjoerg
7647330f729Sjoerg /// TypeIdMap - The slot map for type ids used in the summary index.
7657330f729Sjoerg StringMap<unsigned> TypeIdMap;
7667330f729Sjoerg unsigned TypeIdNext = 0;
7677330f729Sjoerg
7687330f729Sjoerg public:
7697330f729Sjoerg /// Construct from a module.
7707330f729Sjoerg ///
7717330f729Sjoerg /// If \c ShouldInitializeAllMetadata, initializes all metadata in all
7727330f729Sjoerg /// functions, giving correct numbering for metadata referenced only from
7737330f729Sjoerg /// within a function (even if no functions have been initialized).
7747330f729Sjoerg explicit SlotTracker(const Module *M,
7757330f729Sjoerg bool ShouldInitializeAllMetadata = false);
7767330f729Sjoerg
7777330f729Sjoerg /// Construct from a function, starting out in incorp state.
7787330f729Sjoerg ///
7797330f729Sjoerg /// If \c ShouldInitializeAllMetadata, initializes all metadata in all
7807330f729Sjoerg /// functions, giving correct numbering for metadata referenced only from
7817330f729Sjoerg /// within a function (even if no functions have been initialized).
7827330f729Sjoerg explicit SlotTracker(const Function *F,
7837330f729Sjoerg bool ShouldInitializeAllMetadata = false);
7847330f729Sjoerg
7857330f729Sjoerg /// Construct from a module summary index.
7867330f729Sjoerg explicit SlotTracker(const ModuleSummaryIndex *Index);
7877330f729Sjoerg
7887330f729Sjoerg SlotTracker(const SlotTracker &) = delete;
7897330f729Sjoerg SlotTracker &operator=(const SlotTracker &) = delete;
7907330f729Sjoerg
7917330f729Sjoerg /// Return the slot number of the specified value in it's type
7927330f729Sjoerg /// plane. If something is not in the SlotTracker, return -1.
7937330f729Sjoerg int getLocalSlot(const Value *V);
7947330f729Sjoerg int getGlobalSlot(const GlobalValue *V);
7957330f729Sjoerg int getMetadataSlot(const MDNode *N);
7967330f729Sjoerg int getAttributeGroupSlot(AttributeSet AS);
7977330f729Sjoerg int getModulePathSlot(StringRef Path);
7987330f729Sjoerg int getGUIDSlot(GlobalValue::GUID GUID);
7997330f729Sjoerg int getTypeIdSlot(StringRef Id);
8007330f729Sjoerg
8017330f729Sjoerg /// If you'd like to deal with a function instead of just a module, use
8027330f729Sjoerg /// this method to get its data into the SlotTracker.
incorporateFunction(const Function * F)8037330f729Sjoerg void incorporateFunction(const Function *F) {
8047330f729Sjoerg TheFunction = F;
8057330f729Sjoerg FunctionProcessed = false;
8067330f729Sjoerg }
8077330f729Sjoerg
getFunction() const8087330f729Sjoerg const Function *getFunction() const { return TheFunction; }
8097330f729Sjoerg
8107330f729Sjoerg /// After calling incorporateFunction, use this method to remove the
8117330f729Sjoerg /// most recently incorporated function from the SlotTracker. This
8127330f729Sjoerg /// will reset the state of the machine back to just the module contents.
8137330f729Sjoerg void purgeFunction();
8147330f729Sjoerg
8157330f729Sjoerg /// MDNode map iterators.
8167330f729Sjoerg using mdn_iterator = DenseMap<const MDNode*, unsigned>::iterator;
8177330f729Sjoerg
mdn_begin()8187330f729Sjoerg mdn_iterator mdn_begin() { return mdnMap.begin(); }
mdn_end()8197330f729Sjoerg mdn_iterator mdn_end() { return mdnMap.end(); }
mdn_size() const8207330f729Sjoerg unsigned mdn_size() const { return mdnMap.size(); }
mdn_empty() const8217330f729Sjoerg bool mdn_empty() const { return mdnMap.empty(); }
8227330f729Sjoerg
8237330f729Sjoerg /// AttributeSet map iterators.
8247330f729Sjoerg using as_iterator = DenseMap<AttributeSet, unsigned>::iterator;
8257330f729Sjoerg
as_begin()8267330f729Sjoerg as_iterator as_begin() { return asMap.begin(); }
as_end()8277330f729Sjoerg as_iterator as_end() { return asMap.end(); }
as_size() const8287330f729Sjoerg unsigned as_size() const { return asMap.size(); }
as_empty() const8297330f729Sjoerg bool as_empty() const { return asMap.empty(); }
8307330f729Sjoerg
8317330f729Sjoerg /// GUID map iterators.
8327330f729Sjoerg using guid_iterator = DenseMap<GlobalValue::GUID, unsigned>::iterator;
8337330f729Sjoerg
8347330f729Sjoerg /// These functions do the actual initialization.
8357330f729Sjoerg inline void initializeIfNeeded();
836*82d56013Sjoerg int initializeIndexIfNeeded();
8377330f729Sjoerg
8387330f729Sjoerg // Implementation Details
8397330f729Sjoerg private:
8407330f729Sjoerg /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
8417330f729Sjoerg void CreateModuleSlot(const GlobalValue *V);
8427330f729Sjoerg
8437330f729Sjoerg /// CreateMetadataSlot - Insert the specified MDNode* into the slot table.
8447330f729Sjoerg void CreateMetadataSlot(const MDNode *N);
8457330f729Sjoerg
8467330f729Sjoerg /// CreateFunctionSlot - Insert the specified Value* into the slot table.
8477330f729Sjoerg void CreateFunctionSlot(const Value *V);
8487330f729Sjoerg
8497330f729Sjoerg /// Insert the specified AttributeSet into the slot table.
8507330f729Sjoerg void CreateAttributeSetSlot(AttributeSet AS);
8517330f729Sjoerg
8527330f729Sjoerg inline void CreateModulePathSlot(StringRef Path);
8537330f729Sjoerg void CreateGUIDSlot(GlobalValue::GUID GUID);
8547330f729Sjoerg void CreateTypeIdSlot(StringRef Id);
8557330f729Sjoerg
8567330f729Sjoerg /// Add all of the module level global variables (and their initializers)
8577330f729Sjoerg /// and function declarations, but not the contents of those functions.
8587330f729Sjoerg void processModule();
859*82d56013Sjoerg // Returns number of allocated slots
860*82d56013Sjoerg int processIndex();
8617330f729Sjoerg
8627330f729Sjoerg /// Add all of the functions arguments, basic blocks, and instructions.
8637330f729Sjoerg void processFunction();
8647330f729Sjoerg
8657330f729Sjoerg /// Add the metadata directly attached to a GlobalObject.
8667330f729Sjoerg void processGlobalObjectMetadata(const GlobalObject &GO);
8677330f729Sjoerg
8687330f729Sjoerg /// Add all of the metadata from a function.
8697330f729Sjoerg void processFunctionMetadata(const Function &F);
8707330f729Sjoerg
8717330f729Sjoerg /// Add all of the metadata from an instruction.
8727330f729Sjoerg void processInstructionMetadata(const Instruction &I);
8737330f729Sjoerg };
8747330f729Sjoerg
8757330f729Sjoerg } // end namespace llvm
8767330f729Sjoerg
ModuleSlotTracker(SlotTracker & Machine,const Module * M,const Function * F)8777330f729Sjoerg ModuleSlotTracker::ModuleSlotTracker(SlotTracker &Machine, const Module *M,
8787330f729Sjoerg const Function *F)
8797330f729Sjoerg : M(M), F(F), Machine(&Machine) {}
8807330f729Sjoerg
ModuleSlotTracker(const Module * M,bool ShouldInitializeAllMetadata)8817330f729Sjoerg ModuleSlotTracker::ModuleSlotTracker(const Module *M,
8827330f729Sjoerg bool ShouldInitializeAllMetadata)
8837330f729Sjoerg : ShouldCreateStorage(M),
8847330f729Sjoerg ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), M(M) {}
8857330f729Sjoerg
8867330f729Sjoerg ModuleSlotTracker::~ModuleSlotTracker() = default;
8877330f729Sjoerg
getMachine()8887330f729Sjoerg SlotTracker *ModuleSlotTracker::getMachine() {
8897330f729Sjoerg if (!ShouldCreateStorage)
8907330f729Sjoerg return Machine;
8917330f729Sjoerg
8927330f729Sjoerg ShouldCreateStorage = false;
8937330f729Sjoerg MachineStorage =
8947330f729Sjoerg std::make_unique<SlotTracker>(M, ShouldInitializeAllMetadata);
8957330f729Sjoerg Machine = MachineStorage.get();
8967330f729Sjoerg return Machine;
8977330f729Sjoerg }
8987330f729Sjoerg
incorporateFunction(const Function & F)8997330f729Sjoerg void ModuleSlotTracker::incorporateFunction(const Function &F) {
9007330f729Sjoerg // Using getMachine() may lazily create the slot tracker.
9017330f729Sjoerg if (!getMachine())
9027330f729Sjoerg return;
9037330f729Sjoerg
9047330f729Sjoerg // Nothing to do if this is the right function already.
9057330f729Sjoerg if (this->F == &F)
9067330f729Sjoerg return;
9077330f729Sjoerg if (this->F)
9087330f729Sjoerg Machine->purgeFunction();
9097330f729Sjoerg Machine->incorporateFunction(&F);
9107330f729Sjoerg this->F = &F;
9117330f729Sjoerg }
9127330f729Sjoerg
getLocalSlot(const Value * V)9137330f729Sjoerg int ModuleSlotTracker::getLocalSlot(const Value *V) {
9147330f729Sjoerg assert(F && "No function incorporated");
9157330f729Sjoerg return Machine->getLocalSlot(V);
9167330f729Sjoerg }
9177330f729Sjoerg
createSlotTracker(const Value * V)9187330f729Sjoerg static SlotTracker *createSlotTracker(const Value *V) {
9197330f729Sjoerg if (const Argument *FA = dyn_cast<Argument>(V))
9207330f729Sjoerg return new SlotTracker(FA->getParent());
9217330f729Sjoerg
9227330f729Sjoerg if (const Instruction *I = dyn_cast<Instruction>(V))
9237330f729Sjoerg if (I->getParent())
9247330f729Sjoerg return new SlotTracker(I->getParent()->getParent());
9257330f729Sjoerg
9267330f729Sjoerg if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
9277330f729Sjoerg return new SlotTracker(BB->getParent());
9287330f729Sjoerg
9297330f729Sjoerg if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
9307330f729Sjoerg return new SlotTracker(GV->getParent());
9317330f729Sjoerg
9327330f729Sjoerg if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
9337330f729Sjoerg return new SlotTracker(GA->getParent());
9347330f729Sjoerg
9357330f729Sjoerg if (const GlobalIFunc *GIF = dyn_cast<GlobalIFunc>(V))
9367330f729Sjoerg return new SlotTracker(GIF->getParent());
9377330f729Sjoerg
9387330f729Sjoerg if (const Function *Func = dyn_cast<Function>(V))
9397330f729Sjoerg return new SlotTracker(Func);
9407330f729Sjoerg
9417330f729Sjoerg return nullptr;
9427330f729Sjoerg }
9437330f729Sjoerg
9447330f729Sjoerg #if 0
9457330f729Sjoerg #define ST_DEBUG(X) dbgs() << X
9467330f729Sjoerg #else
9477330f729Sjoerg #define ST_DEBUG(X)
9487330f729Sjoerg #endif
9497330f729Sjoerg
9507330f729Sjoerg // Module level constructor. Causes the contents of the Module (sans functions)
9517330f729Sjoerg // to be added to the slot table.
SlotTracker(const Module * M,bool ShouldInitializeAllMetadata)9527330f729Sjoerg SlotTracker::SlotTracker(const Module *M, bool ShouldInitializeAllMetadata)
9537330f729Sjoerg : TheModule(M), ShouldInitializeAllMetadata(ShouldInitializeAllMetadata) {}
9547330f729Sjoerg
9557330f729Sjoerg // Function level constructor. Causes the contents of the Module and the one
9567330f729Sjoerg // function provided to be added to the slot table.
SlotTracker(const Function * F,bool ShouldInitializeAllMetadata)9577330f729Sjoerg SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata)
9587330f729Sjoerg : TheModule(F ? F->getParent() : nullptr), TheFunction(F),
9597330f729Sjoerg ShouldInitializeAllMetadata(ShouldInitializeAllMetadata) {}
9607330f729Sjoerg
SlotTracker(const ModuleSummaryIndex * Index)9617330f729Sjoerg SlotTracker::SlotTracker(const ModuleSummaryIndex *Index)
9627330f729Sjoerg : TheModule(nullptr), ShouldInitializeAllMetadata(false), TheIndex(Index) {}
9637330f729Sjoerg
initializeIfNeeded()9647330f729Sjoerg inline void SlotTracker::initializeIfNeeded() {
9657330f729Sjoerg if (TheModule) {
9667330f729Sjoerg processModule();
9677330f729Sjoerg TheModule = nullptr; ///< Prevent re-processing next time we're called.
9687330f729Sjoerg }
9697330f729Sjoerg
9707330f729Sjoerg if (TheFunction && !FunctionProcessed)
9717330f729Sjoerg processFunction();
9727330f729Sjoerg }
9737330f729Sjoerg
initializeIndexIfNeeded()974*82d56013Sjoerg int SlotTracker::initializeIndexIfNeeded() {
9757330f729Sjoerg if (!TheIndex)
976*82d56013Sjoerg return 0;
977*82d56013Sjoerg int NumSlots = processIndex();
9787330f729Sjoerg TheIndex = nullptr; ///< Prevent re-processing next time we're called.
979*82d56013Sjoerg return NumSlots;
9807330f729Sjoerg }
9817330f729Sjoerg
9827330f729Sjoerg // Iterate through all the global variables, functions, and global
9837330f729Sjoerg // variable initializers and create slots for them.
processModule()9847330f729Sjoerg void SlotTracker::processModule() {
9857330f729Sjoerg ST_DEBUG("begin processModule!\n");
9867330f729Sjoerg
9877330f729Sjoerg // Add all of the unnamed global variables to the value table.
9887330f729Sjoerg for (const GlobalVariable &Var : TheModule->globals()) {
9897330f729Sjoerg if (!Var.hasName())
9907330f729Sjoerg CreateModuleSlot(&Var);
9917330f729Sjoerg processGlobalObjectMetadata(Var);
9927330f729Sjoerg auto Attrs = Var.getAttributes();
9937330f729Sjoerg if (Attrs.hasAttributes())
9947330f729Sjoerg CreateAttributeSetSlot(Attrs);
9957330f729Sjoerg }
9967330f729Sjoerg
9977330f729Sjoerg for (const GlobalAlias &A : TheModule->aliases()) {
9987330f729Sjoerg if (!A.hasName())
9997330f729Sjoerg CreateModuleSlot(&A);
10007330f729Sjoerg }
10017330f729Sjoerg
10027330f729Sjoerg for (const GlobalIFunc &I : TheModule->ifuncs()) {
10037330f729Sjoerg if (!I.hasName())
10047330f729Sjoerg CreateModuleSlot(&I);
10057330f729Sjoerg }
10067330f729Sjoerg
10077330f729Sjoerg // Add metadata used by named metadata.
10087330f729Sjoerg for (const NamedMDNode &NMD : TheModule->named_metadata()) {
10097330f729Sjoerg for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
10107330f729Sjoerg CreateMetadataSlot(NMD.getOperand(i));
10117330f729Sjoerg }
10127330f729Sjoerg
10137330f729Sjoerg for (const Function &F : *TheModule) {
10147330f729Sjoerg if (!F.hasName())
10157330f729Sjoerg // Add all the unnamed functions to the table.
10167330f729Sjoerg CreateModuleSlot(&F);
10177330f729Sjoerg
10187330f729Sjoerg if (ShouldInitializeAllMetadata)
10197330f729Sjoerg processFunctionMetadata(F);
10207330f729Sjoerg
10217330f729Sjoerg // Add all the function attributes to the table.
10227330f729Sjoerg // FIXME: Add attributes of other objects?
10237330f729Sjoerg AttributeSet FnAttrs = F.getAttributes().getFnAttributes();
10247330f729Sjoerg if (FnAttrs.hasAttributes())
10257330f729Sjoerg CreateAttributeSetSlot(FnAttrs);
10267330f729Sjoerg }
10277330f729Sjoerg
10287330f729Sjoerg ST_DEBUG("end processModule!\n");
10297330f729Sjoerg }
10307330f729Sjoerg
10317330f729Sjoerg // Process the arguments, basic blocks, and instructions of a function.
processFunction()10327330f729Sjoerg void SlotTracker::processFunction() {
10337330f729Sjoerg ST_DEBUG("begin processFunction!\n");
10347330f729Sjoerg fNext = 0;
10357330f729Sjoerg
10367330f729Sjoerg // Process function metadata if it wasn't hit at the module-level.
10377330f729Sjoerg if (!ShouldInitializeAllMetadata)
10387330f729Sjoerg processFunctionMetadata(*TheFunction);
10397330f729Sjoerg
10407330f729Sjoerg // Add all the function arguments with no names.
10417330f729Sjoerg for(Function::const_arg_iterator AI = TheFunction->arg_begin(),
10427330f729Sjoerg AE = TheFunction->arg_end(); AI != AE; ++AI)
10437330f729Sjoerg if (!AI->hasName())
10447330f729Sjoerg CreateFunctionSlot(&*AI);
10457330f729Sjoerg
10467330f729Sjoerg ST_DEBUG("Inserting Instructions:\n");
10477330f729Sjoerg
10487330f729Sjoerg // Add all of the basic blocks and instructions with no names.
10497330f729Sjoerg for (auto &BB : *TheFunction) {
10507330f729Sjoerg if (!BB.hasName())
10517330f729Sjoerg CreateFunctionSlot(&BB);
10527330f729Sjoerg
10537330f729Sjoerg for (auto &I : BB) {
10547330f729Sjoerg if (!I.getType()->isVoidTy() && !I.hasName())
10557330f729Sjoerg CreateFunctionSlot(&I);
10567330f729Sjoerg
10577330f729Sjoerg // We allow direct calls to any llvm.foo function here, because the
10587330f729Sjoerg // target may not be linked into the optimizer.
10597330f729Sjoerg if (const auto *Call = dyn_cast<CallBase>(&I)) {
10607330f729Sjoerg // Add all the call attributes to the table.
10617330f729Sjoerg AttributeSet Attrs = Call->getAttributes().getFnAttributes();
10627330f729Sjoerg if (Attrs.hasAttributes())
10637330f729Sjoerg CreateAttributeSetSlot(Attrs);
10647330f729Sjoerg }
10657330f729Sjoerg }
10667330f729Sjoerg }
10677330f729Sjoerg
10687330f729Sjoerg FunctionProcessed = true;
10697330f729Sjoerg
10707330f729Sjoerg ST_DEBUG("end processFunction!\n");
10717330f729Sjoerg }
10727330f729Sjoerg
10737330f729Sjoerg // Iterate through all the GUID in the index and create slots for them.
processIndex()1074*82d56013Sjoerg int SlotTracker::processIndex() {
10757330f729Sjoerg ST_DEBUG("begin processIndex!\n");
10767330f729Sjoerg assert(TheIndex);
10777330f729Sjoerg
10787330f729Sjoerg // The first block of slots are just the module ids, which start at 0 and are
10797330f729Sjoerg // assigned consecutively. Since the StringMap iteration order isn't
10807330f729Sjoerg // guaranteed, use a std::map to order by module ID before assigning slots.
10817330f729Sjoerg std::map<uint64_t, StringRef> ModuleIdToPathMap;
10827330f729Sjoerg for (auto &ModPath : TheIndex->modulePaths())
10837330f729Sjoerg ModuleIdToPathMap[ModPath.second.first] = ModPath.first();
10847330f729Sjoerg for (auto &ModPair : ModuleIdToPathMap)
10857330f729Sjoerg CreateModulePathSlot(ModPair.second);
10867330f729Sjoerg
10877330f729Sjoerg // Start numbering the GUIDs after the module ids.
10887330f729Sjoerg GUIDNext = ModulePathNext;
10897330f729Sjoerg
10907330f729Sjoerg for (auto &GlobalList : *TheIndex)
10917330f729Sjoerg CreateGUIDSlot(GlobalList.first);
10927330f729Sjoerg
10937330f729Sjoerg for (auto &TId : TheIndex->typeIdCompatibleVtableMap())
10947330f729Sjoerg CreateGUIDSlot(GlobalValue::getGUID(TId.first));
10957330f729Sjoerg
1096*82d56013Sjoerg // Start numbering the TypeIds after the GUIDs.
1097*82d56013Sjoerg TypeIdNext = GUIDNext;
1098*82d56013Sjoerg for (const auto &TID : TheIndex->typeIds())
1099*82d56013Sjoerg CreateTypeIdSlot(TID.second.first);
1100*82d56013Sjoerg
11017330f729Sjoerg ST_DEBUG("end processIndex!\n");
1102*82d56013Sjoerg return TypeIdNext;
11037330f729Sjoerg }
11047330f729Sjoerg
processGlobalObjectMetadata(const GlobalObject & GO)11057330f729Sjoerg void SlotTracker::processGlobalObjectMetadata(const GlobalObject &GO) {
11067330f729Sjoerg SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
11077330f729Sjoerg GO.getAllMetadata(MDs);
11087330f729Sjoerg for (auto &MD : MDs)
11097330f729Sjoerg CreateMetadataSlot(MD.second);
11107330f729Sjoerg }
11117330f729Sjoerg
processFunctionMetadata(const Function & F)11127330f729Sjoerg void SlotTracker::processFunctionMetadata(const Function &F) {
11137330f729Sjoerg processGlobalObjectMetadata(F);
11147330f729Sjoerg for (auto &BB : F) {
11157330f729Sjoerg for (auto &I : BB)
11167330f729Sjoerg processInstructionMetadata(I);
11177330f729Sjoerg }
11187330f729Sjoerg }
11197330f729Sjoerg
processInstructionMetadata(const Instruction & I)11207330f729Sjoerg void SlotTracker::processInstructionMetadata(const Instruction &I) {
11217330f729Sjoerg // Process metadata used directly by intrinsics.
11227330f729Sjoerg if (const CallInst *CI = dyn_cast<CallInst>(&I))
11237330f729Sjoerg if (Function *F = CI->getCalledFunction())
11247330f729Sjoerg if (F->isIntrinsic())
11257330f729Sjoerg for (auto &Op : I.operands())
11267330f729Sjoerg if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
11277330f729Sjoerg if (MDNode *N = dyn_cast<MDNode>(V->getMetadata()))
11287330f729Sjoerg CreateMetadataSlot(N);
11297330f729Sjoerg
11307330f729Sjoerg // Process metadata attached to this instruction.
11317330f729Sjoerg SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
11327330f729Sjoerg I.getAllMetadata(MDs);
11337330f729Sjoerg for (auto &MD : MDs)
11347330f729Sjoerg CreateMetadataSlot(MD.second);
11357330f729Sjoerg }
11367330f729Sjoerg
11377330f729Sjoerg /// Clean up after incorporating a function. This is the only way to get out of
11387330f729Sjoerg /// the function incorporation state that affects get*Slot/Create*Slot. Function
11397330f729Sjoerg /// incorporation state is indicated by TheFunction != 0.
purgeFunction()11407330f729Sjoerg void SlotTracker::purgeFunction() {
11417330f729Sjoerg ST_DEBUG("begin purgeFunction!\n");
11427330f729Sjoerg fMap.clear(); // Simply discard the function level map
11437330f729Sjoerg TheFunction = nullptr;
11447330f729Sjoerg FunctionProcessed = false;
11457330f729Sjoerg ST_DEBUG("end purgeFunction!\n");
11467330f729Sjoerg }
11477330f729Sjoerg
11487330f729Sjoerg /// getGlobalSlot - Get the slot number of a global value.
getGlobalSlot(const GlobalValue * V)11497330f729Sjoerg int SlotTracker::getGlobalSlot(const GlobalValue *V) {
11507330f729Sjoerg // Check for uninitialized state and do lazy initialization.
11517330f729Sjoerg initializeIfNeeded();
11527330f729Sjoerg
11537330f729Sjoerg // Find the value in the module map
11547330f729Sjoerg ValueMap::iterator MI = mMap.find(V);
11557330f729Sjoerg return MI == mMap.end() ? -1 : (int)MI->second;
11567330f729Sjoerg }
11577330f729Sjoerg
11587330f729Sjoerg /// getMetadataSlot - Get the slot number of a MDNode.
getMetadataSlot(const MDNode * N)11597330f729Sjoerg int SlotTracker::getMetadataSlot(const MDNode *N) {
11607330f729Sjoerg // Check for uninitialized state and do lazy initialization.
11617330f729Sjoerg initializeIfNeeded();
11627330f729Sjoerg
11637330f729Sjoerg // Find the MDNode in the module map
11647330f729Sjoerg mdn_iterator MI = mdnMap.find(N);
11657330f729Sjoerg return MI == mdnMap.end() ? -1 : (int)MI->second;
11667330f729Sjoerg }
11677330f729Sjoerg
11687330f729Sjoerg /// getLocalSlot - Get the slot number for a value that is local to a function.
getLocalSlot(const Value * V)11697330f729Sjoerg int SlotTracker::getLocalSlot(const Value *V) {
11707330f729Sjoerg assert(!isa<Constant>(V) && "Can't get a constant or global slot with this!");
11717330f729Sjoerg
11727330f729Sjoerg // Check for uninitialized state and do lazy initialization.
11737330f729Sjoerg initializeIfNeeded();
11747330f729Sjoerg
11757330f729Sjoerg ValueMap::iterator FI = fMap.find(V);
11767330f729Sjoerg return FI == fMap.end() ? -1 : (int)FI->second;
11777330f729Sjoerg }
11787330f729Sjoerg
getAttributeGroupSlot(AttributeSet AS)11797330f729Sjoerg int SlotTracker::getAttributeGroupSlot(AttributeSet AS) {
11807330f729Sjoerg // Check for uninitialized state and do lazy initialization.
11817330f729Sjoerg initializeIfNeeded();
11827330f729Sjoerg
11837330f729Sjoerg // Find the AttributeSet in the module map.
11847330f729Sjoerg as_iterator AI = asMap.find(AS);
11857330f729Sjoerg return AI == asMap.end() ? -1 : (int)AI->second;
11867330f729Sjoerg }
11877330f729Sjoerg
getModulePathSlot(StringRef Path)11887330f729Sjoerg int SlotTracker::getModulePathSlot(StringRef Path) {
11897330f729Sjoerg // Check for uninitialized state and do lazy initialization.
11907330f729Sjoerg initializeIndexIfNeeded();
11917330f729Sjoerg
11927330f729Sjoerg // Find the Module path in the map
11937330f729Sjoerg auto I = ModulePathMap.find(Path);
11947330f729Sjoerg return I == ModulePathMap.end() ? -1 : (int)I->second;
11957330f729Sjoerg }
11967330f729Sjoerg
getGUIDSlot(GlobalValue::GUID GUID)11977330f729Sjoerg int SlotTracker::getGUIDSlot(GlobalValue::GUID GUID) {
11987330f729Sjoerg // Check for uninitialized state and do lazy initialization.
11997330f729Sjoerg initializeIndexIfNeeded();
12007330f729Sjoerg
12017330f729Sjoerg // Find the GUID in the map
12027330f729Sjoerg guid_iterator I = GUIDMap.find(GUID);
12037330f729Sjoerg return I == GUIDMap.end() ? -1 : (int)I->second;
12047330f729Sjoerg }
12057330f729Sjoerg
getTypeIdSlot(StringRef Id)12067330f729Sjoerg int SlotTracker::getTypeIdSlot(StringRef Id) {
12077330f729Sjoerg // Check for uninitialized state and do lazy initialization.
12087330f729Sjoerg initializeIndexIfNeeded();
12097330f729Sjoerg
12107330f729Sjoerg // Find the TypeId string in the map
12117330f729Sjoerg auto I = TypeIdMap.find(Id);
12127330f729Sjoerg return I == TypeIdMap.end() ? -1 : (int)I->second;
12137330f729Sjoerg }
12147330f729Sjoerg
12157330f729Sjoerg /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table.
CreateModuleSlot(const GlobalValue * V)12167330f729Sjoerg void SlotTracker::CreateModuleSlot(const GlobalValue *V) {
12177330f729Sjoerg assert(V && "Can't insert a null Value into SlotTracker!");
12187330f729Sjoerg assert(!V->getType()->isVoidTy() && "Doesn't need a slot!");
12197330f729Sjoerg assert(!V->hasName() && "Doesn't need a slot!");
12207330f729Sjoerg
12217330f729Sjoerg unsigned DestSlot = mNext++;
12227330f729Sjoerg mMap[V] = DestSlot;
12237330f729Sjoerg
12247330f729Sjoerg ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" <<
12257330f729Sjoerg DestSlot << " [");
12267330f729Sjoerg // G = Global, F = Function, A = Alias, I = IFunc, o = other
12277330f729Sjoerg ST_DEBUG((isa<GlobalVariable>(V) ? 'G' :
12287330f729Sjoerg (isa<Function>(V) ? 'F' :
12297330f729Sjoerg (isa<GlobalAlias>(V) ? 'A' :
12307330f729Sjoerg (isa<GlobalIFunc>(V) ? 'I' : 'o')))) << "]\n");
12317330f729Sjoerg }
12327330f729Sjoerg
12337330f729Sjoerg /// CreateSlot - Create a new slot for the specified value if it has no name.
CreateFunctionSlot(const Value * V)12347330f729Sjoerg void SlotTracker::CreateFunctionSlot(const Value *V) {
12357330f729Sjoerg assert(!V->getType()->isVoidTy() && !V->hasName() && "Doesn't need a slot!");
12367330f729Sjoerg
12377330f729Sjoerg unsigned DestSlot = fNext++;
12387330f729Sjoerg fMap[V] = DestSlot;
12397330f729Sjoerg
12407330f729Sjoerg // G = Global, F = Function, o = other
12417330f729Sjoerg ST_DEBUG(" Inserting value [" << V->getType() << "] = " << V << " slot=" <<
12427330f729Sjoerg DestSlot << " [o]\n");
12437330f729Sjoerg }
12447330f729Sjoerg
12457330f729Sjoerg /// CreateModuleSlot - Insert the specified MDNode* into the slot table.
CreateMetadataSlot(const MDNode * N)12467330f729Sjoerg void SlotTracker::CreateMetadataSlot(const MDNode *N) {
12477330f729Sjoerg assert(N && "Can't insert a null Value into SlotTracker!");
12487330f729Sjoerg
1249*82d56013Sjoerg // Don't make slots for DIExpressions or DIArgLists. We just print them inline
1250*82d56013Sjoerg // everywhere.
1251*82d56013Sjoerg if (isa<DIExpression>(N) || isa<DIArgList>(N))
12527330f729Sjoerg return;
12537330f729Sjoerg
12547330f729Sjoerg unsigned DestSlot = mdnNext;
12557330f729Sjoerg if (!mdnMap.insert(std::make_pair(N, DestSlot)).second)
12567330f729Sjoerg return;
12577330f729Sjoerg ++mdnNext;
12587330f729Sjoerg
12597330f729Sjoerg // Recursively add any MDNodes referenced by operands.
12607330f729Sjoerg for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
12617330f729Sjoerg if (const MDNode *Op = dyn_cast_or_null<MDNode>(N->getOperand(i)))
12627330f729Sjoerg CreateMetadataSlot(Op);
12637330f729Sjoerg }
12647330f729Sjoerg
CreateAttributeSetSlot(AttributeSet AS)12657330f729Sjoerg void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) {
12667330f729Sjoerg assert(AS.hasAttributes() && "Doesn't need a slot!");
12677330f729Sjoerg
12687330f729Sjoerg as_iterator I = asMap.find(AS);
12697330f729Sjoerg if (I != asMap.end())
12707330f729Sjoerg return;
12717330f729Sjoerg
12727330f729Sjoerg unsigned DestSlot = asNext++;
12737330f729Sjoerg asMap[AS] = DestSlot;
12747330f729Sjoerg }
12757330f729Sjoerg
12767330f729Sjoerg /// Create a new slot for the specified Module
CreateModulePathSlot(StringRef Path)12777330f729Sjoerg void SlotTracker::CreateModulePathSlot(StringRef Path) {
12787330f729Sjoerg ModulePathMap[Path] = ModulePathNext++;
12797330f729Sjoerg }
12807330f729Sjoerg
12817330f729Sjoerg /// Create a new slot for the specified GUID
CreateGUIDSlot(GlobalValue::GUID GUID)12827330f729Sjoerg void SlotTracker::CreateGUIDSlot(GlobalValue::GUID GUID) {
12837330f729Sjoerg GUIDMap[GUID] = GUIDNext++;
12847330f729Sjoerg }
12857330f729Sjoerg
12867330f729Sjoerg /// Create a new slot for the specified Id
CreateTypeIdSlot(StringRef Id)12877330f729Sjoerg void SlotTracker::CreateTypeIdSlot(StringRef Id) {
12887330f729Sjoerg TypeIdMap[Id] = TypeIdNext++;
12897330f729Sjoerg }
12907330f729Sjoerg
12917330f729Sjoerg //===----------------------------------------------------------------------===//
12927330f729Sjoerg // AsmWriter Implementation
12937330f729Sjoerg //===----------------------------------------------------------------------===//
12947330f729Sjoerg
12957330f729Sjoerg static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
12967330f729Sjoerg TypePrinting *TypePrinter,
12977330f729Sjoerg SlotTracker *Machine,
12987330f729Sjoerg const Module *Context);
12997330f729Sjoerg
13007330f729Sjoerg static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
13017330f729Sjoerg TypePrinting *TypePrinter,
13027330f729Sjoerg SlotTracker *Machine, const Module *Context,
13037330f729Sjoerg bool FromValue = false);
13047330f729Sjoerg
WriteOptimizationInfo(raw_ostream & Out,const User * U)13057330f729Sjoerg static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
13067330f729Sjoerg if (const FPMathOperator *FPO = dyn_cast<const FPMathOperator>(U)) {
13077330f729Sjoerg // 'Fast' is an abbreviation for all fast-math-flags.
13087330f729Sjoerg if (FPO->isFast())
13097330f729Sjoerg Out << " fast";
13107330f729Sjoerg else {
13117330f729Sjoerg if (FPO->hasAllowReassoc())
13127330f729Sjoerg Out << " reassoc";
13137330f729Sjoerg if (FPO->hasNoNaNs())
13147330f729Sjoerg Out << " nnan";
13157330f729Sjoerg if (FPO->hasNoInfs())
13167330f729Sjoerg Out << " ninf";
13177330f729Sjoerg if (FPO->hasNoSignedZeros())
13187330f729Sjoerg Out << " nsz";
13197330f729Sjoerg if (FPO->hasAllowReciprocal())
13207330f729Sjoerg Out << " arcp";
13217330f729Sjoerg if (FPO->hasAllowContract())
13227330f729Sjoerg Out << " contract";
13237330f729Sjoerg if (FPO->hasApproxFunc())
13247330f729Sjoerg Out << " afn";
13257330f729Sjoerg }
13267330f729Sjoerg }
13277330f729Sjoerg
13287330f729Sjoerg if (const OverflowingBinaryOperator *OBO =
13297330f729Sjoerg dyn_cast<OverflowingBinaryOperator>(U)) {
13307330f729Sjoerg if (OBO->hasNoUnsignedWrap())
13317330f729Sjoerg Out << " nuw";
13327330f729Sjoerg if (OBO->hasNoSignedWrap())
13337330f729Sjoerg Out << " nsw";
13347330f729Sjoerg } else if (const PossiblyExactOperator *Div =
13357330f729Sjoerg dyn_cast<PossiblyExactOperator>(U)) {
13367330f729Sjoerg if (Div->isExact())
13377330f729Sjoerg Out << " exact";
13387330f729Sjoerg } else if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
13397330f729Sjoerg if (GEP->isInBounds())
13407330f729Sjoerg Out << " inbounds";
13417330f729Sjoerg }
13427330f729Sjoerg }
13437330f729Sjoerg
WriteConstantInternal(raw_ostream & Out,const Constant * CV,TypePrinting & TypePrinter,SlotTracker * Machine,const Module * Context)13447330f729Sjoerg static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
13457330f729Sjoerg TypePrinting &TypePrinter,
13467330f729Sjoerg SlotTracker *Machine,
13477330f729Sjoerg const Module *Context) {
13487330f729Sjoerg if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
13497330f729Sjoerg if (CI->getType()->isIntegerTy(1)) {
13507330f729Sjoerg Out << (CI->getZExtValue() ? "true" : "false");
13517330f729Sjoerg return;
13527330f729Sjoerg }
13537330f729Sjoerg Out << CI->getValue();
13547330f729Sjoerg return;
13557330f729Sjoerg }
13567330f729Sjoerg
13577330f729Sjoerg if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
13587330f729Sjoerg const APFloat &APF = CFP->getValueAPF();
13597330f729Sjoerg if (&APF.getSemantics() == &APFloat::IEEEsingle() ||
13607330f729Sjoerg &APF.getSemantics() == &APFloat::IEEEdouble()) {
13617330f729Sjoerg // We would like to output the FP constant value in exponential notation,
13627330f729Sjoerg // but we cannot do this if doing so will lose precision. Check here to
13637330f729Sjoerg // make sure that we only output it in exponential format if we can parse
13647330f729Sjoerg // the value back and get the same value.
13657330f729Sjoerg //
13667330f729Sjoerg bool ignored;
13677330f729Sjoerg bool isDouble = &APF.getSemantics() == &APFloat::IEEEdouble();
13687330f729Sjoerg bool isInf = APF.isInfinity();
13697330f729Sjoerg bool isNaN = APF.isNaN();
13707330f729Sjoerg if (!isInf && !isNaN) {
1371*82d56013Sjoerg double Val = APF.convertToDouble();
13727330f729Sjoerg SmallString<128> StrVal;
13737330f729Sjoerg APF.toString(StrVal, 6, 0, false);
13747330f729Sjoerg // Check to make sure that the stringized number is not some string like
13757330f729Sjoerg // "Inf" or NaN, that atof will accept, but the lexer will not. Check
13767330f729Sjoerg // that the string matches the "[-+]?[0-9]" regex.
13777330f729Sjoerg //
1378*82d56013Sjoerg assert((isDigit(StrVal[0]) || ((StrVal[0] == '-' || StrVal[0] == '+') &&
1379*82d56013Sjoerg isDigit(StrVal[1]))) &&
13807330f729Sjoerg "[-+]?[0-9] regex does not match!");
13817330f729Sjoerg // Reparse stringized version!
13827330f729Sjoerg if (APFloat(APFloat::IEEEdouble(), StrVal).convertToDouble() == Val) {
13837330f729Sjoerg Out << StrVal;
13847330f729Sjoerg return;
13857330f729Sjoerg }
13867330f729Sjoerg }
13877330f729Sjoerg // Otherwise we could not reparse it to exactly the same value, so we must
13887330f729Sjoerg // output the string in hexadecimal format! Note that loading and storing
13897330f729Sjoerg // floating point types changes the bits of NaNs on some hosts, notably
13907330f729Sjoerg // x86, so we must not use these types.
13917330f729Sjoerg static_assert(sizeof(double) == sizeof(uint64_t),
13927330f729Sjoerg "assuming that double is 64 bits!");
13937330f729Sjoerg APFloat apf = APF;
13947330f729Sjoerg // Floats are represented in ASCII IR as double, convert.
1395*82d56013Sjoerg // FIXME: We should allow 32-bit hex float and remove this.
1396*82d56013Sjoerg if (!isDouble) {
1397*82d56013Sjoerg // A signaling NaN is quieted on conversion, so we need to recreate the
1398*82d56013Sjoerg // expected value after convert (quiet bit of the payload is clear).
1399*82d56013Sjoerg bool IsSNAN = apf.isSignaling();
14007330f729Sjoerg apf.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven,
14017330f729Sjoerg &ignored);
1402*82d56013Sjoerg if (IsSNAN) {
1403*82d56013Sjoerg APInt Payload = apf.bitcastToAPInt();
1404*82d56013Sjoerg apf = APFloat::getSNaN(APFloat::IEEEdouble(), apf.isNegative(),
1405*82d56013Sjoerg &Payload);
1406*82d56013Sjoerg }
1407*82d56013Sjoerg }
14087330f729Sjoerg Out << format_hex(apf.bitcastToAPInt().getZExtValue(), 0, /*Upper=*/true);
14097330f729Sjoerg return;
14107330f729Sjoerg }
14117330f729Sjoerg
1412*82d56013Sjoerg // Either half, bfloat or some form of long double.
14137330f729Sjoerg // These appear as a magic letter identifying the type, then a
14147330f729Sjoerg // fixed number of hex digits.
14157330f729Sjoerg Out << "0x";
14167330f729Sjoerg APInt API = APF.bitcastToAPInt();
14177330f729Sjoerg if (&APF.getSemantics() == &APFloat::x87DoubleExtended()) {
14187330f729Sjoerg Out << 'K';
14197330f729Sjoerg Out << format_hex_no_prefix(API.getHiBits(16).getZExtValue(), 4,
14207330f729Sjoerg /*Upper=*/true);
14217330f729Sjoerg Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16,
14227330f729Sjoerg /*Upper=*/true);
14237330f729Sjoerg return;
14247330f729Sjoerg } else if (&APF.getSemantics() == &APFloat::IEEEquad()) {
14257330f729Sjoerg Out << 'L';
14267330f729Sjoerg Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16,
14277330f729Sjoerg /*Upper=*/true);
14287330f729Sjoerg Out << format_hex_no_prefix(API.getHiBits(64).getZExtValue(), 16,
14297330f729Sjoerg /*Upper=*/true);
14307330f729Sjoerg } else if (&APF.getSemantics() == &APFloat::PPCDoubleDouble()) {
14317330f729Sjoerg Out << 'M';
14327330f729Sjoerg Out << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16,
14337330f729Sjoerg /*Upper=*/true);
14347330f729Sjoerg Out << format_hex_no_prefix(API.getHiBits(64).getZExtValue(), 16,
14357330f729Sjoerg /*Upper=*/true);
14367330f729Sjoerg } else if (&APF.getSemantics() == &APFloat::IEEEhalf()) {
14377330f729Sjoerg Out << 'H';
14387330f729Sjoerg Out << format_hex_no_prefix(API.getZExtValue(), 4,
14397330f729Sjoerg /*Upper=*/true);
1440*82d56013Sjoerg } else if (&APF.getSemantics() == &APFloat::BFloat()) {
1441*82d56013Sjoerg Out << 'R';
1442*82d56013Sjoerg Out << format_hex_no_prefix(API.getZExtValue(), 4,
1443*82d56013Sjoerg /*Upper=*/true);
14447330f729Sjoerg } else
14457330f729Sjoerg llvm_unreachable("Unsupported floating point type");
14467330f729Sjoerg return;
14477330f729Sjoerg }
14487330f729Sjoerg
14497330f729Sjoerg if (isa<ConstantAggregateZero>(CV)) {
14507330f729Sjoerg Out << "zeroinitializer";
14517330f729Sjoerg return;
14527330f729Sjoerg }
14537330f729Sjoerg
14547330f729Sjoerg if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV)) {
14557330f729Sjoerg Out << "blockaddress(";
14567330f729Sjoerg WriteAsOperandInternal(Out, BA->getFunction(), &TypePrinter, Machine,
14577330f729Sjoerg Context);
14587330f729Sjoerg Out << ", ";
14597330f729Sjoerg WriteAsOperandInternal(Out, BA->getBasicBlock(), &TypePrinter, Machine,
14607330f729Sjoerg Context);
14617330f729Sjoerg Out << ")";
14627330f729Sjoerg return;
14637330f729Sjoerg }
14647330f729Sjoerg
1465*82d56013Sjoerg if (const auto *Equiv = dyn_cast<DSOLocalEquivalent>(CV)) {
1466*82d56013Sjoerg Out << "dso_local_equivalent ";
1467*82d56013Sjoerg WriteAsOperandInternal(Out, Equiv->getGlobalValue(), &TypePrinter, Machine,
1468*82d56013Sjoerg Context);
1469*82d56013Sjoerg return;
1470*82d56013Sjoerg }
1471*82d56013Sjoerg
14727330f729Sjoerg if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV)) {
14737330f729Sjoerg Type *ETy = CA->getType()->getElementType();
14747330f729Sjoerg Out << '[';
14757330f729Sjoerg TypePrinter.print(ETy, Out);
14767330f729Sjoerg Out << ' ';
14777330f729Sjoerg WriteAsOperandInternal(Out, CA->getOperand(0),
14787330f729Sjoerg &TypePrinter, Machine,
14797330f729Sjoerg Context);
14807330f729Sjoerg for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) {
14817330f729Sjoerg Out << ", ";
14827330f729Sjoerg TypePrinter.print(ETy, Out);
14837330f729Sjoerg Out << ' ';
14847330f729Sjoerg WriteAsOperandInternal(Out, CA->getOperand(i), &TypePrinter, Machine,
14857330f729Sjoerg Context);
14867330f729Sjoerg }
14877330f729Sjoerg Out << ']';
14887330f729Sjoerg return;
14897330f729Sjoerg }
14907330f729Sjoerg
14917330f729Sjoerg if (const ConstantDataArray *CA = dyn_cast<ConstantDataArray>(CV)) {
14927330f729Sjoerg // As a special case, print the array as a string if it is an array of
14937330f729Sjoerg // i8 with ConstantInt values.
14947330f729Sjoerg if (CA->isString()) {
14957330f729Sjoerg Out << "c\"";
14967330f729Sjoerg printEscapedString(CA->getAsString(), Out);
14977330f729Sjoerg Out << '"';
14987330f729Sjoerg return;
14997330f729Sjoerg }
15007330f729Sjoerg
15017330f729Sjoerg Type *ETy = CA->getType()->getElementType();
15027330f729Sjoerg Out << '[';
15037330f729Sjoerg TypePrinter.print(ETy, Out);
15047330f729Sjoerg Out << ' ';
15057330f729Sjoerg WriteAsOperandInternal(Out, CA->getElementAsConstant(0),
15067330f729Sjoerg &TypePrinter, Machine,
15077330f729Sjoerg Context);
15087330f729Sjoerg for (unsigned i = 1, e = CA->getNumElements(); i != e; ++i) {
15097330f729Sjoerg Out << ", ";
15107330f729Sjoerg TypePrinter.print(ETy, Out);
15117330f729Sjoerg Out << ' ';
15127330f729Sjoerg WriteAsOperandInternal(Out, CA->getElementAsConstant(i), &TypePrinter,
15137330f729Sjoerg Machine, Context);
15147330f729Sjoerg }
15157330f729Sjoerg Out << ']';
15167330f729Sjoerg return;
15177330f729Sjoerg }
15187330f729Sjoerg
15197330f729Sjoerg if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(CV)) {
15207330f729Sjoerg if (CS->getType()->isPacked())
15217330f729Sjoerg Out << '<';
15227330f729Sjoerg Out << '{';
15237330f729Sjoerg unsigned N = CS->getNumOperands();
15247330f729Sjoerg if (N) {
15257330f729Sjoerg Out << ' ';
15267330f729Sjoerg TypePrinter.print(CS->getOperand(0)->getType(), Out);
15277330f729Sjoerg Out << ' ';
15287330f729Sjoerg
15297330f729Sjoerg WriteAsOperandInternal(Out, CS->getOperand(0), &TypePrinter, Machine,
15307330f729Sjoerg Context);
15317330f729Sjoerg
15327330f729Sjoerg for (unsigned i = 1; i < N; i++) {
15337330f729Sjoerg Out << ", ";
15347330f729Sjoerg TypePrinter.print(CS->getOperand(i)->getType(), Out);
15357330f729Sjoerg Out << ' ';
15367330f729Sjoerg
15377330f729Sjoerg WriteAsOperandInternal(Out, CS->getOperand(i), &TypePrinter, Machine,
15387330f729Sjoerg Context);
15397330f729Sjoerg }
15407330f729Sjoerg Out << ' ';
15417330f729Sjoerg }
15427330f729Sjoerg
15437330f729Sjoerg Out << '}';
15447330f729Sjoerg if (CS->getType()->isPacked())
15457330f729Sjoerg Out << '>';
15467330f729Sjoerg return;
15477330f729Sjoerg }
15487330f729Sjoerg
15497330f729Sjoerg if (isa<ConstantVector>(CV) || isa<ConstantDataVector>(CV)) {
1550*82d56013Sjoerg auto *CVVTy = cast<FixedVectorType>(CV->getType());
1551*82d56013Sjoerg Type *ETy = CVVTy->getElementType();
15527330f729Sjoerg Out << '<';
15537330f729Sjoerg TypePrinter.print(ETy, Out);
15547330f729Sjoerg Out << ' ';
15557330f729Sjoerg WriteAsOperandInternal(Out, CV->getAggregateElement(0U), &TypePrinter,
15567330f729Sjoerg Machine, Context);
1557*82d56013Sjoerg for (unsigned i = 1, e = CVVTy->getNumElements(); i != e; ++i) {
15587330f729Sjoerg Out << ", ";
15597330f729Sjoerg TypePrinter.print(ETy, Out);
15607330f729Sjoerg Out << ' ';
15617330f729Sjoerg WriteAsOperandInternal(Out, CV->getAggregateElement(i), &TypePrinter,
15627330f729Sjoerg Machine, Context);
15637330f729Sjoerg }
15647330f729Sjoerg Out << '>';
15657330f729Sjoerg return;
15667330f729Sjoerg }
15677330f729Sjoerg
15687330f729Sjoerg if (isa<ConstantPointerNull>(CV)) {
15697330f729Sjoerg Out << "null";
15707330f729Sjoerg return;
15717330f729Sjoerg }
15727330f729Sjoerg
15737330f729Sjoerg if (isa<ConstantTokenNone>(CV)) {
15747330f729Sjoerg Out << "none";
15757330f729Sjoerg return;
15767330f729Sjoerg }
15777330f729Sjoerg
1578*82d56013Sjoerg if (isa<PoisonValue>(CV)) {
1579*82d56013Sjoerg Out << "poison";
1580*82d56013Sjoerg return;
1581*82d56013Sjoerg }
1582*82d56013Sjoerg
15837330f729Sjoerg if (isa<UndefValue>(CV)) {
15847330f729Sjoerg Out << "undef";
15857330f729Sjoerg return;
15867330f729Sjoerg }
15877330f729Sjoerg
15887330f729Sjoerg if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
15897330f729Sjoerg Out << CE->getOpcodeName();
15907330f729Sjoerg WriteOptimizationInfo(Out, CE);
15917330f729Sjoerg if (CE->isCompare())
15927330f729Sjoerg Out << ' ' << CmpInst::getPredicateName(
15937330f729Sjoerg static_cast<CmpInst::Predicate>(CE->getPredicate()));
15947330f729Sjoerg Out << " (";
15957330f729Sjoerg
15967330f729Sjoerg Optional<unsigned> InRangeOp;
15977330f729Sjoerg if (const GEPOperator *GEP = dyn_cast<GEPOperator>(CE)) {
15987330f729Sjoerg TypePrinter.print(GEP->getSourceElementType(), Out);
15997330f729Sjoerg Out << ", ";
16007330f729Sjoerg InRangeOp = GEP->getInRangeIndex();
16017330f729Sjoerg if (InRangeOp)
16027330f729Sjoerg ++*InRangeOp;
16037330f729Sjoerg }
16047330f729Sjoerg
16057330f729Sjoerg for (User::const_op_iterator OI=CE->op_begin(); OI != CE->op_end(); ++OI) {
16067330f729Sjoerg if (InRangeOp && unsigned(OI - CE->op_begin()) == *InRangeOp)
16077330f729Sjoerg Out << "inrange ";
16087330f729Sjoerg TypePrinter.print((*OI)->getType(), Out);
16097330f729Sjoerg Out << ' ';
16107330f729Sjoerg WriteAsOperandInternal(Out, *OI, &TypePrinter, Machine, Context);
16117330f729Sjoerg if (OI+1 != CE->op_end())
16127330f729Sjoerg Out << ", ";
16137330f729Sjoerg }
16147330f729Sjoerg
16157330f729Sjoerg if (CE->hasIndices()) {
16167330f729Sjoerg ArrayRef<unsigned> Indices = CE->getIndices();
16177330f729Sjoerg for (unsigned i = 0, e = Indices.size(); i != e; ++i)
16187330f729Sjoerg Out << ", " << Indices[i];
16197330f729Sjoerg }
16207330f729Sjoerg
16217330f729Sjoerg if (CE->isCast()) {
16227330f729Sjoerg Out << " to ";
16237330f729Sjoerg TypePrinter.print(CE->getType(), Out);
16247330f729Sjoerg }
16257330f729Sjoerg
1626*82d56013Sjoerg if (CE->getOpcode() == Instruction::ShuffleVector)
1627*82d56013Sjoerg PrintShuffleMask(Out, CE->getType(), CE->getShuffleMask());
1628*82d56013Sjoerg
16297330f729Sjoerg Out << ')';
16307330f729Sjoerg return;
16317330f729Sjoerg }
16327330f729Sjoerg
16337330f729Sjoerg Out << "<placeholder or erroneous Constant>";
16347330f729Sjoerg }
16357330f729Sjoerg
writeMDTuple(raw_ostream & Out,const MDTuple * Node,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)16367330f729Sjoerg static void writeMDTuple(raw_ostream &Out, const MDTuple *Node,
16377330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
16387330f729Sjoerg const Module *Context) {
16397330f729Sjoerg Out << "!{";
16407330f729Sjoerg for (unsigned mi = 0, me = Node->getNumOperands(); mi != me; ++mi) {
16417330f729Sjoerg const Metadata *MD = Node->getOperand(mi);
16427330f729Sjoerg if (!MD)
16437330f729Sjoerg Out << "null";
16447330f729Sjoerg else if (auto *MDV = dyn_cast<ValueAsMetadata>(MD)) {
16457330f729Sjoerg Value *V = MDV->getValue();
16467330f729Sjoerg TypePrinter->print(V->getType(), Out);
16477330f729Sjoerg Out << ' ';
16487330f729Sjoerg WriteAsOperandInternal(Out, V, TypePrinter, Machine, Context);
16497330f729Sjoerg } else {
16507330f729Sjoerg WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context);
16517330f729Sjoerg }
16527330f729Sjoerg if (mi + 1 != me)
16537330f729Sjoerg Out << ", ";
16547330f729Sjoerg }
16557330f729Sjoerg
16567330f729Sjoerg Out << "}";
16577330f729Sjoerg }
16587330f729Sjoerg
16597330f729Sjoerg namespace {
16607330f729Sjoerg
16617330f729Sjoerg struct FieldSeparator {
16627330f729Sjoerg bool Skip = true;
16637330f729Sjoerg const char *Sep;
16647330f729Sjoerg
FieldSeparator__anonf93afd230711::FieldSeparator16657330f729Sjoerg FieldSeparator(const char *Sep = ", ") : Sep(Sep) {}
16667330f729Sjoerg };
16677330f729Sjoerg
operator <<(raw_ostream & OS,FieldSeparator & FS)16687330f729Sjoerg raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) {
16697330f729Sjoerg if (FS.Skip) {
16707330f729Sjoerg FS.Skip = false;
16717330f729Sjoerg return OS;
16727330f729Sjoerg }
16737330f729Sjoerg return OS << FS.Sep;
16747330f729Sjoerg }
16757330f729Sjoerg
16767330f729Sjoerg struct MDFieldPrinter {
16777330f729Sjoerg raw_ostream &Out;
16787330f729Sjoerg FieldSeparator FS;
16797330f729Sjoerg TypePrinting *TypePrinter = nullptr;
16807330f729Sjoerg SlotTracker *Machine = nullptr;
16817330f729Sjoerg const Module *Context = nullptr;
16827330f729Sjoerg
MDFieldPrinter__anonf93afd230711::MDFieldPrinter16837330f729Sjoerg explicit MDFieldPrinter(raw_ostream &Out) : Out(Out) {}
MDFieldPrinter__anonf93afd230711::MDFieldPrinter16847330f729Sjoerg MDFieldPrinter(raw_ostream &Out, TypePrinting *TypePrinter,
16857330f729Sjoerg SlotTracker *Machine, const Module *Context)
16867330f729Sjoerg : Out(Out), TypePrinter(TypePrinter), Machine(Machine), Context(Context) {
16877330f729Sjoerg }
16887330f729Sjoerg
16897330f729Sjoerg void printTag(const DINode *N);
16907330f729Sjoerg void printMacinfoType(const DIMacroNode *N);
16917330f729Sjoerg void printChecksum(const DIFile::ChecksumInfo<StringRef> &N);
16927330f729Sjoerg void printString(StringRef Name, StringRef Value,
16937330f729Sjoerg bool ShouldSkipEmpty = true);
16947330f729Sjoerg void printMetadata(StringRef Name, const Metadata *MD,
16957330f729Sjoerg bool ShouldSkipNull = true);
16967330f729Sjoerg template <class IntTy>
16977330f729Sjoerg void printInt(StringRef Name, IntTy Int, bool ShouldSkipZero = true);
1698*82d56013Sjoerg void printAPInt(StringRef Name, const APInt &Int, bool IsUnsigned,
1699*82d56013Sjoerg bool ShouldSkipZero);
17007330f729Sjoerg void printBool(StringRef Name, bool Value, Optional<bool> Default = None);
17017330f729Sjoerg void printDIFlags(StringRef Name, DINode::DIFlags Flags);
17027330f729Sjoerg void printDISPFlags(StringRef Name, DISubprogram::DISPFlags Flags);
17037330f729Sjoerg template <class IntTy, class Stringifier>
17047330f729Sjoerg void printDwarfEnum(StringRef Name, IntTy Value, Stringifier toString,
17057330f729Sjoerg bool ShouldSkipZero = true);
17067330f729Sjoerg void printEmissionKind(StringRef Name, DICompileUnit::DebugEmissionKind EK);
17077330f729Sjoerg void printNameTableKind(StringRef Name,
17087330f729Sjoerg DICompileUnit::DebugNameTableKind NTK);
17097330f729Sjoerg };
17107330f729Sjoerg
17117330f729Sjoerg } // end anonymous namespace
17127330f729Sjoerg
printTag(const DINode * N)17137330f729Sjoerg void MDFieldPrinter::printTag(const DINode *N) {
17147330f729Sjoerg Out << FS << "tag: ";
17157330f729Sjoerg auto Tag = dwarf::TagString(N->getTag());
17167330f729Sjoerg if (!Tag.empty())
17177330f729Sjoerg Out << Tag;
17187330f729Sjoerg else
17197330f729Sjoerg Out << N->getTag();
17207330f729Sjoerg }
17217330f729Sjoerg
printMacinfoType(const DIMacroNode * N)17227330f729Sjoerg void MDFieldPrinter::printMacinfoType(const DIMacroNode *N) {
17237330f729Sjoerg Out << FS << "type: ";
17247330f729Sjoerg auto Type = dwarf::MacinfoString(N->getMacinfoType());
17257330f729Sjoerg if (!Type.empty())
17267330f729Sjoerg Out << Type;
17277330f729Sjoerg else
17287330f729Sjoerg Out << N->getMacinfoType();
17297330f729Sjoerg }
17307330f729Sjoerg
printChecksum(const DIFile::ChecksumInfo<StringRef> & Checksum)17317330f729Sjoerg void MDFieldPrinter::printChecksum(
17327330f729Sjoerg const DIFile::ChecksumInfo<StringRef> &Checksum) {
17337330f729Sjoerg Out << FS << "checksumkind: " << Checksum.getKindAsString();
17347330f729Sjoerg printString("checksum", Checksum.Value, /* ShouldSkipEmpty */ false);
17357330f729Sjoerg }
17367330f729Sjoerg
printString(StringRef Name,StringRef Value,bool ShouldSkipEmpty)17377330f729Sjoerg void MDFieldPrinter::printString(StringRef Name, StringRef Value,
17387330f729Sjoerg bool ShouldSkipEmpty) {
17397330f729Sjoerg if (ShouldSkipEmpty && Value.empty())
17407330f729Sjoerg return;
17417330f729Sjoerg
17427330f729Sjoerg Out << FS << Name << ": \"";
17437330f729Sjoerg printEscapedString(Value, Out);
17447330f729Sjoerg Out << "\"";
17457330f729Sjoerg }
17467330f729Sjoerg
writeMetadataAsOperand(raw_ostream & Out,const Metadata * MD,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)17477330f729Sjoerg static void writeMetadataAsOperand(raw_ostream &Out, const Metadata *MD,
17487330f729Sjoerg TypePrinting *TypePrinter,
17497330f729Sjoerg SlotTracker *Machine,
17507330f729Sjoerg const Module *Context) {
17517330f729Sjoerg if (!MD) {
17527330f729Sjoerg Out << "null";
17537330f729Sjoerg return;
17547330f729Sjoerg }
17557330f729Sjoerg WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context);
17567330f729Sjoerg }
17577330f729Sjoerg
printMetadata(StringRef Name,const Metadata * MD,bool ShouldSkipNull)17587330f729Sjoerg void MDFieldPrinter::printMetadata(StringRef Name, const Metadata *MD,
17597330f729Sjoerg bool ShouldSkipNull) {
17607330f729Sjoerg if (ShouldSkipNull && !MD)
17617330f729Sjoerg return;
17627330f729Sjoerg
17637330f729Sjoerg Out << FS << Name << ": ";
17647330f729Sjoerg writeMetadataAsOperand(Out, MD, TypePrinter, Machine, Context);
17657330f729Sjoerg }
17667330f729Sjoerg
17677330f729Sjoerg template <class IntTy>
printInt(StringRef Name,IntTy Int,bool ShouldSkipZero)17687330f729Sjoerg void MDFieldPrinter::printInt(StringRef Name, IntTy Int, bool ShouldSkipZero) {
17697330f729Sjoerg if (ShouldSkipZero && !Int)
17707330f729Sjoerg return;
17717330f729Sjoerg
17727330f729Sjoerg Out << FS << Name << ": " << Int;
17737330f729Sjoerg }
17747330f729Sjoerg
printAPInt(StringRef Name,const APInt & Int,bool IsUnsigned,bool ShouldSkipZero)1775*82d56013Sjoerg void MDFieldPrinter::printAPInt(StringRef Name, const APInt &Int,
1776*82d56013Sjoerg bool IsUnsigned, bool ShouldSkipZero) {
1777*82d56013Sjoerg if (ShouldSkipZero && Int.isNullValue())
1778*82d56013Sjoerg return;
1779*82d56013Sjoerg
1780*82d56013Sjoerg Out << FS << Name << ": ";
1781*82d56013Sjoerg Int.print(Out, !IsUnsigned);
1782*82d56013Sjoerg }
1783*82d56013Sjoerg
printBool(StringRef Name,bool Value,Optional<bool> Default)17847330f729Sjoerg void MDFieldPrinter::printBool(StringRef Name, bool Value,
17857330f729Sjoerg Optional<bool> Default) {
17867330f729Sjoerg if (Default && Value == *Default)
17877330f729Sjoerg return;
17887330f729Sjoerg Out << FS << Name << ": " << (Value ? "true" : "false");
17897330f729Sjoerg }
17907330f729Sjoerg
printDIFlags(StringRef Name,DINode::DIFlags Flags)17917330f729Sjoerg void MDFieldPrinter::printDIFlags(StringRef Name, DINode::DIFlags Flags) {
17927330f729Sjoerg if (!Flags)
17937330f729Sjoerg return;
17947330f729Sjoerg
17957330f729Sjoerg Out << FS << Name << ": ";
17967330f729Sjoerg
17977330f729Sjoerg SmallVector<DINode::DIFlags, 8> SplitFlags;
17987330f729Sjoerg auto Extra = DINode::splitFlags(Flags, SplitFlags);
17997330f729Sjoerg
18007330f729Sjoerg FieldSeparator FlagsFS(" | ");
18017330f729Sjoerg for (auto F : SplitFlags) {
18027330f729Sjoerg auto StringF = DINode::getFlagString(F);
18037330f729Sjoerg assert(!StringF.empty() && "Expected valid flag");
18047330f729Sjoerg Out << FlagsFS << StringF;
18057330f729Sjoerg }
18067330f729Sjoerg if (Extra || SplitFlags.empty())
18077330f729Sjoerg Out << FlagsFS << Extra;
18087330f729Sjoerg }
18097330f729Sjoerg
printDISPFlags(StringRef Name,DISubprogram::DISPFlags Flags)18107330f729Sjoerg void MDFieldPrinter::printDISPFlags(StringRef Name,
18117330f729Sjoerg DISubprogram::DISPFlags Flags) {
18127330f729Sjoerg // Always print this field, because no flags in the IR at all will be
18137330f729Sjoerg // interpreted as old-style isDefinition: true.
18147330f729Sjoerg Out << FS << Name << ": ";
18157330f729Sjoerg
18167330f729Sjoerg if (!Flags) {
18177330f729Sjoerg Out << 0;
18187330f729Sjoerg return;
18197330f729Sjoerg }
18207330f729Sjoerg
18217330f729Sjoerg SmallVector<DISubprogram::DISPFlags, 8> SplitFlags;
18227330f729Sjoerg auto Extra = DISubprogram::splitFlags(Flags, SplitFlags);
18237330f729Sjoerg
18247330f729Sjoerg FieldSeparator FlagsFS(" | ");
18257330f729Sjoerg for (auto F : SplitFlags) {
18267330f729Sjoerg auto StringF = DISubprogram::getFlagString(F);
18277330f729Sjoerg assert(!StringF.empty() && "Expected valid flag");
18287330f729Sjoerg Out << FlagsFS << StringF;
18297330f729Sjoerg }
18307330f729Sjoerg if (Extra || SplitFlags.empty())
18317330f729Sjoerg Out << FlagsFS << Extra;
18327330f729Sjoerg }
18337330f729Sjoerg
printEmissionKind(StringRef Name,DICompileUnit::DebugEmissionKind EK)18347330f729Sjoerg void MDFieldPrinter::printEmissionKind(StringRef Name,
18357330f729Sjoerg DICompileUnit::DebugEmissionKind EK) {
18367330f729Sjoerg Out << FS << Name << ": " << DICompileUnit::emissionKindString(EK);
18377330f729Sjoerg }
18387330f729Sjoerg
printNameTableKind(StringRef Name,DICompileUnit::DebugNameTableKind NTK)18397330f729Sjoerg void MDFieldPrinter::printNameTableKind(StringRef Name,
18407330f729Sjoerg DICompileUnit::DebugNameTableKind NTK) {
18417330f729Sjoerg if (NTK == DICompileUnit::DebugNameTableKind::Default)
18427330f729Sjoerg return;
18437330f729Sjoerg Out << FS << Name << ": " << DICompileUnit::nameTableKindString(NTK);
18447330f729Sjoerg }
18457330f729Sjoerg
18467330f729Sjoerg template <class IntTy, class Stringifier>
printDwarfEnum(StringRef Name,IntTy Value,Stringifier toString,bool ShouldSkipZero)18477330f729Sjoerg void MDFieldPrinter::printDwarfEnum(StringRef Name, IntTy Value,
18487330f729Sjoerg Stringifier toString, bool ShouldSkipZero) {
18497330f729Sjoerg if (!Value)
18507330f729Sjoerg return;
18517330f729Sjoerg
18527330f729Sjoerg Out << FS << Name << ": ";
18537330f729Sjoerg auto S = toString(Value);
18547330f729Sjoerg if (!S.empty())
18557330f729Sjoerg Out << S;
18567330f729Sjoerg else
18577330f729Sjoerg Out << Value;
18587330f729Sjoerg }
18597330f729Sjoerg
writeGenericDINode(raw_ostream & Out,const GenericDINode * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)18607330f729Sjoerg static void writeGenericDINode(raw_ostream &Out, const GenericDINode *N,
18617330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
18627330f729Sjoerg const Module *Context) {
18637330f729Sjoerg Out << "!GenericDINode(";
18647330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
18657330f729Sjoerg Printer.printTag(N);
18667330f729Sjoerg Printer.printString("header", N->getHeader());
18677330f729Sjoerg if (N->getNumDwarfOperands()) {
18687330f729Sjoerg Out << Printer.FS << "operands: {";
18697330f729Sjoerg FieldSeparator IFS;
18707330f729Sjoerg for (auto &I : N->dwarf_operands()) {
18717330f729Sjoerg Out << IFS;
18727330f729Sjoerg writeMetadataAsOperand(Out, I, TypePrinter, Machine, Context);
18737330f729Sjoerg }
18747330f729Sjoerg Out << "}";
18757330f729Sjoerg }
18767330f729Sjoerg Out << ")";
18777330f729Sjoerg }
18787330f729Sjoerg
writeDILocation(raw_ostream & Out,const DILocation * DL,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)18797330f729Sjoerg static void writeDILocation(raw_ostream &Out, const DILocation *DL,
18807330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
18817330f729Sjoerg const Module *Context) {
18827330f729Sjoerg Out << "!DILocation(";
18837330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
18847330f729Sjoerg // Always output the line, since 0 is a relevant and important value for it.
18857330f729Sjoerg Printer.printInt("line", DL->getLine(), /* ShouldSkipZero */ false);
18867330f729Sjoerg Printer.printInt("column", DL->getColumn());
18877330f729Sjoerg Printer.printMetadata("scope", DL->getRawScope(), /* ShouldSkipNull */ false);
18887330f729Sjoerg Printer.printMetadata("inlinedAt", DL->getRawInlinedAt());
18897330f729Sjoerg Printer.printBool("isImplicitCode", DL->isImplicitCode(),
18907330f729Sjoerg /* Default */ false);
18917330f729Sjoerg Out << ")";
18927330f729Sjoerg }
18937330f729Sjoerg
writeDISubrange(raw_ostream & Out,const DISubrange * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)18947330f729Sjoerg static void writeDISubrange(raw_ostream &Out, const DISubrange *N,
18957330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
18967330f729Sjoerg const Module *Context) {
18977330f729Sjoerg Out << "!DISubrange(";
18987330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
1899*82d56013Sjoerg
1900*82d56013Sjoerg auto *Count = N->getRawCountNode();
1901*82d56013Sjoerg if (auto *CE = dyn_cast_or_null<ConstantAsMetadata>(Count)) {
1902*82d56013Sjoerg auto *CV = cast<ConstantInt>(CE->getValue());
1903*82d56013Sjoerg Printer.printInt("count", CV->getSExtValue(),
1904*82d56013Sjoerg /* ShouldSkipZero */ false);
1905*82d56013Sjoerg } else
1906*82d56013Sjoerg Printer.printMetadata("count", Count, /*ShouldSkipNull */ true);
1907*82d56013Sjoerg
1908*82d56013Sjoerg // A lowerBound of constant 0 should not be skipped, since it is different
1909*82d56013Sjoerg // from an unspecified lower bound (= nullptr).
1910*82d56013Sjoerg auto *LBound = N->getRawLowerBound();
1911*82d56013Sjoerg if (auto *LE = dyn_cast_or_null<ConstantAsMetadata>(LBound)) {
1912*82d56013Sjoerg auto *LV = cast<ConstantInt>(LE->getValue());
1913*82d56013Sjoerg Printer.printInt("lowerBound", LV->getSExtValue(),
1914*82d56013Sjoerg /* ShouldSkipZero */ false);
1915*82d56013Sjoerg } else
1916*82d56013Sjoerg Printer.printMetadata("lowerBound", LBound, /*ShouldSkipNull */ true);
1917*82d56013Sjoerg
1918*82d56013Sjoerg auto *UBound = N->getRawUpperBound();
1919*82d56013Sjoerg if (auto *UE = dyn_cast_or_null<ConstantAsMetadata>(UBound)) {
1920*82d56013Sjoerg auto *UV = cast<ConstantInt>(UE->getValue());
1921*82d56013Sjoerg Printer.printInt("upperBound", UV->getSExtValue(),
1922*82d56013Sjoerg /* ShouldSkipZero */ false);
1923*82d56013Sjoerg } else
1924*82d56013Sjoerg Printer.printMetadata("upperBound", UBound, /*ShouldSkipNull */ true);
1925*82d56013Sjoerg
1926*82d56013Sjoerg auto *Stride = N->getRawStride();
1927*82d56013Sjoerg if (auto *SE = dyn_cast_or_null<ConstantAsMetadata>(Stride)) {
1928*82d56013Sjoerg auto *SV = cast<ConstantInt>(SE->getValue());
1929*82d56013Sjoerg Printer.printInt("stride", SV->getSExtValue(), /* ShouldSkipZero */ false);
1930*82d56013Sjoerg } else
1931*82d56013Sjoerg Printer.printMetadata("stride", Stride, /*ShouldSkipNull */ true);
1932*82d56013Sjoerg
1933*82d56013Sjoerg Out << ")";
1934*82d56013Sjoerg }
1935*82d56013Sjoerg
writeDIGenericSubrange(raw_ostream & Out,const DIGenericSubrange * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)1936*82d56013Sjoerg static void writeDIGenericSubrange(raw_ostream &Out, const DIGenericSubrange *N,
1937*82d56013Sjoerg TypePrinting *TypePrinter,
1938*82d56013Sjoerg SlotTracker *Machine,
1939*82d56013Sjoerg const Module *Context) {
1940*82d56013Sjoerg Out << "!DIGenericSubrange(";
1941*82d56013Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
1942*82d56013Sjoerg
1943*82d56013Sjoerg auto IsConstant = [&](Metadata *Bound) -> bool {
1944*82d56013Sjoerg if (auto *BE = dyn_cast_or_null<DIExpression>(Bound)) {
1945*82d56013Sjoerg return BE->isConstant()
1946*82d56013Sjoerg ? DIExpression::SignedOrUnsignedConstant::SignedConstant ==
1947*82d56013Sjoerg *BE->isConstant()
1948*82d56013Sjoerg : false;
1949*82d56013Sjoerg }
1950*82d56013Sjoerg return false;
1951*82d56013Sjoerg };
1952*82d56013Sjoerg
1953*82d56013Sjoerg auto GetConstant = [&](Metadata *Bound) -> int64_t {
1954*82d56013Sjoerg assert(IsConstant(Bound) && "Expected constant");
1955*82d56013Sjoerg auto *BE = dyn_cast_or_null<DIExpression>(Bound);
1956*82d56013Sjoerg return static_cast<int64_t>(BE->getElement(1));
1957*82d56013Sjoerg };
1958*82d56013Sjoerg
1959*82d56013Sjoerg auto *Count = N->getRawCountNode();
1960*82d56013Sjoerg if (IsConstant(Count))
1961*82d56013Sjoerg Printer.printInt("count", GetConstant(Count),
1962*82d56013Sjoerg /* ShouldSkipZero */ false);
19637330f729Sjoerg else
1964*82d56013Sjoerg Printer.printMetadata("count", Count, /*ShouldSkipNull */ true);
1965*82d56013Sjoerg
1966*82d56013Sjoerg auto *LBound = N->getRawLowerBound();
1967*82d56013Sjoerg if (IsConstant(LBound))
1968*82d56013Sjoerg Printer.printInt("lowerBound", GetConstant(LBound),
1969*82d56013Sjoerg /* ShouldSkipZero */ false);
1970*82d56013Sjoerg else
1971*82d56013Sjoerg Printer.printMetadata("lowerBound", LBound, /*ShouldSkipNull */ true);
1972*82d56013Sjoerg
1973*82d56013Sjoerg auto *UBound = N->getRawUpperBound();
1974*82d56013Sjoerg if (IsConstant(UBound))
1975*82d56013Sjoerg Printer.printInt("upperBound", GetConstant(UBound),
1976*82d56013Sjoerg /* ShouldSkipZero */ false);
1977*82d56013Sjoerg else
1978*82d56013Sjoerg Printer.printMetadata("upperBound", UBound, /*ShouldSkipNull */ true);
1979*82d56013Sjoerg
1980*82d56013Sjoerg auto *Stride = N->getRawStride();
1981*82d56013Sjoerg if (IsConstant(Stride))
1982*82d56013Sjoerg Printer.printInt("stride", GetConstant(Stride),
1983*82d56013Sjoerg /* ShouldSkipZero */ false);
1984*82d56013Sjoerg else
1985*82d56013Sjoerg Printer.printMetadata("stride", Stride, /*ShouldSkipNull */ true);
1986*82d56013Sjoerg
19877330f729Sjoerg Out << ")";
19887330f729Sjoerg }
19897330f729Sjoerg
writeDIEnumerator(raw_ostream & Out,const DIEnumerator * N,TypePrinting *,SlotTracker *,const Module *)19907330f729Sjoerg static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N,
19917330f729Sjoerg TypePrinting *, SlotTracker *, const Module *) {
19927330f729Sjoerg Out << "!DIEnumerator(";
19937330f729Sjoerg MDFieldPrinter Printer(Out);
19947330f729Sjoerg Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false);
1995*82d56013Sjoerg Printer.printAPInt("value", N->getValue(), N->isUnsigned(),
1996*82d56013Sjoerg /*ShouldSkipZero=*/false);
1997*82d56013Sjoerg if (N->isUnsigned())
19987330f729Sjoerg Printer.printBool("isUnsigned", true);
19997330f729Sjoerg Out << ")";
20007330f729Sjoerg }
20017330f729Sjoerg
writeDIBasicType(raw_ostream & Out,const DIBasicType * N,TypePrinting *,SlotTracker *,const Module *)20027330f729Sjoerg static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
20037330f729Sjoerg TypePrinting *, SlotTracker *, const Module *) {
20047330f729Sjoerg Out << "!DIBasicType(";
20057330f729Sjoerg MDFieldPrinter Printer(Out);
20067330f729Sjoerg if (N->getTag() != dwarf::DW_TAG_base_type)
20077330f729Sjoerg Printer.printTag(N);
20087330f729Sjoerg Printer.printString("name", N->getName());
20097330f729Sjoerg Printer.printInt("size", N->getSizeInBits());
20107330f729Sjoerg Printer.printInt("align", N->getAlignInBits());
20117330f729Sjoerg Printer.printDwarfEnum("encoding", N->getEncoding(),
20127330f729Sjoerg dwarf::AttributeEncodingString);
20137330f729Sjoerg Printer.printDIFlags("flags", N->getFlags());
20147330f729Sjoerg Out << ")";
20157330f729Sjoerg }
20167330f729Sjoerg
writeDIStringType(raw_ostream & Out,const DIStringType * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)2017*82d56013Sjoerg static void writeDIStringType(raw_ostream &Out, const DIStringType *N,
2018*82d56013Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
2019*82d56013Sjoerg const Module *Context) {
2020*82d56013Sjoerg Out << "!DIStringType(";
2021*82d56013Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
2022*82d56013Sjoerg if (N->getTag() != dwarf::DW_TAG_string_type)
2023*82d56013Sjoerg Printer.printTag(N);
2024*82d56013Sjoerg Printer.printString("name", N->getName());
2025*82d56013Sjoerg Printer.printMetadata("stringLength", N->getRawStringLength());
2026*82d56013Sjoerg Printer.printMetadata("stringLengthExpression", N->getRawStringLengthExp());
2027*82d56013Sjoerg Printer.printInt("size", N->getSizeInBits());
2028*82d56013Sjoerg Printer.printInt("align", N->getAlignInBits());
2029*82d56013Sjoerg Printer.printDwarfEnum("encoding", N->getEncoding(),
2030*82d56013Sjoerg dwarf::AttributeEncodingString);
2031*82d56013Sjoerg Out << ")";
2032*82d56013Sjoerg }
2033*82d56013Sjoerg
writeDIDerivedType(raw_ostream & Out,const DIDerivedType * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)20347330f729Sjoerg static void writeDIDerivedType(raw_ostream &Out, const DIDerivedType *N,
20357330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
20367330f729Sjoerg const Module *Context) {
20377330f729Sjoerg Out << "!DIDerivedType(";
20387330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
20397330f729Sjoerg Printer.printTag(N);
20407330f729Sjoerg Printer.printString("name", N->getName());
20417330f729Sjoerg Printer.printMetadata("scope", N->getRawScope());
20427330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
20437330f729Sjoerg Printer.printInt("line", N->getLine());
20447330f729Sjoerg Printer.printMetadata("baseType", N->getRawBaseType(),
20457330f729Sjoerg /* ShouldSkipNull */ false);
20467330f729Sjoerg Printer.printInt("size", N->getSizeInBits());
20477330f729Sjoerg Printer.printInt("align", N->getAlignInBits());
20487330f729Sjoerg Printer.printInt("offset", N->getOffsetInBits());
20497330f729Sjoerg Printer.printDIFlags("flags", N->getFlags());
20507330f729Sjoerg Printer.printMetadata("extraData", N->getRawExtraData());
20517330f729Sjoerg if (const auto &DWARFAddressSpace = N->getDWARFAddressSpace())
20527330f729Sjoerg Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace,
20537330f729Sjoerg /* ShouldSkipZero */ false);
20547330f729Sjoerg Out << ")";
20557330f729Sjoerg }
20567330f729Sjoerg
writeDICompositeType(raw_ostream & Out,const DICompositeType * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)20577330f729Sjoerg static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
20587330f729Sjoerg TypePrinting *TypePrinter,
20597330f729Sjoerg SlotTracker *Machine, const Module *Context) {
20607330f729Sjoerg Out << "!DICompositeType(";
20617330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
20627330f729Sjoerg Printer.printTag(N);
20637330f729Sjoerg Printer.printString("name", N->getName());
20647330f729Sjoerg Printer.printMetadata("scope", N->getRawScope());
20657330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
20667330f729Sjoerg Printer.printInt("line", N->getLine());
20677330f729Sjoerg Printer.printMetadata("baseType", N->getRawBaseType());
20687330f729Sjoerg Printer.printInt("size", N->getSizeInBits());
20697330f729Sjoerg Printer.printInt("align", N->getAlignInBits());
20707330f729Sjoerg Printer.printInt("offset", N->getOffsetInBits());
20717330f729Sjoerg Printer.printDIFlags("flags", N->getFlags());
20727330f729Sjoerg Printer.printMetadata("elements", N->getRawElements());
20737330f729Sjoerg Printer.printDwarfEnum("runtimeLang", N->getRuntimeLang(),
20747330f729Sjoerg dwarf::LanguageString);
20757330f729Sjoerg Printer.printMetadata("vtableHolder", N->getRawVTableHolder());
20767330f729Sjoerg Printer.printMetadata("templateParams", N->getRawTemplateParams());
20777330f729Sjoerg Printer.printString("identifier", N->getIdentifier());
20787330f729Sjoerg Printer.printMetadata("discriminator", N->getRawDiscriminator());
2079*82d56013Sjoerg Printer.printMetadata("dataLocation", N->getRawDataLocation());
2080*82d56013Sjoerg Printer.printMetadata("associated", N->getRawAssociated());
2081*82d56013Sjoerg Printer.printMetadata("allocated", N->getRawAllocated());
2082*82d56013Sjoerg if (auto *RankConst = N->getRankConst())
2083*82d56013Sjoerg Printer.printInt("rank", RankConst->getSExtValue(),
2084*82d56013Sjoerg /* ShouldSkipZero */ false);
2085*82d56013Sjoerg else
2086*82d56013Sjoerg Printer.printMetadata("rank", N->getRawRank(), /*ShouldSkipNull */ true);
20877330f729Sjoerg Out << ")";
20887330f729Sjoerg }
20897330f729Sjoerg
writeDISubroutineType(raw_ostream & Out,const DISubroutineType * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)20907330f729Sjoerg static void writeDISubroutineType(raw_ostream &Out, const DISubroutineType *N,
20917330f729Sjoerg TypePrinting *TypePrinter,
20927330f729Sjoerg SlotTracker *Machine, const Module *Context) {
20937330f729Sjoerg Out << "!DISubroutineType(";
20947330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
20957330f729Sjoerg Printer.printDIFlags("flags", N->getFlags());
20967330f729Sjoerg Printer.printDwarfEnum("cc", N->getCC(), dwarf::ConventionString);
20977330f729Sjoerg Printer.printMetadata("types", N->getRawTypeArray(),
20987330f729Sjoerg /* ShouldSkipNull */ false);
20997330f729Sjoerg Out << ")";
21007330f729Sjoerg }
21017330f729Sjoerg
writeDIFile(raw_ostream & Out,const DIFile * N,TypePrinting *,SlotTracker *,const Module *)21027330f729Sjoerg static void writeDIFile(raw_ostream &Out, const DIFile *N, TypePrinting *,
21037330f729Sjoerg SlotTracker *, const Module *) {
21047330f729Sjoerg Out << "!DIFile(";
21057330f729Sjoerg MDFieldPrinter Printer(Out);
21067330f729Sjoerg Printer.printString("filename", N->getFilename(),
21077330f729Sjoerg /* ShouldSkipEmpty */ false);
21087330f729Sjoerg Printer.printString("directory", N->getDirectory(),
21097330f729Sjoerg /* ShouldSkipEmpty */ false);
21107330f729Sjoerg // Print all values for checksum together, or not at all.
21117330f729Sjoerg if (N->getChecksum())
21127330f729Sjoerg Printer.printChecksum(*N->getChecksum());
21137330f729Sjoerg Printer.printString("source", N->getSource().getValueOr(StringRef()),
21147330f729Sjoerg /* ShouldSkipEmpty */ true);
21157330f729Sjoerg Out << ")";
21167330f729Sjoerg }
21177330f729Sjoerg
writeDICompileUnit(raw_ostream & Out,const DICompileUnit * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)21187330f729Sjoerg static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N,
21197330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
21207330f729Sjoerg const Module *Context) {
21217330f729Sjoerg Out << "!DICompileUnit(";
21227330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
21237330f729Sjoerg Printer.printDwarfEnum("language", N->getSourceLanguage(),
21247330f729Sjoerg dwarf::LanguageString, /* ShouldSkipZero */ false);
21257330f729Sjoerg Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false);
21267330f729Sjoerg Printer.printString("producer", N->getProducer());
21277330f729Sjoerg Printer.printBool("isOptimized", N->isOptimized());
21287330f729Sjoerg Printer.printString("flags", N->getFlags());
21297330f729Sjoerg Printer.printInt("runtimeVersion", N->getRuntimeVersion(),
21307330f729Sjoerg /* ShouldSkipZero */ false);
21317330f729Sjoerg Printer.printString("splitDebugFilename", N->getSplitDebugFilename());
21327330f729Sjoerg Printer.printEmissionKind("emissionKind", N->getEmissionKind());
21337330f729Sjoerg Printer.printMetadata("enums", N->getRawEnumTypes());
21347330f729Sjoerg Printer.printMetadata("retainedTypes", N->getRawRetainedTypes());
21357330f729Sjoerg Printer.printMetadata("globals", N->getRawGlobalVariables());
21367330f729Sjoerg Printer.printMetadata("imports", N->getRawImportedEntities());
21377330f729Sjoerg Printer.printMetadata("macros", N->getRawMacros());
21387330f729Sjoerg Printer.printInt("dwoId", N->getDWOId());
21397330f729Sjoerg Printer.printBool("splitDebugInlining", N->getSplitDebugInlining(), true);
21407330f729Sjoerg Printer.printBool("debugInfoForProfiling", N->getDebugInfoForProfiling(),
21417330f729Sjoerg false);
21427330f729Sjoerg Printer.printNameTableKind("nameTableKind", N->getNameTableKind());
21437330f729Sjoerg Printer.printBool("rangesBaseAddress", N->getRangesBaseAddress(), false);
2144*82d56013Sjoerg Printer.printString("sysroot", N->getSysRoot());
2145*82d56013Sjoerg Printer.printString("sdk", N->getSDK());
21467330f729Sjoerg Out << ")";
21477330f729Sjoerg }
21487330f729Sjoerg
writeDISubprogram(raw_ostream & Out,const DISubprogram * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)21497330f729Sjoerg static void writeDISubprogram(raw_ostream &Out, const DISubprogram *N,
21507330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
21517330f729Sjoerg const Module *Context) {
21527330f729Sjoerg Out << "!DISubprogram(";
21537330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
21547330f729Sjoerg Printer.printString("name", N->getName());
21557330f729Sjoerg Printer.printString("linkageName", N->getLinkageName());
21567330f729Sjoerg Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
21577330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
21587330f729Sjoerg Printer.printInt("line", N->getLine());
21597330f729Sjoerg Printer.printMetadata("type", N->getRawType());
21607330f729Sjoerg Printer.printInt("scopeLine", N->getScopeLine());
21617330f729Sjoerg Printer.printMetadata("containingType", N->getRawContainingType());
21627330f729Sjoerg if (N->getVirtuality() != dwarf::DW_VIRTUALITY_none ||
21637330f729Sjoerg N->getVirtualIndex() != 0)
21647330f729Sjoerg Printer.printInt("virtualIndex", N->getVirtualIndex(), false);
21657330f729Sjoerg Printer.printInt("thisAdjustment", N->getThisAdjustment());
21667330f729Sjoerg Printer.printDIFlags("flags", N->getFlags());
21677330f729Sjoerg Printer.printDISPFlags("spFlags", N->getSPFlags());
21687330f729Sjoerg Printer.printMetadata("unit", N->getRawUnit());
21697330f729Sjoerg Printer.printMetadata("templateParams", N->getRawTemplateParams());
21707330f729Sjoerg Printer.printMetadata("declaration", N->getRawDeclaration());
21717330f729Sjoerg Printer.printMetadata("retainedNodes", N->getRawRetainedNodes());
21727330f729Sjoerg Printer.printMetadata("thrownTypes", N->getRawThrownTypes());
21737330f729Sjoerg Out << ")";
21747330f729Sjoerg }
21757330f729Sjoerg
writeDILexicalBlock(raw_ostream & Out,const DILexicalBlock * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)21767330f729Sjoerg static void writeDILexicalBlock(raw_ostream &Out, const DILexicalBlock *N,
21777330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
21787330f729Sjoerg const Module *Context) {
21797330f729Sjoerg Out << "!DILexicalBlock(";
21807330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
21817330f729Sjoerg Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
21827330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
21837330f729Sjoerg Printer.printInt("line", N->getLine());
21847330f729Sjoerg Printer.printInt("column", N->getColumn());
21857330f729Sjoerg Out << ")";
21867330f729Sjoerg }
21877330f729Sjoerg
writeDILexicalBlockFile(raw_ostream & Out,const DILexicalBlockFile * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)21887330f729Sjoerg static void writeDILexicalBlockFile(raw_ostream &Out,
21897330f729Sjoerg const DILexicalBlockFile *N,
21907330f729Sjoerg TypePrinting *TypePrinter,
21917330f729Sjoerg SlotTracker *Machine,
21927330f729Sjoerg const Module *Context) {
21937330f729Sjoerg Out << "!DILexicalBlockFile(";
21947330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
21957330f729Sjoerg Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
21967330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
21977330f729Sjoerg Printer.printInt("discriminator", N->getDiscriminator(),
21987330f729Sjoerg /* ShouldSkipZero */ false);
21997330f729Sjoerg Out << ")";
22007330f729Sjoerg }
22017330f729Sjoerg
writeDINamespace(raw_ostream & Out,const DINamespace * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)22027330f729Sjoerg static void writeDINamespace(raw_ostream &Out, const DINamespace *N,
22037330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
22047330f729Sjoerg const Module *Context) {
22057330f729Sjoerg Out << "!DINamespace(";
22067330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
22077330f729Sjoerg Printer.printString("name", N->getName());
22087330f729Sjoerg Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
22097330f729Sjoerg Printer.printBool("exportSymbols", N->getExportSymbols(), false);
22107330f729Sjoerg Out << ")";
22117330f729Sjoerg }
22127330f729Sjoerg
writeDICommonBlock(raw_ostream & Out,const DICommonBlock * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)22137330f729Sjoerg static void writeDICommonBlock(raw_ostream &Out, const DICommonBlock *N,
22147330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
22157330f729Sjoerg const Module *Context) {
22167330f729Sjoerg Out << "!DICommonBlock(";
22177330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
22187330f729Sjoerg Printer.printMetadata("scope", N->getRawScope(), false);
22197330f729Sjoerg Printer.printMetadata("declaration", N->getRawDecl(), false);
22207330f729Sjoerg Printer.printString("name", N->getName());
22217330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
22227330f729Sjoerg Printer.printInt("line", N->getLineNo());
22237330f729Sjoerg Out << ")";
22247330f729Sjoerg }
22257330f729Sjoerg
writeDIMacro(raw_ostream & Out,const DIMacro * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)22267330f729Sjoerg static void writeDIMacro(raw_ostream &Out, const DIMacro *N,
22277330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
22287330f729Sjoerg const Module *Context) {
22297330f729Sjoerg Out << "!DIMacro(";
22307330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
22317330f729Sjoerg Printer.printMacinfoType(N);
22327330f729Sjoerg Printer.printInt("line", N->getLine());
22337330f729Sjoerg Printer.printString("name", N->getName());
22347330f729Sjoerg Printer.printString("value", N->getValue());
22357330f729Sjoerg Out << ")";
22367330f729Sjoerg }
22377330f729Sjoerg
writeDIMacroFile(raw_ostream & Out,const DIMacroFile * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)22387330f729Sjoerg static void writeDIMacroFile(raw_ostream &Out, const DIMacroFile *N,
22397330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
22407330f729Sjoerg const Module *Context) {
22417330f729Sjoerg Out << "!DIMacroFile(";
22427330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
22437330f729Sjoerg Printer.printInt("line", N->getLine());
22447330f729Sjoerg Printer.printMetadata("file", N->getRawFile(), /* ShouldSkipNull */ false);
22457330f729Sjoerg Printer.printMetadata("nodes", N->getRawElements());
22467330f729Sjoerg Out << ")";
22477330f729Sjoerg }
22487330f729Sjoerg
writeDIModule(raw_ostream & Out,const DIModule * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)22497330f729Sjoerg static void writeDIModule(raw_ostream &Out, const DIModule *N,
22507330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
22517330f729Sjoerg const Module *Context) {
22527330f729Sjoerg Out << "!DIModule(";
22537330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
22547330f729Sjoerg Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
22557330f729Sjoerg Printer.printString("name", N->getName());
22567330f729Sjoerg Printer.printString("configMacros", N->getConfigurationMacros());
22577330f729Sjoerg Printer.printString("includePath", N->getIncludePath());
2258*82d56013Sjoerg Printer.printString("apinotes", N->getAPINotesFile());
2259*82d56013Sjoerg Printer.printMetadata("file", N->getRawFile());
2260*82d56013Sjoerg Printer.printInt("line", N->getLineNo());
2261*82d56013Sjoerg Printer.printBool("isDecl", N->getIsDecl(), /* Default */ false);
22627330f729Sjoerg Out << ")";
22637330f729Sjoerg }
22647330f729Sjoerg
22657330f729Sjoerg
writeDITemplateTypeParameter(raw_ostream & Out,const DITemplateTypeParameter * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)22667330f729Sjoerg static void writeDITemplateTypeParameter(raw_ostream &Out,
22677330f729Sjoerg const DITemplateTypeParameter *N,
22687330f729Sjoerg TypePrinting *TypePrinter,
22697330f729Sjoerg SlotTracker *Machine,
22707330f729Sjoerg const Module *Context) {
22717330f729Sjoerg Out << "!DITemplateTypeParameter(";
22727330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
22737330f729Sjoerg Printer.printString("name", N->getName());
22747330f729Sjoerg Printer.printMetadata("type", N->getRawType(), /* ShouldSkipNull */ false);
2275*82d56013Sjoerg Printer.printBool("defaulted", N->isDefault(), /* Default= */ false);
22767330f729Sjoerg Out << ")";
22777330f729Sjoerg }
22787330f729Sjoerg
writeDITemplateValueParameter(raw_ostream & Out,const DITemplateValueParameter * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)22797330f729Sjoerg static void writeDITemplateValueParameter(raw_ostream &Out,
22807330f729Sjoerg const DITemplateValueParameter *N,
22817330f729Sjoerg TypePrinting *TypePrinter,
22827330f729Sjoerg SlotTracker *Machine,
22837330f729Sjoerg const Module *Context) {
22847330f729Sjoerg Out << "!DITemplateValueParameter(";
22857330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
22867330f729Sjoerg if (N->getTag() != dwarf::DW_TAG_template_value_parameter)
22877330f729Sjoerg Printer.printTag(N);
22887330f729Sjoerg Printer.printString("name", N->getName());
22897330f729Sjoerg Printer.printMetadata("type", N->getRawType());
2290*82d56013Sjoerg Printer.printBool("defaulted", N->isDefault(), /* Default= */ false);
22917330f729Sjoerg Printer.printMetadata("value", N->getValue(), /* ShouldSkipNull */ false);
22927330f729Sjoerg Out << ")";
22937330f729Sjoerg }
22947330f729Sjoerg
writeDIGlobalVariable(raw_ostream & Out,const DIGlobalVariable * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)22957330f729Sjoerg static void writeDIGlobalVariable(raw_ostream &Out, const DIGlobalVariable *N,
22967330f729Sjoerg TypePrinting *TypePrinter,
22977330f729Sjoerg SlotTracker *Machine, const Module *Context) {
22987330f729Sjoerg Out << "!DIGlobalVariable(";
22997330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
23007330f729Sjoerg Printer.printString("name", N->getName());
23017330f729Sjoerg Printer.printString("linkageName", N->getLinkageName());
23027330f729Sjoerg Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
23037330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
23047330f729Sjoerg Printer.printInt("line", N->getLine());
23057330f729Sjoerg Printer.printMetadata("type", N->getRawType());
23067330f729Sjoerg Printer.printBool("isLocal", N->isLocalToUnit());
23077330f729Sjoerg Printer.printBool("isDefinition", N->isDefinition());
23087330f729Sjoerg Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration());
23097330f729Sjoerg Printer.printMetadata("templateParams", N->getRawTemplateParams());
23107330f729Sjoerg Printer.printInt("align", N->getAlignInBits());
23117330f729Sjoerg Out << ")";
23127330f729Sjoerg }
23137330f729Sjoerg
writeDILocalVariable(raw_ostream & Out,const DILocalVariable * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)23147330f729Sjoerg static void writeDILocalVariable(raw_ostream &Out, const DILocalVariable *N,
23157330f729Sjoerg TypePrinting *TypePrinter,
23167330f729Sjoerg SlotTracker *Machine, const Module *Context) {
23177330f729Sjoerg Out << "!DILocalVariable(";
23187330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
23197330f729Sjoerg Printer.printString("name", N->getName());
23207330f729Sjoerg Printer.printInt("arg", N->getArg());
23217330f729Sjoerg Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
23227330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
23237330f729Sjoerg Printer.printInt("line", N->getLine());
23247330f729Sjoerg Printer.printMetadata("type", N->getRawType());
23257330f729Sjoerg Printer.printDIFlags("flags", N->getFlags());
23267330f729Sjoerg Printer.printInt("align", N->getAlignInBits());
23277330f729Sjoerg Out << ")";
23287330f729Sjoerg }
23297330f729Sjoerg
writeDILabel(raw_ostream & Out,const DILabel * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)23307330f729Sjoerg static void writeDILabel(raw_ostream &Out, const DILabel *N,
23317330f729Sjoerg TypePrinting *TypePrinter,
23327330f729Sjoerg SlotTracker *Machine, const Module *Context) {
23337330f729Sjoerg Out << "!DILabel(";
23347330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
23357330f729Sjoerg Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
23367330f729Sjoerg Printer.printString("name", N->getName());
23377330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
23387330f729Sjoerg Printer.printInt("line", N->getLine());
23397330f729Sjoerg Out << ")";
23407330f729Sjoerg }
23417330f729Sjoerg
writeDIExpression(raw_ostream & Out,const DIExpression * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)23427330f729Sjoerg static void writeDIExpression(raw_ostream &Out, const DIExpression *N,
23437330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
23447330f729Sjoerg const Module *Context) {
23457330f729Sjoerg Out << "!DIExpression(";
23467330f729Sjoerg FieldSeparator FS;
23477330f729Sjoerg if (N->isValid()) {
2348*82d56013Sjoerg for (const DIExpression::ExprOperand &Op : N->expr_ops()) {
2349*82d56013Sjoerg auto OpStr = dwarf::OperationEncodingString(Op.getOp());
23507330f729Sjoerg assert(!OpStr.empty() && "Expected valid opcode");
23517330f729Sjoerg
23527330f729Sjoerg Out << FS << OpStr;
2353*82d56013Sjoerg if (Op.getOp() == dwarf::DW_OP_LLVM_convert) {
2354*82d56013Sjoerg Out << FS << Op.getArg(0);
2355*82d56013Sjoerg Out << FS << dwarf::AttributeEncodingString(Op.getArg(1));
23567330f729Sjoerg } else {
2357*82d56013Sjoerg for (unsigned A = 0, AE = Op.getNumArgs(); A != AE; ++A)
2358*82d56013Sjoerg Out << FS << Op.getArg(A);
23597330f729Sjoerg }
23607330f729Sjoerg }
23617330f729Sjoerg } else {
23627330f729Sjoerg for (const auto &I : N->getElements())
23637330f729Sjoerg Out << FS << I;
23647330f729Sjoerg }
23657330f729Sjoerg Out << ")";
23667330f729Sjoerg }
23677330f729Sjoerg
writeDIArgList(raw_ostream & Out,const DIArgList * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context,bool FromValue=false)2368*82d56013Sjoerg static void writeDIArgList(raw_ostream &Out, const DIArgList *N,
2369*82d56013Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
2370*82d56013Sjoerg const Module *Context, bool FromValue = false) {
2371*82d56013Sjoerg assert(FromValue &&
2372*82d56013Sjoerg "Unexpected DIArgList metadata outside of value argument");
2373*82d56013Sjoerg Out << "!DIArgList(";
2374*82d56013Sjoerg FieldSeparator FS;
2375*82d56013Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
2376*82d56013Sjoerg for (Metadata *Arg : N->getArgs()) {
2377*82d56013Sjoerg Out << FS;
2378*82d56013Sjoerg WriteAsOperandInternal(Out, Arg, TypePrinter, Machine, Context, true);
2379*82d56013Sjoerg }
2380*82d56013Sjoerg Out << ")";
2381*82d56013Sjoerg }
2382*82d56013Sjoerg
writeDIGlobalVariableExpression(raw_ostream & Out,const DIGlobalVariableExpression * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)23837330f729Sjoerg static void writeDIGlobalVariableExpression(raw_ostream &Out,
23847330f729Sjoerg const DIGlobalVariableExpression *N,
23857330f729Sjoerg TypePrinting *TypePrinter,
23867330f729Sjoerg SlotTracker *Machine,
23877330f729Sjoerg const Module *Context) {
23887330f729Sjoerg Out << "!DIGlobalVariableExpression(";
23897330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
23907330f729Sjoerg Printer.printMetadata("var", N->getVariable());
23917330f729Sjoerg Printer.printMetadata("expr", N->getExpression());
23927330f729Sjoerg Out << ")";
23937330f729Sjoerg }
23947330f729Sjoerg
writeDIObjCProperty(raw_ostream & Out,const DIObjCProperty * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)23957330f729Sjoerg static void writeDIObjCProperty(raw_ostream &Out, const DIObjCProperty *N,
23967330f729Sjoerg TypePrinting *TypePrinter, SlotTracker *Machine,
23977330f729Sjoerg const Module *Context) {
23987330f729Sjoerg Out << "!DIObjCProperty(";
23997330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
24007330f729Sjoerg Printer.printString("name", N->getName());
24017330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
24027330f729Sjoerg Printer.printInt("line", N->getLine());
24037330f729Sjoerg Printer.printString("setter", N->getSetterName());
24047330f729Sjoerg Printer.printString("getter", N->getGetterName());
24057330f729Sjoerg Printer.printInt("attributes", N->getAttributes());
24067330f729Sjoerg Printer.printMetadata("type", N->getRawType());
24077330f729Sjoerg Out << ")";
24087330f729Sjoerg }
24097330f729Sjoerg
writeDIImportedEntity(raw_ostream & Out,const DIImportedEntity * N,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)24107330f729Sjoerg static void writeDIImportedEntity(raw_ostream &Out, const DIImportedEntity *N,
24117330f729Sjoerg TypePrinting *TypePrinter,
24127330f729Sjoerg SlotTracker *Machine, const Module *Context) {
24137330f729Sjoerg Out << "!DIImportedEntity(";
24147330f729Sjoerg MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
24157330f729Sjoerg Printer.printTag(N);
24167330f729Sjoerg Printer.printString("name", N->getName());
24177330f729Sjoerg Printer.printMetadata("scope", N->getRawScope(), /* ShouldSkipNull */ false);
24187330f729Sjoerg Printer.printMetadata("entity", N->getRawEntity());
24197330f729Sjoerg Printer.printMetadata("file", N->getRawFile());
24207330f729Sjoerg Printer.printInt("line", N->getLine());
24217330f729Sjoerg Out << ")";
24227330f729Sjoerg }
24237330f729Sjoerg
WriteMDNodeBodyInternal(raw_ostream & Out,const MDNode * Node,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)24247330f729Sjoerg static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
24257330f729Sjoerg TypePrinting *TypePrinter,
24267330f729Sjoerg SlotTracker *Machine,
24277330f729Sjoerg const Module *Context) {
24287330f729Sjoerg if (Node->isDistinct())
24297330f729Sjoerg Out << "distinct ";
24307330f729Sjoerg else if (Node->isTemporary())
24317330f729Sjoerg Out << "<temporary!> "; // Handle broken code.
24327330f729Sjoerg
24337330f729Sjoerg switch (Node->getMetadataID()) {
24347330f729Sjoerg default:
24357330f729Sjoerg llvm_unreachable("Expected uniquable MDNode");
24367330f729Sjoerg #define HANDLE_MDNODE_LEAF(CLASS) \
24377330f729Sjoerg case Metadata::CLASS##Kind: \
24387330f729Sjoerg write##CLASS(Out, cast<CLASS>(Node), TypePrinter, Machine, Context); \
24397330f729Sjoerg break;
24407330f729Sjoerg #include "llvm/IR/Metadata.def"
24417330f729Sjoerg }
24427330f729Sjoerg }
24437330f729Sjoerg
24447330f729Sjoerg // Full implementation of printing a Value as an operand with support for
24457330f729Sjoerg // TypePrinting, etc.
WriteAsOperandInternal(raw_ostream & Out,const Value * V,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context)24467330f729Sjoerg static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
24477330f729Sjoerg TypePrinting *TypePrinter,
24487330f729Sjoerg SlotTracker *Machine,
24497330f729Sjoerg const Module *Context) {
24507330f729Sjoerg if (V->hasName()) {
24517330f729Sjoerg PrintLLVMName(Out, V);
24527330f729Sjoerg return;
24537330f729Sjoerg }
24547330f729Sjoerg
24557330f729Sjoerg const Constant *CV = dyn_cast<Constant>(V);
24567330f729Sjoerg if (CV && !isa<GlobalValue>(CV)) {
24577330f729Sjoerg assert(TypePrinter && "Constants require TypePrinting!");
24587330f729Sjoerg WriteConstantInternal(Out, CV, *TypePrinter, Machine, Context);
24597330f729Sjoerg return;
24607330f729Sjoerg }
24617330f729Sjoerg
24627330f729Sjoerg if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) {
24637330f729Sjoerg Out << "asm ";
24647330f729Sjoerg if (IA->hasSideEffects())
24657330f729Sjoerg Out << "sideeffect ";
24667330f729Sjoerg if (IA->isAlignStack())
24677330f729Sjoerg Out << "alignstack ";
24687330f729Sjoerg // We don't emit the AD_ATT dialect as it's the assumed default.
24697330f729Sjoerg if (IA->getDialect() == InlineAsm::AD_Intel)
24707330f729Sjoerg Out << "inteldialect ";
2471*82d56013Sjoerg if (IA->canThrow())
2472*82d56013Sjoerg Out << "unwind ";
24737330f729Sjoerg Out << '"';
24747330f729Sjoerg printEscapedString(IA->getAsmString(), Out);
24757330f729Sjoerg Out << "\", \"";
24767330f729Sjoerg printEscapedString(IA->getConstraintString(), Out);
24777330f729Sjoerg Out << '"';
24787330f729Sjoerg return;
24797330f729Sjoerg }
24807330f729Sjoerg
24817330f729Sjoerg if (auto *MD = dyn_cast<MetadataAsValue>(V)) {
24827330f729Sjoerg WriteAsOperandInternal(Out, MD->getMetadata(), TypePrinter, Machine,
24837330f729Sjoerg Context, /* FromValue */ true);
24847330f729Sjoerg return;
24857330f729Sjoerg }
24867330f729Sjoerg
24877330f729Sjoerg char Prefix = '%';
24887330f729Sjoerg int Slot;
24897330f729Sjoerg // If we have a SlotTracker, use it.
24907330f729Sjoerg if (Machine) {
24917330f729Sjoerg if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
24927330f729Sjoerg Slot = Machine->getGlobalSlot(GV);
24937330f729Sjoerg Prefix = '@';
24947330f729Sjoerg } else {
24957330f729Sjoerg Slot = Machine->getLocalSlot(V);
24967330f729Sjoerg
24977330f729Sjoerg // If the local value didn't succeed, then we may be referring to a value
24987330f729Sjoerg // from a different function. Translate it, as this can happen when using
24997330f729Sjoerg // address of blocks.
25007330f729Sjoerg if (Slot == -1)
25017330f729Sjoerg if ((Machine = createSlotTracker(V))) {
25027330f729Sjoerg Slot = Machine->getLocalSlot(V);
25037330f729Sjoerg delete Machine;
25047330f729Sjoerg }
25057330f729Sjoerg }
25067330f729Sjoerg } else if ((Machine = createSlotTracker(V))) {
25077330f729Sjoerg // Otherwise, create one to get the # and then destroy it.
25087330f729Sjoerg if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
25097330f729Sjoerg Slot = Machine->getGlobalSlot(GV);
25107330f729Sjoerg Prefix = '@';
25117330f729Sjoerg } else {
25127330f729Sjoerg Slot = Machine->getLocalSlot(V);
25137330f729Sjoerg }
25147330f729Sjoerg delete Machine;
25157330f729Sjoerg Machine = nullptr;
25167330f729Sjoerg } else {
25177330f729Sjoerg Slot = -1;
25187330f729Sjoerg }
25197330f729Sjoerg
25207330f729Sjoerg if (Slot != -1)
25217330f729Sjoerg Out << Prefix << Slot;
25227330f729Sjoerg else
25237330f729Sjoerg Out << "<badref>";
25247330f729Sjoerg }
25257330f729Sjoerg
WriteAsOperandInternal(raw_ostream & Out,const Metadata * MD,TypePrinting * TypePrinter,SlotTracker * Machine,const Module * Context,bool FromValue)25267330f729Sjoerg static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
25277330f729Sjoerg TypePrinting *TypePrinter,
25287330f729Sjoerg SlotTracker *Machine, const Module *Context,
25297330f729Sjoerg bool FromValue) {
2530*82d56013Sjoerg // Write DIExpressions and DIArgLists inline when used as a value. Improves
2531*82d56013Sjoerg // readability of debug info intrinsics.
25327330f729Sjoerg if (const DIExpression *Expr = dyn_cast<DIExpression>(MD)) {
25337330f729Sjoerg writeDIExpression(Out, Expr, TypePrinter, Machine, Context);
25347330f729Sjoerg return;
25357330f729Sjoerg }
2536*82d56013Sjoerg if (const DIArgList *ArgList = dyn_cast<DIArgList>(MD)) {
2537*82d56013Sjoerg writeDIArgList(Out, ArgList, TypePrinter, Machine, Context, FromValue);
2538*82d56013Sjoerg return;
2539*82d56013Sjoerg }
25407330f729Sjoerg
25417330f729Sjoerg if (const MDNode *N = dyn_cast<MDNode>(MD)) {
25427330f729Sjoerg std::unique_ptr<SlotTracker> MachineStorage;
25437330f729Sjoerg if (!Machine) {
25447330f729Sjoerg MachineStorage = std::make_unique<SlotTracker>(Context);
25457330f729Sjoerg Machine = MachineStorage.get();
25467330f729Sjoerg }
25477330f729Sjoerg int Slot = Machine->getMetadataSlot(N);
25487330f729Sjoerg if (Slot == -1) {
25497330f729Sjoerg if (const DILocation *Loc = dyn_cast<DILocation>(N)) {
25507330f729Sjoerg writeDILocation(Out, Loc, TypePrinter, Machine, Context);
25517330f729Sjoerg return;
25527330f729Sjoerg }
25537330f729Sjoerg // Give the pointer value instead of "badref", since this comes up all
25547330f729Sjoerg // the time when debugging.
25557330f729Sjoerg Out << "<" << N << ">";
25567330f729Sjoerg } else
25577330f729Sjoerg Out << '!' << Slot;
25587330f729Sjoerg return;
25597330f729Sjoerg }
25607330f729Sjoerg
25617330f729Sjoerg if (const MDString *MDS = dyn_cast<MDString>(MD)) {
25627330f729Sjoerg Out << "!\"";
25637330f729Sjoerg printEscapedString(MDS->getString(), Out);
25647330f729Sjoerg Out << '"';
25657330f729Sjoerg return;
25667330f729Sjoerg }
25677330f729Sjoerg
25687330f729Sjoerg auto *V = cast<ValueAsMetadata>(MD);
25697330f729Sjoerg assert(TypePrinter && "TypePrinter required for metadata values");
25707330f729Sjoerg assert((FromValue || !isa<LocalAsMetadata>(V)) &&
25717330f729Sjoerg "Unexpected function-local metadata outside of value argument");
25727330f729Sjoerg
25737330f729Sjoerg TypePrinter->print(V->getValue()->getType(), Out);
25747330f729Sjoerg Out << ' ';
25757330f729Sjoerg WriteAsOperandInternal(Out, V->getValue(), TypePrinter, Machine, Context);
25767330f729Sjoerg }
25777330f729Sjoerg
25787330f729Sjoerg namespace {
25797330f729Sjoerg
25807330f729Sjoerg class AssemblyWriter {
25817330f729Sjoerg formatted_raw_ostream &Out;
25827330f729Sjoerg const Module *TheModule = nullptr;
25837330f729Sjoerg const ModuleSummaryIndex *TheIndex = nullptr;
25847330f729Sjoerg std::unique_ptr<SlotTracker> SlotTrackerStorage;
25857330f729Sjoerg SlotTracker &Machine;
25867330f729Sjoerg TypePrinting TypePrinter;
25877330f729Sjoerg AssemblyAnnotationWriter *AnnotationWriter = nullptr;
25887330f729Sjoerg SetVector<const Comdat *> Comdats;
25897330f729Sjoerg bool IsForDebug;
25907330f729Sjoerg bool ShouldPreserveUseListOrder;
25917330f729Sjoerg UseListOrderStack UseListOrders;
25927330f729Sjoerg SmallVector<StringRef, 8> MDNames;
25937330f729Sjoerg /// Synchronization scope names registered with LLVMContext.
25947330f729Sjoerg SmallVector<StringRef, 8> SSNs;
25957330f729Sjoerg DenseMap<const GlobalValueSummary *, GlobalValue::GUID> SummaryToGUIDMap;
25967330f729Sjoerg
25977330f729Sjoerg public:
25987330f729Sjoerg /// Construct an AssemblyWriter with an external SlotTracker
25997330f729Sjoerg AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, const Module *M,
26007330f729Sjoerg AssemblyAnnotationWriter *AAW, bool IsForDebug,
26017330f729Sjoerg bool ShouldPreserveUseListOrder = false);
26027330f729Sjoerg
26037330f729Sjoerg AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
26047330f729Sjoerg const ModuleSummaryIndex *Index, bool IsForDebug);
26057330f729Sjoerg
26067330f729Sjoerg void printMDNodeBody(const MDNode *MD);
26077330f729Sjoerg void printNamedMDNode(const NamedMDNode *NMD);
26087330f729Sjoerg
26097330f729Sjoerg void printModule(const Module *M);
26107330f729Sjoerg
26117330f729Sjoerg void writeOperand(const Value *Op, bool PrintType);
26127330f729Sjoerg void writeParamOperand(const Value *Operand, AttributeSet Attrs);
26137330f729Sjoerg void writeOperandBundles(const CallBase *Call);
26147330f729Sjoerg void writeSyncScope(const LLVMContext &Context,
26157330f729Sjoerg SyncScope::ID SSID);
26167330f729Sjoerg void writeAtomic(const LLVMContext &Context,
26177330f729Sjoerg AtomicOrdering Ordering,
26187330f729Sjoerg SyncScope::ID SSID);
26197330f729Sjoerg void writeAtomicCmpXchg(const LLVMContext &Context,
26207330f729Sjoerg AtomicOrdering SuccessOrdering,
26217330f729Sjoerg AtomicOrdering FailureOrdering,
26227330f729Sjoerg SyncScope::ID SSID);
26237330f729Sjoerg
26247330f729Sjoerg void writeAllMDNodes();
26257330f729Sjoerg void writeMDNode(unsigned Slot, const MDNode *Node);
2626*82d56013Sjoerg void writeAttribute(const Attribute &Attr, bool InAttrGroup = false);
2627*82d56013Sjoerg void writeAttributeSet(const AttributeSet &AttrSet, bool InAttrGroup = false);
26287330f729Sjoerg void writeAllAttributeGroups();
26297330f729Sjoerg
26307330f729Sjoerg void printTypeIdentities();
26317330f729Sjoerg void printGlobal(const GlobalVariable *GV);
26327330f729Sjoerg void printIndirectSymbol(const GlobalIndirectSymbol *GIS);
26337330f729Sjoerg void printComdat(const Comdat *C);
26347330f729Sjoerg void printFunction(const Function *F);
26357330f729Sjoerg void printArgument(const Argument *FA, AttributeSet Attrs);
26367330f729Sjoerg void printBasicBlock(const BasicBlock *BB);
26377330f729Sjoerg void printInstructionLine(const Instruction &I);
26387330f729Sjoerg void printInstruction(const Instruction &I);
26397330f729Sjoerg
26407330f729Sjoerg void printUseListOrder(const UseListOrder &Order);
26417330f729Sjoerg void printUseLists(const Function *F);
26427330f729Sjoerg
26437330f729Sjoerg void printModuleSummaryIndex();
26447330f729Sjoerg void printSummaryInfo(unsigned Slot, const ValueInfo &VI);
26457330f729Sjoerg void printSummary(const GlobalValueSummary &Summary);
26467330f729Sjoerg void printAliasSummary(const AliasSummary *AS);
26477330f729Sjoerg void printGlobalVarSummary(const GlobalVarSummary *GS);
26487330f729Sjoerg void printFunctionSummary(const FunctionSummary *FS);
26497330f729Sjoerg void printTypeIdSummary(const TypeIdSummary &TIS);
26507330f729Sjoerg void printTypeIdCompatibleVtableSummary(const TypeIdCompatibleVtableInfo &TI);
26517330f729Sjoerg void printTypeTestResolution(const TypeTestResolution &TTRes);
26527330f729Sjoerg void printArgs(const std::vector<uint64_t> &Args);
26537330f729Sjoerg void printWPDRes(const WholeProgramDevirtResolution &WPDRes);
26547330f729Sjoerg void printTypeIdInfo(const FunctionSummary::TypeIdInfo &TIDInfo);
26557330f729Sjoerg void printVFuncId(const FunctionSummary::VFuncId VFId);
26567330f729Sjoerg void
2657*82d56013Sjoerg printNonConstVCalls(const std::vector<FunctionSummary::VFuncId> &VCallList,
26587330f729Sjoerg const char *Tag);
26597330f729Sjoerg void
2660*82d56013Sjoerg printConstVCalls(const std::vector<FunctionSummary::ConstVCall> &VCallList,
26617330f729Sjoerg const char *Tag);
26627330f729Sjoerg
26637330f729Sjoerg private:
26647330f729Sjoerg /// Print out metadata attachments.
26657330f729Sjoerg void printMetadataAttachments(
26667330f729Sjoerg const SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs,
26677330f729Sjoerg StringRef Separator);
26687330f729Sjoerg
26697330f729Sjoerg // printInfoComment - Print a little comment after the instruction indicating
26707330f729Sjoerg // which slot it occupies.
26717330f729Sjoerg void printInfoComment(const Value &V);
26727330f729Sjoerg
26737330f729Sjoerg // printGCRelocateComment - print comment after call to the gc.relocate
26747330f729Sjoerg // intrinsic indicating base and derived pointer names.
26757330f729Sjoerg void printGCRelocateComment(const GCRelocateInst &Relocate);
26767330f729Sjoerg };
26777330f729Sjoerg
26787330f729Sjoerg } // end anonymous namespace
26797330f729Sjoerg
AssemblyWriter(formatted_raw_ostream & o,SlotTracker & Mac,const Module * M,AssemblyAnnotationWriter * AAW,bool IsForDebug,bool ShouldPreserveUseListOrder)26807330f729Sjoerg AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
26817330f729Sjoerg const Module *M, AssemblyAnnotationWriter *AAW,
26827330f729Sjoerg bool IsForDebug, bool ShouldPreserveUseListOrder)
26837330f729Sjoerg : Out(o), TheModule(M), Machine(Mac), TypePrinter(M), AnnotationWriter(AAW),
26847330f729Sjoerg IsForDebug(IsForDebug),
26857330f729Sjoerg ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {
26867330f729Sjoerg if (!TheModule)
26877330f729Sjoerg return;
26887330f729Sjoerg for (const GlobalObject &GO : TheModule->global_objects())
26897330f729Sjoerg if (const Comdat *C = GO.getComdat())
26907330f729Sjoerg Comdats.insert(C);
26917330f729Sjoerg }
26927330f729Sjoerg
AssemblyWriter(formatted_raw_ostream & o,SlotTracker & Mac,const ModuleSummaryIndex * Index,bool IsForDebug)26937330f729Sjoerg AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac,
26947330f729Sjoerg const ModuleSummaryIndex *Index, bool IsForDebug)
26957330f729Sjoerg : Out(o), TheIndex(Index), Machine(Mac), TypePrinter(/*Module=*/nullptr),
26967330f729Sjoerg IsForDebug(IsForDebug), ShouldPreserveUseListOrder(false) {}
26977330f729Sjoerg
writeOperand(const Value * Operand,bool PrintType)26987330f729Sjoerg void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
26997330f729Sjoerg if (!Operand) {
27007330f729Sjoerg Out << "<null operand!>";
27017330f729Sjoerg return;
27027330f729Sjoerg }
27037330f729Sjoerg if (PrintType) {
27047330f729Sjoerg TypePrinter.print(Operand->getType(), Out);
27057330f729Sjoerg Out << ' ';
27067330f729Sjoerg }
27077330f729Sjoerg WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine, TheModule);
27087330f729Sjoerg }
27097330f729Sjoerg
writeSyncScope(const LLVMContext & Context,SyncScope::ID SSID)27107330f729Sjoerg void AssemblyWriter::writeSyncScope(const LLVMContext &Context,
27117330f729Sjoerg SyncScope::ID SSID) {
27127330f729Sjoerg switch (SSID) {
27137330f729Sjoerg case SyncScope::System: {
27147330f729Sjoerg break;
27157330f729Sjoerg }
27167330f729Sjoerg default: {
27177330f729Sjoerg if (SSNs.empty())
27187330f729Sjoerg Context.getSyncScopeNames(SSNs);
27197330f729Sjoerg
27207330f729Sjoerg Out << " syncscope(\"";
27217330f729Sjoerg printEscapedString(SSNs[SSID], Out);
27227330f729Sjoerg Out << "\")";
27237330f729Sjoerg break;
27247330f729Sjoerg }
27257330f729Sjoerg }
27267330f729Sjoerg }
27277330f729Sjoerg
writeAtomic(const LLVMContext & Context,AtomicOrdering Ordering,SyncScope::ID SSID)27287330f729Sjoerg void AssemblyWriter::writeAtomic(const LLVMContext &Context,
27297330f729Sjoerg AtomicOrdering Ordering,
27307330f729Sjoerg SyncScope::ID SSID) {
27317330f729Sjoerg if (Ordering == AtomicOrdering::NotAtomic)
27327330f729Sjoerg return;
27337330f729Sjoerg
27347330f729Sjoerg writeSyncScope(Context, SSID);
27357330f729Sjoerg Out << " " << toIRString(Ordering);
27367330f729Sjoerg }
27377330f729Sjoerg
writeAtomicCmpXchg(const LLVMContext & Context,AtomicOrdering SuccessOrdering,AtomicOrdering FailureOrdering,SyncScope::ID SSID)27387330f729Sjoerg void AssemblyWriter::writeAtomicCmpXchg(const LLVMContext &Context,
27397330f729Sjoerg AtomicOrdering SuccessOrdering,
27407330f729Sjoerg AtomicOrdering FailureOrdering,
27417330f729Sjoerg SyncScope::ID SSID) {
27427330f729Sjoerg assert(SuccessOrdering != AtomicOrdering::NotAtomic &&
27437330f729Sjoerg FailureOrdering != AtomicOrdering::NotAtomic);
27447330f729Sjoerg
27457330f729Sjoerg writeSyncScope(Context, SSID);
27467330f729Sjoerg Out << " " << toIRString(SuccessOrdering);
27477330f729Sjoerg Out << " " << toIRString(FailureOrdering);
27487330f729Sjoerg }
27497330f729Sjoerg
writeParamOperand(const Value * Operand,AttributeSet Attrs)27507330f729Sjoerg void AssemblyWriter::writeParamOperand(const Value *Operand,
27517330f729Sjoerg AttributeSet Attrs) {
27527330f729Sjoerg if (!Operand) {
27537330f729Sjoerg Out << "<null operand!>";
27547330f729Sjoerg return;
27557330f729Sjoerg }
27567330f729Sjoerg
27577330f729Sjoerg // Print the type
27587330f729Sjoerg TypePrinter.print(Operand->getType(), Out);
27597330f729Sjoerg // Print parameter attributes list
2760*82d56013Sjoerg if (Attrs.hasAttributes()) {
2761*82d56013Sjoerg Out << ' ';
2762*82d56013Sjoerg writeAttributeSet(Attrs);
2763*82d56013Sjoerg }
27647330f729Sjoerg Out << ' ';
27657330f729Sjoerg // Print the operand
27667330f729Sjoerg WriteAsOperandInternal(Out, Operand, &TypePrinter, &Machine, TheModule);
27677330f729Sjoerg }
27687330f729Sjoerg
writeOperandBundles(const CallBase * Call)27697330f729Sjoerg void AssemblyWriter::writeOperandBundles(const CallBase *Call) {
27707330f729Sjoerg if (!Call->hasOperandBundles())
27717330f729Sjoerg return;
27727330f729Sjoerg
27737330f729Sjoerg Out << " [ ";
27747330f729Sjoerg
27757330f729Sjoerg bool FirstBundle = true;
27767330f729Sjoerg for (unsigned i = 0, e = Call->getNumOperandBundles(); i != e; ++i) {
27777330f729Sjoerg OperandBundleUse BU = Call->getOperandBundleAt(i);
27787330f729Sjoerg
27797330f729Sjoerg if (!FirstBundle)
27807330f729Sjoerg Out << ", ";
27817330f729Sjoerg FirstBundle = false;
27827330f729Sjoerg
27837330f729Sjoerg Out << '"';
27847330f729Sjoerg printEscapedString(BU.getTagName(), Out);
27857330f729Sjoerg Out << '"';
27867330f729Sjoerg
27877330f729Sjoerg Out << '(';
27887330f729Sjoerg
27897330f729Sjoerg bool FirstInput = true;
27907330f729Sjoerg for (const auto &Input : BU.Inputs) {
27917330f729Sjoerg if (!FirstInput)
27927330f729Sjoerg Out << ", ";
27937330f729Sjoerg FirstInput = false;
27947330f729Sjoerg
27957330f729Sjoerg TypePrinter.print(Input->getType(), Out);
27967330f729Sjoerg Out << " ";
27977330f729Sjoerg WriteAsOperandInternal(Out, Input, &TypePrinter, &Machine, TheModule);
27987330f729Sjoerg }
27997330f729Sjoerg
28007330f729Sjoerg Out << ')';
28017330f729Sjoerg }
28027330f729Sjoerg
28037330f729Sjoerg Out << " ]";
28047330f729Sjoerg }
28057330f729Sjoerg
printModule(const Module * M)28067330f729Sjoerg void AssemblyWriter::printModule(const Module *M) {
28077330f729Sjoerg Machine.initializeIfNeeded();
28087330f729Sjoerg
28097330f729Sjoerg if (ShouldPreserveUseListOrder)
28107330f729Sjoerg UseListOrders = predictUseListOrder(M);
28117330f729Sjoerg
28127330f729Sjoerg if (!M->getModuleIdentifier().empty() &&
28137330f729Sjoerg // Don't print the ID if it will start a new line (which would
28147330f729Sjoerg // require a comment char before it).
28157330f729Sjoerg M->getModuleIdentifier().find('\n') == std::string::npos)
28167330f729Sjoerg Out << "; ModuleID = '" << M->getModuleIdentifier() << "'\n";
28177330f729Sjoerg
28187330f729Sjoerg if (!M->getSourceFileName().empty()) {
28197330f729Sjoerg Out << "source_filename = \"";
28207330f729Sjoerg printEscapedString(M->getSourceFileName(), Out);
28217330f729Sjoerg Out << "\"\n";
28227330f729Sjoerg }
28237330f729Sjoerg
28247330f729Sjoerg const std::string &DL = M->getDataLayoutStr();
28257330f729Sjoerg if (!DL.empty())
28267330f729Sjoerg Out << "target datalayout = \"" << DL << "\"\n";
28277330f729Sjoerg if (!M->getTargetTriple().empty())
28287330f729Sjoerg Out << "target triple = \"" << M->getTargetTriple() << "\"\n";
28297330f729Sjoerg
28307330f729Sjoerg if (!M->getModuleInlineAsm().empty()) {
28317330f729Sjoerg Out << '\n';
28327330f729Sjoerg
28337330f729Sjoerg // Split the string into lines, to make it easier to read the .ll file.
28347330f729Sjoerg StringRef Asm = M->getModuleInlineAsm();
28357330f729Sjoerg do {
28367330f729Sjoerg StringRef Front;
28377330f729Sjoerg std::tie(Front, Asm) = Asm.split('\n');
28387330f729Sjoerg
28397330f729Sjoerg // We found a newline, print the portion of the asm string from the
28407330f729Sjoerg // last newline up to this newline.
28417330f729Sjoerg Out << "module asm \"";
28427330f729Sjoerg printEscapedString(Front, Out);
28437330f729Sjoerg Out << "\"\n";
28447330f729Sjoerg } while (!Asm.empty());
28457330f729Sjoerg }
28467330f729Sjoerg
28477330f729Sjoerg printTypeIdentities();
28487330f729Sjoerg
28497330f729Sjoerg // Output all comdats.
28507330f729Sjoerg if (!Comdats.empty())
28517330f729Sjoerg Out << '\n';
28527330f729Sjoerg for (const Comdat *C : Comdats) {
28537330f729Sjoerg printComdat(C);
28547330f729Sjoerg if (C != Comdats.back())
28557330f729Sjoerg Out << '\n';
28567330f729Sjoerg }
28577330f729Sjoerg
28587330f729Sjoerg // Output all globals.
28597330f729Sjoerg if (!M->global_empty()) Out << '\n';
28607330f729Sjoerg for (const GlobalVariable &GV : M->globals()) {
28617330f729Sjoerg printGlobal(&GV); Out << '\n';
28627330f729Sjoerg }
28637330f729Sjoerg
28647330f729Sjoerg // Output all aliases.
28657330f729Sjoerg if (!M->alias_empty()) Out << "\n";
28667330f729Sjoerg for (const GlobalAlias &GA : M->aliases())
28677330f729Sjoerg printIndirectSymbol(&GA);
28687330f729Sjoerg
28697330f729Sjoerg // Output all ifuncs.
28707330f729Sjoerg if (!M->ifunc_empty()) Out << "\n";
28717330f729Sjoerg for (const GlobalIFunc &GI : M->ifuncs())
28727330f729Sjoerg printIndirectSymbol(&GI);
28737330f729Sjoerg
28747330f729Sjoerg // Output global use-lists.
28757330f729Sjoerg printUseLists(nullptr);
28767330f729Sjoerg
28777330f729Sjoerg // Output all of the functions.
2878*82d56013Sjoerg for (const Function &F : *M) {
2879*82d56013Sjoerg Out << '\n';
28807330f729Sjoerg printFunction(&F);
2881*82d56013Sjoerg }
28827330f729Sjoerg assert(UseListOrders.empty() && "All use-lists should have been consumed");
28837330f729Sjoerg
28847330f729Sjoerg // Output all attribute groups.
28857330f729Sjoerg if (!Machine.as_empty()) {
28867330f729Sjoerg Out << '\n';
28877330f729Sjoerg writeAllAttributeGroups();
28887330f729Sjoerg }
28897330f729Sjoerg
28907330f729Sjoerg // Output named metadata.
28917330f729Sjoerg if (!M->named_metadata_empty()) Out << '\n';
28927330f729Sjoerg
28937330f729Sjoerg for (const NamedMDNode &Node : M->named_metadata())
28947330f729Sjoerg printNamedMDNode(&Node);
28957330f729Sjoerg
28967330f729Sjoerg // Output metadata.
28977330f729Sjoerg if (!Machine.mdn_empty()) {
28987330f729Sjoerg Out << '\n';
28997330f729Sjoerg writeAllMDNodes();
29007330f729Sjoerg }
29017330f729Sjoerg }
29027330f729Sjoerg
printModuleSummaryIndex()29037330f729Sjoerg void AssemblyWriter::printModuleSummaryIndex() {
29047330f729Sjoerg assert(TheIndex);
2905*82d56013Sjoerg int NumSlots = Machine.initializeIndexIfNeeded();
29067330f729Sjoerg
29077330f729Sjoerg Out << "\n";
29087330f729Sjoerg
29097330f729Sjoerg // Print module path entries. To print in order, add paths to a vector
29107330f729Sjoerg // indexed by module slot.
29117330f729Sjoerg std::vector<std::pair<std::string, ModuleHash>> moduleVec;
2912*82d56013Sjoerg std::string RegularLTOModuleName =
2913*82d56013Sjoerg ModuleSummaryIndex::getRegularLTOModuleName();
29147330f729Sjoerg moduleVec.resize(TheIndex->modulePaths().size());
29157330f729Sjoerg for (auto &ModPath : TheIndex->modulePaths())
29167330f729Sjoerg moduleVec[Machine.getModulePathSlot(ModPath.first())] = std::make_pair(
29177330f729Sjoerg // A module id of -1 is a special entry for a regular LTO module created
29187330f729Sjoerg // during the thin link.
29197330f729Sjoerg ModPath.second.first == -1u ? RegularLTOModuleName
2920*82d56013Sjoerg : (std::string)std::string(ModPath.first()),
29217330f729Sjoerg ModPath.second.second);
29227330f729Sjoerg
29237330f729Sjoerg unsigned i = 0;
29247330f729Sjoerg for (auto &ModPair : moduleVec) {
29257330f729Sjoerg Out << "^" << i++ << " = module: (";
29267330f729Sjoerg Out << "path: \"";
29277330f729Sjoerg printEscapedString(ModPair.first, Out);
29287330f729Sjoerg Out << "\", hash: (";
29297330f729Sjoerg FieldSeparator FS;
29307330f729Sjoerg for (auto Hash : ModPair.second)
29317330f729Sjoerg Out << FS << Hash;
29327330f729Sjoerg Out << "))\n";
29337330f729Sjoerg }
29347330f729Sjoerg
29357330f729Sjoerg // FIXME: Change AliasSummary to hold a ValueInfo instead of summary pointer
29367330f729Sjoerg // for aliasee (then update BitcodeWriter.cpp and remove get/setAliaseeGUID).
29377330f729Sjoerg for (auto &GlobalList : *TheIndex) {
29387330f729Sjoerg auto GUID = GlobalList.first;
29397330f729Sjoerg for (auto &Summary : GlobalList.second.SummaryList)
29407330f729Sjoerg SummaryToGUIDMap[Summary.get()] = GUID;
29417330f729Sjoerg }
29427330f729Sjoerg
29437330f729Sjoerg // Print the global value summary entries.
29447330f729Sjoerg for (auto &GlobalList : *TheIndex) {
29457330f729Sjoerg auto GUID = GlobalList.first;
29467330f729Sjoerg auto VI = TheIndex->getValueInfo(GlobalList);
29477330f729Sjoerg printSummaryInfo(Machine.getGUIDSlot(GUID), VI);
29487330f729Sjoerg }
29497330f729Sjoerg
29507330f729Sjoerg // Print the TypeIdMap entries.
2951*82d56013Sjoerg for (const auto &TID : TheIndex->typeIds()) {
2952*82d56013Sjoerg Out << "^" << Machine.getTypeIdSlot(TID.second.first)
2953*82d56013Sjoerg << " = typeid: (name: \"" << TID.second.first << "\"";
2954*82d56013Sjoerg printTypeIdSummary(TID.second.second);
2955*82d56013Sjoerg Out << ") ; guid = " << TID.first << "\n";
29567330f729Sjoerg }
29577330f729Sjoerg
29587330f729Sjoerg // Print the TypeIdCompatibleVtableMap entries.
29597330f729Sjoerg for (auto &TId : TheIndex->typeIdCompatibleVtableMap()) {
29607330f729Sjoerg auto GUID = GlobalValue::getGUID(TId.first);
29617330f729Sjoerg Out << "^" << Machine.getGUIDSlot(GUID)
29627330f729Sjoerg << " = typeidCompatibleVTable: (name: \"" << TId.first << "\"";
29637330f729Sjoerg printTypeIdCompatibleVtableSummary(TId.second);
29647330f729Sjoerg Out << ") ; guid = " << GUID << "\n";
29657330f729Sjoerg }
2966*82d56013Sjoerg
2967*82d56013Sjoerg // Don't emit flags when it's not really needed (value is zero by default).
2968*82d56013Sjoerg if (TheIndex->getFlags()) {
2969*82d56013Sjoerg Out << "^" << NumSlots << " = flags: " << TheIndex->getFlags() << "\n";
2970*82d56013Sjoerg ++NumSlots;
2971*82d56013Sjoerg }
2972*82d56013Sjoerg
2973*82d56013Sjoerg Out << "^" << NumSlots << " = blockcount: " << TheIndex->getBlockCount()
2974*82d56013Sjoerg << "\n";
29757330f729Sjoerg }
29767330f729Sjoerg
29777330f729Sjoerg static const char *
getWholeProgDevirtResKindName(WholeProgramDevirtResolution::Kind K)29787330f729Sjoerg getWholeProgDevirtResKindName(WholeProgramDevirtResolution::Kind K) {
29797330f729Sjoerg switch (K) {
29807330f729Sjoerg case WholeProgramDevirtResolution::Indir:
29817330f729Sjoerg return "indir";
29827330f729Sjoerg case WholeProgramDevirtResolution::SingleImpl:
29837330f729Sjoerg return "singleImpl";
29847330f729Sjoerg case WholeProgramDevirtResolution::BranchFunnel:
29857330f729Sjoerg return "branchFunnel";
29867330f729Sjoerg }
29877330f729Sjoerg llvm_unreachable("invalid WholeProgramDevirtResolution kind");
29887330f729Sjoerg }
29897330f729Sjoerg
getWholeProgDevirtResByArgKindName(WholeProgramDevirtResolution::ByArg::Kind K)29907330f729Sjoerg static const char *getWholeProgDevirtResByArgKindName(
29917330f729Sjoerg WholeProgramDevirtResolution::ByArg::Kind K) {
29927330f729Sjoerg switch (K) {
29937330f729Sjoerg case WholeProgramDevirtResolution::ByArg::Indir:
29947330f729Sjoerg return "indir";
29957330f729Sjoerg case WholeProgramDevirtResolution::ByArg::UniformRetVal:
29967330f729Sjoerg return "uniformRetVal";
29977330f729Sjoerg case WholeProgramDevirtResolution::ByArg::UniqueRetVal:
29987330f729Sjoerg return "uniqueRetVal";
29997330f729Sjoerg case WholeProgramDevirtResolution::ByArg::VirtualConstProp:
30007330f729Sjoerg return "virtualConstProp";
30017330f729Sjoerg }
30027330f729Sjoerg llvm_unreachable("invalid WholeProgramDevirtResolution::ByArg kind");
30037330f729Sjoerg }
30047330f729Sjoerg
getTTResKindName(TypeTestResolution::Kind K)30057330f729Sjoerg static const char *getTTResKindName(TypeTestResolution::Kind K) {
30067330f729Sjoerg switch (K) {
3007*82d56013Sjoerg case TypeTestResolution::Unknown:
3008*82d56013Sjoerg return "unknown";
30097330f729Sjoerg case TypeTestResolution::Unsat:
30107330f729Sjoerg return "unsat";
30117330f729Sjoerg case TypeTestResolution::ByteArray:
30127330f729Sjoerg return "byteArray";
30137330f729Sjoerg case TypeTestResolution::Inline:
30147330f729Sjoerg return "inline";
30157330f729Sjoerg case TypeTestResolution::Single:
30167330f729Sjoerg return "single";
30177330f729Sjoerg case TypeTestResolution::AllOnes:
30187330f729Sjoerg return "allOnes";
30197330f729Sjoerg }
30207330f729Sjoerg llvm_unreachable("invalid TypeTestResolution kind");
30217330f729Sjoerg }
30227330f729Sjoerg
printTypeTestResolution(const TypeTestResolution & TTRes)30237330f729Sjoerg void AssemblyWriter::printTypeTestResolution(const TypeTestResolution &TTRes) {
30247330f729Sjoerg Out << "typeTestRes: (kind: " << getTTResKindName(TTRes.TheKind)
30257330f729Sjoerg << ", sizeM1BitWidth: " << TTRes.SizeM1BitWidth;
30267330f729Sjoerg
30277330f729Sjoerg // The following fields are only used if the target does not support the use
30287330f729Sjoerg // of absolute symbols to store constants. Print only if non-zero.
30297330f729Sjoerg if (TTRes.AlignLog2)
30307330f729Sjoerg Out << ", alignLog2: " << TTRes.AlignLog2;
30317330f729Sjoerg if (TTRes.SizeM1)
30327330f729Sjoerg Out << ", sizeM1: " << TTRes.SizeM1;
30337330f729Sjoerg if (TTRes.BitMask)
30347330f729Sjoerg // BitMask is uint8_t which causes it to print the corresponding char.
30357330f729Sjoerg Out << ", bitMask: " << (unsigned)TTRes.BitMask;
30367330f729Sjoerg if (TTRes.InlineBits)
30377330f729Sjoerg Out << ", inlineBits: " << TTRes.InlineBits;
30387330f729Sjoerg
30397330f729Sjoerg Out << ")";
30407330f729Sjoerg }
30417330f729Sjoerg
printTypeIdSummary(const TypeIdSummary & TIS)30427330f729Sjoerg void AssemblyWriter::printTypeIdSummary(const TypeIdSummary &TIS) {
30437330f729Sjoerg Out << ", summary: (";
30447330f729Sjoerg printTypeTestResolution(TIS.TTRes);
30457330f729Sjoerg if (!TIS.WPDRes.empty()) {
30467330f729Sjoerg Out << ", wpdResolutions: (";
30477330f729Sjoerg FieldSeparator FS;
30487330f729Sjoerg for (auto &WPDRes : TIS.WPDRes) {
30497330f729Sjoerg Out << FS;
30507330f729Sjoerg Out << "(offset: " << WPDRes.first << ", ";
30517330f729Sjoerg printWPDRes(WPDRes.second);
30527330f729Sjoerg Out << ")";
30537330f729Sjoerg }
30547330f729Sjoerg Out << ")";
30557330f729Sjoerg }
30567330f729Sjoerg Out << ")";
30577330f729Sjoerg }
30587330f729Sjoerg
printTypeIdCompatibleVtableSummary(const TypeIdCompatibleVtableInfo & TI)30597330f729Sjoerg void AssemblyWriter::printTypeIdCompatibleVtableSummary(
30607330f729Sjoerg const TypeIdCompatibleVtableInfo &TI) {
30617330f729Sjoerg Out << ", summary: (";
30627330f729Sjoerg FieldSeparator FS;
30637330f729Sjoerg for (auto &P : TI) {
30647330f729Sjoerg Out << FS;
30657330f729Sjoerg Out << "(offset: " << P.AddressPointOffset << ", ";
30667330f729Sjoerg Out << "^" << Machine.getGUIDSlot(P.VTableVI.getGUID());
30677330f729Sjoerg Out << ")";
30687330f729Sjoerg }
30697330f729Sjoerg Out << ")";
30707330f729Sjoerg }
30717330f729Sjoerg
printArgs(const std::vector<uint64_t> & Args)30727330f729Sjoerg void AssemblyWriter::printArgs(const std::vector<uint64_t> &Args) {
30737330f729Sjoerg Out << "args: (";
30747330f729Sjoerg FieldSeparator FS;
30757330f729Sjoerg for (auto arg : Args) {
30767330f729Sjoerg Out << FS;
30777330f729Sjoerg Out << arg;
30787330f729Sjoerg }
30797330f729Sjoerg Out << ")";
30807330f729Sjoerg }
30817330f729Sjoerg
printWPDRes(const WholeProgramDevirtResolution & WPDRes)30827330f729Sjoerg void AssemblyWriter::printWPDRes(const WholeProgramDevirtResolution &WPDRes) {
30837330f729Sjoerg Out << "wpdRes: (kind: ";
30847330f729Sjoerg Out << getWholeProgDevirtResKindName(WPDRes.TheKind);
30857330f729Sjoerg
30867330f729Sjoerg if (WPDRes.TheKind == WholeProgramDevirtResolution::SingleImpl)
30877330f729Sjoerg Out << ", singleImplName: \"" << WPDRes.SingleImplName << "\"";
30887330f729Sjoerg
30897330f729Sjoerg if (!WPDRes.ResByArg.empty()) {
30907330f729Sjoerg Out << ", resByArg: (";
30917330f729Sjoerg FieldSeparator FS;
30927330f729Sjoerg for (auto &ResByArg : WPDRes.ResByArg) {
30937330f729Sjoerg Out << FS;
30947330f729Sjoerg printArgs(ResByArg.first);
30957330f729Sjoerg Out << ", byArg: (kind: ";
30967330f729Sjoerg Out << getWholeProgDevirtResByArgKindName(ResByArg.second.TheKind);
30977330f729Sjoerg if (ResByArg.second.TheKind ==
30987330f729Sjoerg WholeProgramDevirtResolution::ByArg::UniformRetVal ||
30997330f729Sjoerg ResByArg.second.TheKind ==
31007330f729Sjoerg WholeProgramDevirtResolution::ByArg::UniqueRetVal)
31017330f729Sjoerg Out << ", info: " << ResByArg.second.Info;
31027330f729Sjoerg
31037330f729Sjoerg // The following fields are only used if the target does not support the
31047330f729Sjoerg // use of absolute symbols to store constants. Print only if non-zero.
31057330f729Sjoerg if (ResByArg.second.Byte || ResByArg.second.Bit)
31067330f729Sjoerg Out << ", byte: " << ResByArg.second.Byte
31077330f729Sjoerg << ", bit: " << ResByArg.second.Bit;
31087330f729Sjoerg
31097330f729Sjoerg Out << ")";
31107330f729Sjoerg }
31117330f729Sjoerg Out << ")";
31127330f729Sjoerg }
31137330f729Sjoerg Out << ")";
31147330f729Sjoerg }
31157330f729Sjoerg
getSummaryKindName(GlobalValueSummary::SummaryKind SK)31167330f729Sjoerg static const char *getSummaryKindName(GlobalValueSummary::SummaryKind SK) {
31177330f729Sjoerg switch (SK) {
31187330f729Sjoerg case GlobalValueSummary::AliasKind:
31197330f729Sjoerg return "alias";
31207330f729Sjoerg case GlobalValueSummary::FunctionKind:
31217330f729Sjoerg return "function";
31227330f729Sjoerg case GlobalValueSummary::GlobalVarKind:
31237330f729Sjoerg return "variable";
31247330f729Sjoerg }
31257330f729Sjoerg llvm_unreachable("invalid summary kind");
31267330f729Sjoerg }
31277330f729Sjoerg
printAliasSummary(const AliasSummary * AS)31287330f729Sjoerg void AssemblyWriter::printAliasSummary(const AliasSummary *AS) {
31297330f729Sjoerg Out << ", aliasee: ";
31307330f729Sjoerg // The indexes emitted for distributed backends may not include the
31317330f729Sjoerg // aliasee summary (only if it is being imported directly). Handle
31327330f729Sjoerg // that case by just emitting "null" as the aliasee.
31337330f729Sjoerg if (AS->hasAliasee())
31347330f729Sjoerg Out << "^" << Machine.getGUIDSlot(SummaryToGUIDMap[&AS->getAliasee()]);
31357330f729Sjoerg else
31367330f729Sjoerg Out << "null";
31377330f729Sjoerg }
31387330f729Sjoerg
printGlobalVarSummary(const GlobalVarSummary * GS)31397330f729Sjoerg void AssemblyWriter::printGlobalVarSummary(const GlobalVarSummary *GS) {
31407330f729Sjoerg auto VTableFuncs = GS->vTableFuncs();
3141*82d56013Sjoerg Out << ", varFlags: (readonly: " << GS->VarFlags.MaybeReadOnly << ", "
3142*82d56013Sjoerg << "writeonly: " << GS->VarFlags.MaybeWriteOnly << ", "
3143*82d56013Sjoerg << "constant: " << GS->VarFlags.Constant;
3144*82d56013Sjoerg if (!VTableFuncs.empty())
3145*82d56013Sjoerg Out << ", "
3146*82d56013Sjoerg << "vcall_visibility: " << GS->VarFlags.VCallVisibility;
3147*82d56013Sjoerg Out << ")";
3148*82d56013Sjoerg
31497330f729Sjoerg if (!VTableFuncs.empty()) {
31507330f729Sjoerg Out << ", vTableFuncs: (";
31517330f729Sjoerg FieldSeparator FS;
31527330f729Sjoerg for (auto &P : VTableFuncs) {
31537330f729Sjoerg Out << FS;
31547330f729Sjoerg Out << "(virtFunc: ^" << Machine.getGUIDSlot(P.FuncVI.getGUID())
31557330f729Sjoerg << ", offset: " << P.VTableOffset;
31567330f729Sjoerg Out << ")";
31577330f729Sjoerg }
31587330f729Sjoerg Out << ")";
31597330f729Sjoerg }
31607330f729Sjoerg }
31617330f729Sjoerg
getLinkageName(GlobalValue::LinkageTypes LT)31627330f729Sjoerg static std::string getLinkageName(GlobalValue::LinkageTypes LT) {
31637330f729Sjoerg switch (LT) {
31647330f729Sjoerg case GlobalValue::ExternalLinkage:
31657330f729Sjoerg return "external";
31667330f729Sjoerg case GlobalValue::PrivateLinkage:
31677330f729Sjoerg return "private";
31687330f729Sjoerg case GlobalValue::InternalLinkage:
31697330f729Sjoerg return "internal";
31707330f729Sjoerg case GlobalValue::LinkOnceAnyLinkage:
31717330f729Sjoerg return "linkonce";
31727330f729Sjoerg case GlobalValue::LinkOnceODRLinkage:
31737330f729Sjoerg return "linkonce_odr";
31747330f729Sjoerg case GlobalValue::WeakAnyLinkage:
31757330f729Sjoerg return "weak";
31767330f729Sjoerg case GlobalValue::WeakODRLinkage:
31777330f729Sjoerg return "weak_odr";
31787330f729Sjoerg case GlobalValue::CommonLinkage:
31797330f729Sjoerg return "common";
31807330f729Sjoerg case GlobalValue::AppendingLinkage:
31817330f729Sjoerg return "appending";
31827330f729Sjoerg case GlobalValue::ExternalWeakLinkage:
31837330f729Sjoerg return "extern_weak";
31847330f729Sjoerg case GlobalValue::AvailableExternallyLinkage:
31857330f729Sjoerg return "available_externally";
31867330f729Sjoerg }
31877330f729Sjoerg llvm_unreachable("invalid linkage");
31887330f729Sjoerg }
31897330f729Sjoerg
31907330f729Sjoerg // When printing the linkage types in IR where the ExternalLinkage is
31917330f729Sjoerg // not printed, and other linkage types are expected to be printed with
31927330f729Sjoerg // a space after the name.
getLinkageNameWithSpace(GlobalValue::LinkageTypes LT)31937330f729Sjoerg static std::string getLinkageNameWithSpace(GlobalValue::LinkageTypes LT) {
31947330f729Sjoerg if (LT == GlobalValue::ExternalLinkage)
31957330f729Sjoerg return "";
31967330f729Sjoerg return getLinkageName(LT) + " ";
31977330f729Sjoerg }
31987330f729Sjoerg
getVisibilityName(GlobalValue::VisibilityTypes Vis)3199*82d56013Sjoerg static const char *getVisibilityName(GlobalValue::VisibilityTypes Vis) {
3200*82d56013Sjoerg switch (Vis) {
3201*82d56013Sjoerg case GlobalValue::DefaultVisibility:
3202*82d56013Sjoerg return "default";
3203*82d56013Sjoerg case GlobalValue::HiddenVisibility:
3204*82d56013Sjoerg return "hidden";
3205*82d56013Sjoerg case GlobalValue::ProtectedVisibility:
3206*82d56013Sjoerg return "protected";
3207*82d56013Sjoerg }
3208*82d56013Sjoerg llvm_unreachable("invalid visibility");
3209*82d56013Sjoerg }
3210*82d56013Sjoerg
printFunctionSummary(const FunctionSummary * FS)32117330f729Sjoerg void AssemblyWriter::printFunctionSummary(const FunctionSummary *FS) {
32127330f729Sjoerg Out << ", insts: " << FS->instCount();
32137330f729Sjoerg
32147330f729Sjoerg FunctionSummary::FFlags FFlags = FS->fflags();
32157330f729Sjoerg if (FFlags.ReadNone | FFlags.ReadOnly | FFlags.NoRecurse |
3216*82d56013Sjoerg FFlags.ReturnDoesNotAlias | FFlags.NoInline | FFlags.AlwaysInline) {
32177330f729Sjoerg Out << ", funcFlags: (";
32187330f729Sjoerg Out << "readNone: " << FFlags.ReadNone;
32197330f729Sjoerg Out << ", readOnly: " << FFlags.ReadOnly;
32207330f729Sjoerg Out << ", noRecurse: " << FFlags.NoRecurse;
32217330f729Sjoerg Out << ", returnDoesNotAlias: " << FFlags.ReturnDoesNotAlias;
32227330f729Sjoerg Out << ", noInline: " << FFlags.NoInline;
3223*82d56013Sjoerg Out << ", alwaysInline: " << FFlags.AlwaysInline;
32247330f729Sjoerg Out << ")";
32257330f729Sjoerg }
32267330f729Sjoerg if (!FS->calls().empty()) {
32277330f729Sjoerg Out << ", calls: (";
32287330f729Sjoerg FieldSeparator IFS;
32297330f729Sjoerg for (auto &Call : FS->calls()) {
32307330f729Sjoerg Out << IFS;
32317330f729Sjoerg Out << "(callee: ^" << Machine.getGUIDSlot(Call.first.getGUID());
32327330f729Sjoerg if (Call.second.getHotness() != CalleeInfo::HotnessType::Unknown)
32337330f729Sjoerg Out << ", hotness: " << getHotnessName(Call.second.getHotness());
32347330f729Sjoerg else if (Call.second.RelBlockFreq)
32357330f729Sjoerg Out << ", relbf: " << Call.second.RelBlockFreq;
32367330f729Sjoerg Out << ")";
32377330f729Sjoerg }
32387330f729Sjoerg Out << ")";
32397330f729Sjoerg }
32407330f729Sjoerg
32417330f729Sjoerg if (const auto *TIdInfo = FS->getTypeIdInfo())
32427330f729Sjoerg printTypeIdInfo(*TIdInfo);
3243*82d56013Sjoerg
3244*82d56013Sjoerg auto PrintRange = [&](const ConstantRange &Range) {
3245*82d56013Sjoerg Out << "[" << Range.getSignedMin() << ", " << Range.getSignedMax() << "]";
3246*82d56013Sjoerg };
3247*82d56013Sjoerg
3248*82d56013Sjoerg if (!FS->paramAccesses().empty()) {
3249*82d56013Sjoerg Out << ", params: (";
3250*82d56013Sjoerg FieldSeparator IFS;
3251*82d56013Sjoerg for (auto &PS : FS->paramAccesses()) {
3252*82d56013Sjoerg Out << IFS;
3253*82d56013Sjoerg Out << "(param: " << PS.ParamNo;
3254*82d56013Sjoerg Out << ", offset: ";
3255*82d56013Sjoerg PrintRange(PS.Use);
3256*82d56013Sjoerg if (!PS.Calls.empty()) {
3257*82d56013Sjoerg Out << ", calls: (";
3258*82d56013Sjoerg FieldSeparator IFS;
3259*82d56013Sjoerg for (auto &Call : PS.Calls) {
3260*82d56013Sjoerg Out << IFS;
3261*82d56013Sjoerg Out << "(callee: ^" << Machine.getGUIDSlot(Call.Callee.getGUID());
3262*82d56013Sjoerg Out << ", param: " << Call.ParamNo;
3263*82d56013Sjoerg Out << ", offset: ";
3264*82d56013Sjoerg PrintRange(Call.Offsets);
3265*82d56013Sjoerg Out << ")";
3266*82d56013Sjoerg }
3267*82d56013Sjoerg Out << ")";
3268*82d56013Sjoerg }
3269*82d56013Sjoerg Out << ")";
3270*82d56013Sjoerg }
3271*82d56013Sjoerg Out << ")";
3272*82d56013Sjoerg }
32737330f729Sjoerg }
32747330f729Sjoerg
printTypeIdInfo(const FunctionSummary::TypeIdInfo & TIDInfo)32757330f729Sjoerg void AssemblyWriter::printTypeIdInfo(
32767330f729Sjoerg const FunctionSummary::TypeIdInfo &TIDInfo) {
32777330f729Sjoerg Out << ", typeIdInfo: (";
32787330f729Sjoerg FieldSeparator TIDFS;
32797330f729Sjoerg if (!TIDInfo.TypeTests.empty()) {
32807330f729Sjoerg Out << TIDFS;
32817330f729Sjoerg Out << "typeTests: (";
32827330f729Sjoerg FieldSeparator FS;
32837330f729Sjoerg for (auto &GUID : TIDInfo.TypeTests) {
32847330f729Sjoerg auto TidIter = TheIndex->typeIds().equal_range(GUID);
32857330f729Sjoerg if (TidIter.first == TidIter.second) {
32867330f729Sjoerg Out << FS;
32877330f729Sjoerg Out << GUID;
32887330f729Sjoerg continue;
32897330f729Sjoerg }
32907330f729Sjoerg // Print all type id that correspond to this GUID.
32917330f729Sjoerg for (auto It = TidIter.first; It != TidIter.second; ++It) {
32927330f729Sjoerg Out << FS;
32937330f729Sjoerg auto Slot = Machine.getTypeIdSlot(It->second.first);
32947330f729Sjoerg assert(Slot != -1);
32957330f729Sjoerg Out << "^" << Slot;
32967330f729Sjoerg }
32977330f729Sjoerg }
32987330f729Sjoerg Out << ")";
32997330f729Sjoerg }
33007330f729Sjoerg if (!TIDInfo.TypeTestAssumeVCalls.empty()) {
33017330f729Sjoerg Out << TIDFS;
33027330f729Sjoerg printNonConstVCalls(TIDInfo.TypeTestAssumeVCalls, "typeTestAssumeVCalls");
33037330f729Sjoerg }
33047330f729Sjoerg if (!TIDInfo.TypeCheckedLoadVCalls.empty()) {
33057330f729Sjoerg Out << TIDFS;
33067330f729Sjoerg printNonConstVCalls(TIDInfo.TypeCheckedLoadVCalls, "typeCheckedLoadVCalls");
33077330f729Sjoerg }
33087330f729Sjoerg if (!TIDInfo.TypeTestAssumeConstVCalls.empty()) {
33097330f729Sjoerg Out << TIDFS;
33107330f729Sjoerg printConstVCalls(TIDInfo.TypeTestAssumeConstVCalls,
33117330f729Sjoerg "typeTestAssumeConstVCalls");
33127330f729Sjoerg }
33137330f729Sjoerg if (!TIDInfo.TypeCheckedLoadConstVCalls.empty()) {
33147330f729Sjoerg Out << TIDFS;
33157330f729Sjoerg printConstVCalls(TIDInfo.TypeCheckedLoadConstVCalls,
33167330f729Sjoerg "typeCheckedLoadConstVCalls");
33177330f729Sjoerg }
33187330f729Sjoerg Out << ")";
33197330f729Sjoerg }
33207330f729Sjoerg
printVFuncId(const FunctionSummary::VFuncId VFId)33217330f729Sjoerg void AssemblyWriter::printVFuncId(const FunctionSummary::VFuncId VFId) {
33227330f729Sjoerg auto TidIter = TheIndex->typeIds().equal_range(VFId.GUID);
33237330f729Sjoerg if (TidIter.first == TidIter.second) {
33247330f729Sjoerg Out << "vFuncId: (";
33257330f729Sjoerg Out << "guid: " << VFId.GUID;
33267330f729Sjoerg Out << ", offset: " << VFId.Offset;
33277330f729Sjoerg Out << ")";
33287330f729Sjoerg return;
33297330f729Sjoerg }
33307330f729Sjoerg // Print all type id that correspond to this GUID.
33317330f729Sjoerg FieldSeparator FS;
33327330f729Sjoerg for (auto It = TidIter.first; It != TidIter.second; ++It) {
33337330f729Sjoerg Out << FS;
33347330f729Sjoerg Out << "vFuncId: (";
33357330f729Sjoerg auto Slot = Machine.getTypeIdSlot(It->second.first);
33367330f729Sjoerg assert(Slot != -1);
33377330f729Sjoerg Out << "^" << Slot;
33387330f729Sjoerg Out << ", offset: " << VFId.Offset;
33397330f729Sjoerg Out << ")";
33407330f729Sjoerg }
33417330f729Sjoerg }
33427330f729Sjoerg
printNonConstVCalls(const std::vector<FunctionSummary::VFuncId> & VCallList,const char * Tag)33437330f729Sjoerg void AssemblyWriter::printNonConstVCalls(
3344*82d56013Sjoerg const std::vector<FunctionSummary::VFuncId> &VCallList, const char *Tag) {
33457330f729Sjoerg Out << Tag << ": (";
33467330f729Sjoerg FieldSeparator FS;
33477330f729Sjoerg for (auto &VFuncId : VCallList) {
33487330f729Sjoerg Out << FS;
33497330f729Sjoerg printVFuncId(VFuncId);
33507330f729Sjoerg }
33517330f729Sjoerg Out << ")";
33527330f729Sjoerg }
33537330f729Sjoerg
printConstVCalls(const std::vector<FunctionSummary::ConstVCall> & VCallList,const char * Tag)33547330f729Sjoerg void AssemblyWriter::printConstVCalls(
3355*82d56013Sjoerg const std::vector<FunctionSummary::ConstVCall> &VCallList,
3356*82d56013Sjoerg const char *Tag) {
33577330f729Sjoerg Out << Tag << ": (";
33587330f729Sjoerg FieldSeparator FS;
33597330f729Sjoerg for (auto &ConstVCall : VCallList) {
33607330f729Sjoerg Out << FS;
33617330f729Sjoerg Out << "(";
33627330f729Sjoerg printVFuncId(ConstVCall.VFunc);
33637330f729Sjoerg if (!ConstVCall.Args.empty()) {
33647330f729Sjoerg Out << ", ";
33657330f729Sjoerg printArgs(ConstVCall.Args);
33667330f729Sjoerg }
33677330f729Sjoerg Out << ")";
33687330f729Sjoerg }
33697330f729Sjoerg Out << ")";
33707330f729Sjoerg }
33717330f729Sjoerg
printSummary(const GlobalValueSummary & Summary)33727330f729Sjoerg void AssemblyWriter::printSummary(const GlobalValueSummary &Summary) {
33737330f729Sjoerg GlobalValueSummary::GVFlags GVFlags = Summary.flags();
33747330f729Sjoerg GlobalValue::LinkageTypes LT = (GlobalValue::LinkageTypes)GVFlags.Linkage;
33757330f729Sjoerg Out << getSummaryKindName(Summary.getSummaryKind()) << ": ";
33767330f729Sjoerg Out << "(module: ^" << Machine.getModulePathSlot(Summary.modulePath())
33777330f729Sjoerg << ", flags: (";
33787330f729Sjoerg Out << "linkage: " << getLinkageName(LT);
3379*82d56013Sjoerg Out << ", visibility: "
3380*82d56013Sjoerg << getVisibilityName((GlobalValue::VisibilityTypes)GVFlags.Visibility);
33817330f729Sjoerg Out << ", notEligibleToImport: " << GVFlags.NotEligibleToImport;
33827330f729Sjoerg Out << ", live: " << GVFlags.Live;
33837330f729Sjoerg Out << ", dsoLocal: " << GVFlags.DSOLocal;
33847330f729Sjoerg Out << ", canAutoHide: " << GVFlags.CanAutoHide;
33857330f729Sjoerg Out << ")";
33867330f729Sjoerg
33877330f729Sjoerg if (Summary.getSummaryKind() == GlobalValueSummary::AliasKind)
33887330f729Sjoerg printAliasSummary(cast<AliasSummary>(&Summary));
33897330f729Sjoerg else if (Summary.getSummaryKind() == GlobalValueSummary::FunctionKind)
33907330f729Sjoerg printFunctionSummary(cast<FunctionSummary>(&Summary));
33917330f729Sjoerg else
33927330f729Sjoerg printGlobalVarSummary(cast<GlobalVarSummary>(&Summary));
33937330f729Sjoerg
33947330f729Sjoerg auto RefList = Summary.refs();
33957330f729Sjoerg if (!RefList.empty()) {
33967330f729Sjoerg Out << ", refs: (";
33977330f729Sjoerg FieldSeparator FS;
33987330f729Sjoerg for (auto &Ref : RefList) {
33997330f729Sjoerg Out << FS;
34007330f729Sjoerg if (Ref.isReadOnly())
34017330f729Sjoerg Out << "readonly ";
34027330f729Sjoerg else if (Ref.isWriteOnly())
34037330f729Sjoerg Out << "writeonly ";
34047330f729Sjoerg Out << "^" << Machine.getGUIDSlot(Ref.getGUID());
34057330f729Sjoerg }
34067330f729Sjoerg Out << ")";
34077330f729Sjoerg }
34087330f729Sjoerg
34097330f729Sjoerg Out << ")";
34107330f729Sjoerg }
34117330f729Sjoerg
printSummaryInfo(unsigned Slot,const ValueInfo & VI)34127330f729Sjoerg void AssemblyWriter::printSummaryInfo(unsigned Slot, const ValueInfo &VI) {
34137330f729Sjoerg Out << "^" << Slot << " = gv: (";
34147330f729Sjoerg if (!VI.name().empty())
34157330f729Sjoerg Out << "name: \"" << VI.name() << "\"";
34167330f729Sjoerg else
34177330f729Sjoerg Out << "guid: " << VI.getGUID();
34187330f729Sjoerg if (!VI.getSummaryList().empty()) {
34197330f729Sjoerg Out << ", summaries: (";
34207330f729Sjoerg FieldSeparator FS;
34217330f729Sjoerg for (auto &Summary : VI.getSummaryList()) {
34227330f729Sjoerg Out << FS;
34237330f729Sjoerg printSummary(*Summary);
34247330f729Sjoerg }
34257330f729Sjoerg Out << ")";
34267330f729Sjoerg }
34277330f729Sjoerg Out << ")";
34287330f729Sjoerg if (!VI.name().empty())
34297330f729Sjoerg Out << " ; guid = " << VI.getGUID();
34307330f729Sjoerg Out << "\n";
34317330f729Sjoerg }
34327330f729Sjoerg
printMetadataIdentifier(StringRef Name,formatted_raw_ostream & Out)34337330f729Sjoerg static void printMetadataIdentifier(StringRef Name,
34347330f729Sjoerg formatted_raw_ostream &Out) {
34357330f729Sjoerg if (Name.empty()) {
34367330f729Sjoerg Out << "<empty name> ";
34377330f729Sjoerg } else {
34387330f729Sjoerg if (isalpha(static_cast<unsigned char>(Name[0])) || Name[0] == '-' ||
34397330f729Sjoerg Name[0] == '$' || Name[0] == '.' || Name[0] == '_')
34407330f729Sjoerg Out << Name[0];
34417330f729Sjoerg else
34427330f729Sjoerg Out << '\\' << hexdigit(Name[0] >> 4) << hexdigit(Name[0] & 0x0F);
34437330f729Sjoerg for (unsigned i = 1, e = Name.size(); i != e; ++i) {
34447330f729Sjoerg unsigned char C = Name[i];
34457330f729Sjoerg if (isalnum(static_cast<unsigned char>(C)) || C == '-' || C == '$' ||
34467330f729Sjoerg C == '.' || C == '_')
34477330f729Sjoerg Out << C;
34487330f729Sjoerg else
34497330f729Sjoerg Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
34507330f729Sjoerg }
34517330f729Sjoerg }
34527330f729Sjoerg }
34537330f729Sjoerg
printNamedMDNode(const NamedMDNode * NMD)34547330f729Sjoerg void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) {
34557330f729Sjoerg Out << '!';
34567330f729Sjoerg printMetadataIdentifier(NMD->getName(), Out);
34577330f729Sjoerg Out << " = !{";
34587330f729Sjoerg for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
34597330f729Sjoerg if (i)
34607330f729Sjoerg Out << ", ";
34617330f729Sjoerg
34627330f729Sjoerg // Write DIExpressions inline.
34637330f729Sjoerg // FIXME: Ban DIExpressions in NamedMDNodes, they will serve no purpose.
34647330f729Sjoerg MDNode *Op = NMD->getOperand(i);
3465*82d56013Sjoerg assert(!isa<DIArgList>(Op) &&
3466*82d56013Sjoerg "DIArgLists should not appear in NamedMDNodes");
34677330f729Sjoerg if (auto *Expr = dyn_cast<DIExpression>(Op)) {
34687330f729Sjoerg writeDIExpression(Out, Expr, nullptr, nullptr, nullptr);
34697330f729Sjoerg continue;
34707330f729Sjoerg }
34717330f729Sjoerg
34727330f729Sjoerg int Slot = Machine.getMetadataSlot(Op);
34737330f729Sjoerg if (Slot == -1)
34747330f729Sjoerg Out << "<badref>";
34757330f729Sjoerg else
34767330f729Sjoerg Out << '!' << Slot;
34777330f729Sjoerg }
34787330f729Sjoerg Out << "}\n";
34797330f729Sjoerg }
34807330f729Sjoerg
PrintVisibility(GlobalValue::VisibilityTypes Vis,formatted_raw_ostream & Out)34817330f729Sjoerg static void PrintVisibility(GlobalValue::VisibilityTypes Vis,
34827330f729Sjoerg formatted_raw_ostream &Out) {
34837330f729Sjoerg switch (Vis) {
34847330f729Sjoerg case GlobalValue::DefaultVisibility: break;
34857330f729Sjoerg case GlobalValue::HiddenVisibility: Out << "hidden "; break;
34867330f729Sjoerg case GlobalValue::ProtectedVisibility: Out << "protected "; break;
34877330f729Sjoerg }
34887330f729Sjoerg }
34897330f729Sjoerg
PrintDSOLocation(const GlobalValue & GV,formatted_raw_ostream & Out)34907330f729Sjoerg static void PrintDSOLocation(const GlobalValue &GV,
34917330f729Sjoerg formatted_raw_ostream &Out) {
3492*82d56013Sjoerg if (GV.isDSOLocal() && !GV.isImplicitDSOLocal())
34937330f729Sjoerg Out << "dso_local ";
34947330f729Sjoerg }
34957330f729Sjoerg
PrintDLLStorageClass(GlobalValue::DLLStorageClassTypes SCT,formatted_raw_ostream & Out)34967330f729Sjoerg static void PrintDLLStorageClass(GlobalValue::DLLStorageClassTypes SCT,
34977330f729Sjoerg formatted_raw_ostream &Out) {
34987330f729Sjoerg switch (SCT) {
34997330f729Sjoerg case GlobalValue::DefaultStorageClass: break;
35007330f729Sjoerg case GlobalValue::DLLImportStorageClass: Out << "dllimport "; break;
35017330f729Sjoerg case GlobalValue::DLLExportStorageClass: Out << "dllexport "; break;
35027330f729Sjoerg }
35037330f729Sjoerg }
35047330f729Sjoerg
PrintThreadLocalModel(GlobalVariable::ThreadLocalMode TLM,formatted_raw_ostream & Out)35057330f729Sjoerg static void PrintThreadLocalModel(GlobalVariable::ThreadLocalMode TLM,
35067330f729Sjoerg formatted_raw_ostream &Out) {
35077330f729Sjoerg switch (TLM) {
35087330f729Sjoerg case GlobalVariable::NotThreadLocal:
35097330f729Sjoerg break;
35107330f729Sjoerg case GlobalVariable::GeneralDynamicTLSModel:
35117330f729Sjoerg Out << "thread_local ";
35127330f729Sjoerg break;
35137330f729Sjoerg case GlobalVariable::LocalDynamicTLSModel:
35147330f729Sjoerg Out << "thread_local(localdynamic) ";
35157330f729Sjoerg break;
35167330f729Sjoerg case GlobalVariable::InitialExecTLSModel:
35177330f729Sjoerg Out << "thread_local(initialexec) ";
35187330f729Sjoerg break;
35197330f729Sjoerg case GlobalVariable::LocalExecTLSModel:
35207330f729Sjoerg Out << "thread_local(localexec) ";
35217330f729Sjoerg break;
35227330f729Sjoerg }
35237330f729Sjoerg }
35247330f729Sjoerg
getUnnamedAddrEncoding(GlobalVariable::UnnamedAddr UA)35257330f729Sjoerg static StringRef getUnnamedAddrEncoding(GlobalVariable::UnnamedAddr UA) {
35267330f729Sjoerg switch (UA) {
35277330f729Sjoerg case GlobalVariable::UnnamedAddr::None:
35287330f729Sjoerg return "";
35297330f729Sjoerg case GlobalVariable::UnnamedAddr::Local:
35307330f729Sjoerg return "local_unnamed_addr";
35317330f729Sjoerg case GlobalVariable::UnnamedAddr::Global:
35327330f729Sjoerg return "unnamed_addr";
35337330f729Sjoerg }
35347330f729Sjoerg llvm_unreachable("Unknown UnnamedAddr");
35357330f729Sjoerg }
35367330f729Sjoerg
maybePrintComdat(formatted_raw_ostream & Out,const GlobalObject & GO)35377330f729Sjoerg static void maybePrintComdat(formatted_raw_ostream &Out,
35387330f729Sjoerg const GlobalObject &GO) {
35397330f729Sjoerg const Comdat *C = GO.getComdat();
35407330f729Sjoerg if (!C)
35417330f729Sjoerg return;
35427330f729Sjoerg
35437330f729Sjoerg if (isa<GlobalVariable>(GO))
35447330f729Sjoerg Out << ',';
35457330f729Sjoerg Out << " comdat";
35467330f729Sjoerg
35477330f729Sjoerg if (GO.getName() == C->getName())
35487330f729Sjoerg return;
35497330f729Sjoerg
35507330f729Sjoerg Out << '(';
35517330f729Sjoerg PrintLLVMName(Out, C->getName(), ComdatPrefix);
35527330f729Sjoerg Out << ')';
35537330f729Sjoerg }
35547330f729Sjoerg
printGlobal(const GlobalVariable * GV)35557330f729Sjoerg void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
35567330f729Sjoerg if (GV->isMaterializable())
35577330f729Sjoerg Out << "; Materializable\n";
35587330f729Sjoerg
35597330f729Sjoerg WriteAsOperandInternal(Out, GV, &TypePrinter, &Machine, GV->getParent());
35607330f729Sjoerg Out << " = ";
35617330f729Sjoerg
35627330f729Sjoerg if (!GV->hasInitializer() && GV->hasExternalLinkage())
35637330f729Sjoerg Out << "external ";
35647330f729Sjoerg
35657330f729Sjoerg Out << getLinkageNameWithSpace(GV->getLinkage());
35667330f729Sjoerg PrintDSOLocation(*GV, Out);
35677330f729Sjoerg PrintVisibility(GV->getVisibility(), Out);
35687330f729Sjoerg PrintDLLStorageClass(GV->getDLLStorageClass(), Out);
35697330f729Sjoerg PrintThreadLocalModel(GV->getThreadLocalMode(), Out);
35707330f729Sjoerg StringRef UA = getUnnamedAddrEncoding(GV->getUnnamedAddr());
35717330f729Sjoerg if (!UA.empty())
35727330f729Sjoerg Out << UA << ' ';
35737330f729Sjoerg
35747330f729Sjoerg if (unsigned AddressSpace = GV->getType()->getAddressSpace())
35757330f729Sjoerg Out << "addrspace(" << AddressSpace << ") ";
35767330f729Sjoerg if (GV->isExternallyInitialized()) Out << "externally_initialized ";
35777330f729Sjoerg Out << (GV->isConstant() ? "constant " : "global ");
35787330f729Sjoerg TypePrinter.print(GV->getValueType(), Out);
35797330f729Sjoerg
35807330f729Sjoerg if (GV->hasInitializer()) {
35817330f729Sjoerg Out << ' ';
35827330f729Sjoerg writeOperand(GV->getInitializer(), false);
35837330f729Sjoerg }
35847330f729Sjoerg
35857330f729Sjoerg if (GV->hasSection()) {
35867330f729Sjoerg Out << ", section \"";
35877330f729Sjoerg printEscapedString(GV->getSection(), Out);
35887330f729Sjoerg Out << '"';
35897330f729Sjoerg }
35907330f729Sjoerg if (GV->hasPartition()) {
35917330f729Sjoerg Out << ", partition \"";
35927330f729Sjoerg printEscapedString(GV->getPartition(), Out);
35937330f729Sjoerg Out << '"';
35947330f729Sjoerg }
35957330f729Sjoerg
35967330f729Sjoerg maybePrintComdat(Out, *GV);
35977330f729Sjoerg if (GV->getAlignment())
35987330f729Sjoerg Out << ", align " << GV->getAlignment();
35997330f729Sjoerg
36007330f729Sjoerg SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
36017330f729Sjoerg GV->getAllMetadata(MDs);
36027330f729Sjoerg printMetadataAttachments(MDs, ", ");
36037330f729Sjoerg
36047330f729Sjoerg auto Attrs = GV->getAttributes();
36057330f729Sjoerg if (Attrs.hasAttributes())
36067330f729Sjoerg Out << " #" << Machine.getAttributeGroupSlot(Attrs);
36077330f729Sjoerg
36087330f729Sjoerg printInfoComment(*GV);
36097330f729Sjoerg }
36107330f729Sjoerg
printIndirectSymbol(const GlobalIndirectSymbol * GIS)36117330f729Sjoerg void AssemblyWriter::printIndirectSymbol(const GlobalIndirectSymbol *GIS) {
36127330f729Sjoerg if (GIS->isMaterializable())
36137330f729Sjoerg Out << "; Materializable\n";
36147330f729Sjoerg
36157330f729Sjoerg WriteAsOperandInternal(Out, GIS, &TypePrinter, &Machine, GIS->getParent());
36167330f729Sjoerg Out << " = ";
36177330f729Sjoerg
36187330f729Sjoerg Out << getLinkageNameWithSpace(GIS->getLinkage());
36197330f729Sjoerg PrintDSOLocation(*GIS, Out);
36207330f729Sjoerg PrintVisibility(GIS->getVisibility(), Out);
36217330f729Sjoerg PrintDLLStorageClass(GIS->getDLLStorageClass(), Out);
36227330f729Sjoerg PrintThreadLocalModel(GIS->getThreadLocalMode(), Out);
36237330f729Sjoerg StringRef UA = getUnnamedAddrEncoding(GIS->getUnnamedAddr());
36247330f729Sjoerg if (!UA.empty())
36257330f729Sjoerg Out << UA << ' ';
36267330f729Sjoerg
36277330f729Sjoerg if (isa<GlobalAlias>(GIS))
36287330f729Sjoerg Out << "alias ";
36297330f729Sjoerg else if (isa<GlobalIFunc>(GIS))
36307330f729Sjoerg Out << "ifunc ";
36317330f729Sjoerg else
36327330f729Sjoerg llvm_unreachable("Not an alias or ifunc!");
36337330f729Sjoerg
36347330f729Sjoerg TypePrinter.print(GIS->getValueType(), Out);
36357330f729Sjoerg
36367330f729Sjoerg Out << ", ";
36377330f729Sjoerg
36387330f729Sjoerg const Constant *IS = GIS->getIndirectSymbol();
36397330f729Sjoerg
36407330f729Sjoerg if (!IS) {
36417330f729Sjoerg TypePrinter.print(GIS->getType(), Out);
36427330f729Sjoerg Out << " <<NULL ALIASEE>>";
36437330f729Sjoerg } else {
36447330f729Sjoerg writeOperand(IS, !isa<ConstantExpr>(IS));
36457330f729Sjoerg }
36467330f729Sjoerg
36477330f729Sjoerg if (GIS->hasPartition()) {
36487330f729Sjoerg Out << ", partition \"";
36497330f729Sjoerg printEscapedString(GIS->getPartition(), Out);
36507330f729Sjoerg Out << '"';
36517330f729Sjoerg }
36527330f729Sjoerg
36537330f729Sjoerg printInfoComment(*GIS);
36547330f729Sjoerg Out << '\n';
36557330f729Sjoerg }
36567330f729Sjoerg
printComdat(const Comdat * C)36577330f729Sjoerg void AssemblyWriter::printComdat(const Comdat *C) {
36587330f729Sjoerg C->print(Out);
36597330f729Sjoerg }
36607330f729Sjoerg
printTypeIdentities()36617330f729Sjoerg void AssemblyWriter::printTypeIdentities() {
36627330f729Sjoerg if (TypePrinter.empty())
36637330f729Sjoerg return;
36647330f729Sjoerg
36657330f729Sjoerg Out << '\n';
36667330f729Sjoerg
36677330f729Sjoerg // Emit all numbered types.
36687330f729Sjoerg auto &NumberedTypes = TypePrinter.getNumberedTypes();
36697330f729Sjoerg for (unsigned I = 0, E = NumberedTypes.size(); I != E; ++I) {
36707330f729Sjoerg Out << '%' << I << " = type ";
36717330f729Sjoerg
36727330f729Sjoerg // Make sure we print out at least one level of the type structure, so
36737330f729Sjoerg // that we do not get %2 = type %2
36747330f729Sjoerg TypePrinter.printStructBody(NumberedTypes[I], Out);
36757330f729Sjoerg Out << '\n';
36767330f729Sjoerg }
36777330f729Sjoerg
36787330f729Sjoerg auto &NamedTypes = TypePrinter.getNamedTypes();
36797330f729Sjoerg for (unsigned I = 0, E = NamedTypes.size(); I != E; ++I) {
36807330f729Sjoerg PrintLLVMName(Out, NamedTypes[I]->getName(), LocalPrefix);
36817330f729Sjoerg Out << " = type ";
36827330f729Sjoerg
36837330f729Sjoerg // Make sure we print out at least one level of the type structure, so
36847330f729Sjoerg // that we do not get %FILE = type %FILE
36857330f729Sjoerg TypePrinter.printStructBody(NamedTypes[I], Out);
36867330f729Sjoerg Out << '\n';
36877330f729Sjoerg }
36887330f729Sjoerg }
36897330f729Sjoerg
36907330f729Sjoerg /// printFunction - Print all aspects of a function.
printFunction(const Function * F)36917330f729Sjoerg void AssemblyWriter::printFunction(const Function *F) {
36927330f729Sjoerg if (AnnotationWriter) AnnotationWriter->emitFunctionAnnot(F, Out);
36937330f729Sjoerg
36947330f729Sjoerg if (F->isMaterializable())
36957330f729Sjoerg Out << "; Materializable\n";
36967330f729Sjoerg
36977330f729Sjoerg const AttributeList &Attrs = F->getAttributes();
36987330f729Sjoerg if (Attrs.hasAttributes(AttributeList::FunctionIndex)) {
36997330f729Sjoerg AttributeSet AS = Attrs.getFnAttributes();
37007330f729Sjoerg std::string AttrStr;
37017330f729Sjoerg
37027330f729Sjoerg for (const Attribute &Attr : AS) {
37037330f729Sjoerg if (!Attr.isStringAttribute()) {
37047330f729Sjoerg if (!AttrStr.empty()) AttrStr += ' ';
37057330f729Sjoerg AttrStr += Attr.getAsString();
37067330f729Sjoerg }
37077330f729Sjoerg }
37087330f729Sjoerg
37097330f729Sjoerg if (!AttrStr.empty())
37107330f729Sjoerg Out << "; Function Attrs: " << AttrStr << '\n';
37117330f729Sjoerg }
37127330f729Sjoerg
37137330f729Sjoerg Machine.incorporateFunction(F);
37147330f729Sjoerg
37157330f729Sjoerg if (F->isDeclaration()) {
37167330f729Sjoerg Out << "declare";
37177330f729Sjoerg SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
37187330f729Sjoerg F->getAllMetadata(MDs);
37197330f729Sjoerg printMetadataAttachments(MDs, " ");
37207330f729Sjoerg Out << ' ';
37217330f729Sjoerg } else
37227330f729Sjoerg Out << "define ";
37237330f729Sjoerg
37247330f729Sjoerg Out << getLinkageNameWithSpace(F->getLinkage());
37257330f729Sjoerg PrintDSOLocation(*F, Out);
37267330f729Sjoerg PrintVisibility(F->getVisibility(), Out);
37277330f729Sjoerg PrintDLLStorageClass(F->getDLLStorageClass(), Out);
37287330f729Sjoerg
37297330f729Sjoerg // Print the calling convention.
37307330f729Sjoerg if (F->getCallingConv() != CallingConv::C) {
37317330f729Sjoerg PrintCallingConv(F->getCallingConv(), Out);
37327330f729Sjoerg Out << " ";
37337330f729Sjoerg }
37347330f729Sjoerg
37357330f729Sjoerg FunctionType *FT = F->getFunctionType();
37367330f729Sjoerg if (Attrs.hasAttributes(AttributeList::ReturnIndex))
37377330f729Sjoerg Out << Attrs.getAsString(AttributeList::ReturnIndex) << ' ';
37387330f729Sjoerg TypePrinter.print(F->getReturnType(), Out);
37397330f729Sjoerg Out << ' ';
37407330f729Sjoerg WriteAsOperandInternal(Out, F, &TypePrinter, &Machine, F->getParent());
37417330f729Sjoerg Out << '(';
37427330f729Sjoerg
37437330f729Sjoerg // Loop over the arguments, printing them...
37447330f729Sjoerg if (F->isDeclaration() && !IsForDebug) {
37457330f729Sjoerg // We're only interested in the type here - don't print argument names.
37467330f729Sjoerg for (unsigned I = 0, E = FT->getNumParams(); I != E; ++I) {
37477330f729Sjoerg // Insert commas as we go... the first arg doesn't get a comma
37487330f729Sjoerg if (I)
37497330f729Sjoerg Out << ", ";
37507330f729Sjoerg // Output type...
37517330f729Sjoerg TypePrinter.print(FT->getParamType(I), Out);
37527330f729Sjoerg
37537330f729Sjoerg AttributeSet ArgAttrs = Attrs.getParamAttributes(I);
3754*82d56013Sjoerg if (ArgAttrs.hasAttributes()) {
3755*82d56013Sjoerg Out << ' ';
3756*82d56013Sjoerg writeAttributeSet(ArgAttrs);
3757*82d56013Sjoerg }
37587330f729Sjoerg }
37597330f729Sjoerg } else {
37607330f729Sjoerg // The arguments are meaningful here, print them in detail.
37617330f729Sjoerg for (const Argument &Arg : F->args()) {
37627330f729Sjoerg // Insert commas as we go... the first arg doesn't get a comma
37637330f729Sjoerg if (Arg.getArgNo() != 0)
37647330f729Sjoerg Out << ", ";
37657330f729Sjoerg printArgument(&Arg, Attrs.getParamAttributes(Arg.getArgNo()));
37667330f729Sjoerg }
37677330f729Sjoerg }
37687330f729Sjoerg
37697330f729Sjoerg // Finish printing arguments...
37707330f729Sjoerg if (FT->isVarArg()) {
37717330f729Sjoerg if (FT->getNumParams()) Out << ", ";
37727330f729Sjoerg Out << "..."; // Output varargs portion of signature!
37737330f729Sjoerg }
37747330f729Sjoerg Out << ')';
37757330f729Sjoerg StringRef UA = getUnnamedAddrEncoding(F->getUnnamedAddr());
37767330f729Sjoerg if (!UA.empty())
37777330f729Sjoerg Out << ' ' << UA;
37787330f729Sjoerg // We print the function address space if it is non-zero or if we are writing
37797330f729Sjoerg // a module with a non-zero program address space or if there is no valid
37807330f729Sjoerg // Module* so that the file can be parsed without the datalayout string.
37817330f729Sjoerg const Module *Mod = F->getParent();
37827330f729Sjoerg if (F->getAddressSpace() != 0 || !Mod ||
37837330f729Sjoerg Mod->getDataLayout().getProgramAddressSpace() != 0)
37847330f729Sjoerg Out << " addrspace(" << F->getAddressSpace() << ")";
37857330f729Sjoerg if (Attrs.hasAttributes(AttributeList::FunctionIndex))
37867330f729Sjoerg Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttributes());
37877330f729Sjoerg if (F->hasSection()) {
37887330f729Sjoerg Out << " section \"";
37897330f729Sjoerg printEscapedString(F->getSection(), Out);
37907330f729Sjoerg Out << '"';
37917330f729Sjoerg }
37927330f729Sjoerg if (F->hasPartition()) {
37937330f729Sjoerg Out << " partition \"";
37947330f729Sjoerg printEscapedString(F->getPartition(), Out);
37957330f729Sjoerg Out << '"';
37967330f729Sjoerg }
37977330f729Sjoerg maybePrintComdat(Out, *F);
37987330f729Sjoerg if (F->getAlignment())
37997330f729Sjoerg Out << " align " << F->getAlignment();
38007330f729Sjoerg if (F->hasGC())
38017330f729Sjoerg Out << " gc \"" << F->getGC() << '"';
38027330f729Sjoerg if (F->hasPrefixData()) {
38037330f729Sjoerg Out << " prefix ";
38047330f729Sjoerg writeOperand(F->getPrefixData(), true);
38057330f729Sjoerg }
38067330f729Sjoerg if (F->hasPrologueData()) {
38077330f729Sjoerg Out << " prologue ";
38087330f729Sjoerg writeOperand(F->getPrologueData(), true);
38097330f729Sjoerg }
38107330f729Sjoerg if (F->hasPersonalityFn()) {
38117330f729Sjoerg Out << " personality ";
38127330f729Sjoerg writeOperand(F->getPersonalityFn(), /*PrintType=*/true);
38137330f729Sjoerg }
38147330f729Sjoerg
38157330f729Sjoerg if (F->isDeclaration()) {
38167330f729Sjoerg Out << '\n';
38177330f729Sjoerg } else {
38187330f729Sjoerg SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
38197330f729Sjoerg F->getAllMetadata(MDs);
38207330f729Sjoerg printMetadataAttachments(MDs, " ");
38217330f729Sjoerg
38227330f729Sjoerg Out << " {";
38237330f729Sjoerg // Output all of the function's basic blocks.
38247330f729Sjoerg for (const BasicBlock &BB : *F)
38257330f729Sjoerg printBasicBlock(&BB);
38267330f729Sjoerg
38277330f729Sjoerg // Output the function's use-lists.
38287330f729Sjoerg printUseLists(F);
38297330f729Sjoerg
38307330f729Sjoerg Out << "}\n";
38317330f729Sjoerg }
38327330f729Sjoerg
38337330f729Sjoerg Machine.purgeFunction();
38347330f729Sjoerg }
38357330f729Sjoerg
38367330f729Sjoerg /// printArgument - This member is called for every argument that is passed into
38377330f729Sjoerg /// the function. Simply print it out
printArgument(const Argument * Arg,AttributeSet Attrs)38387330f729Sjoerg void AssemblyWriter::printArgument(const Argument *Arg, AttributeSet Attrs) {
38397330f729Sjoerg // Output type...
38407330f729Sjoerg TypePrinter.print(Arg->getType(), Out);
38417330f729Sjoerg
38427330f729Sjoerg // Output parameter attributes list
3843*82d56013Sjoerg if (Attrs.hasAttributes()) {
3844*82d56013Sjoerg Out << ' ';
3845*82d56013Sjoerg writeAttributeSet(Attrs);
3846*82d56013Sjoerg }
38477330f729Sjoerg
38487330f729Sjoerg // Output name, if available...
38497330f729Sjoerg if (Arg->hasName()) {
38507330f729Sjoerg Out << ' ';
38517330f729Sjoerg PrintLLVMName(Out, Arg);
38527330f729Sjoerg } else {
38537330f729Sjoerg int Slot = Machine.getLocalSlot(Arg);
38547330f729Sjoerg assert(Slot != -1 && "expect argument in function here");
38557330f729Sjoerg Out << " %" << Slot;
38567330f729Sjoerg }
38577330f729Sjoerg }
38587330f729Sjoerg
38597330f729Sjoerg /// printBasicBlock - This member is called for each basic block in a method.
printBasicBlock(const BasicBlock * BB)38607330f729Sjoerg void AssemblyWriter::printBasicBlock(const BasicBlock *BB) {
3861*82d56013Sjoerg assert(BB && BB->getParent() && "block without parent!");
3862*82d56013Sjoerg bool IsEntryBlock = BB->isEntryBlock();
38637330f729Sjoerg if (BB->hasName()) { // Print out the label if it exists...
38647330f729Sjoerg Out << "\n";
38657330f729Sjoerg PrintLLVMName(Out, BB->getName(), LabelPrefix);
38667330f729Sjoerg Out << ':';
38677330f729Sjoerg } else if (!IsEntryBlock) {
38687330f729Sjoerg Out << "\n";
38697330f729Sjoerg int Slot = Machine.getLocalSlot(BB);
38707330f729Sjoerg if (Slot != -1)
38717330f729Sjoerg Out << Slot << ":";
38727330f729Sjoerg else
38737330f729Sjoerg Out << "<badref>:";
38747330f729Sjoerg }
38757330f729Sjoerg
3876*82d56013Sjoerg if (!IsEntryBlock) {
38777330f729Sjoerg // Output predecessors for the block.
38787330f729Sjoerg Out.PadToColumn(50);
38797330f729Sjoerg Out << ";";
38807330f729Sjoerg const_pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
38817330f729Sjoerg
38827330f729Sjoerg if (PI == PE) {
38837330f729Sjoerg Out << " No predecessors!";
38847330f729Sjoerg } else {
38857330f729Sjoerg Out << " preds = ";
38867330f729Sjoerg writeOperand(*PI, false);
38877330f729Sjoerg for (++PI; PI != PE; ++PI) {
38887330f729Sjoerg Out << ", ";
38897330f729Sjoerg writeOperand(*PI, false);
38907330f729Sjoerg }
38917330f729Sjoerg }
38927330f729Sjoerg }
38937330f729Sjoerg
38947330f729Sjoerg Out << "\n";
38957330f729Sjoerg
38967330f729Sjoerg if (AnnotationWriter) AnnotationWriter->emitBasicBlockStartAnnot(BB, Out);
38977330f729Sjoerg
38987330f729Sjoerg // Output all of the instructions in the basic block...
38997330f729Sjoerg for (const Instruction &I : *BB) {
39007330f729Sjoerg printInstructionLine(I);
39017330f729Sjoerg }
39027330f729Sjoerg
39037330f729Sjoerg if (AnnotationWriter) AnnotationWriter->emitBasicBlockEndAnnot(BB, Out);
39047330f729Sjoerg }
39057330f729Sjoerg
39067330f729Sjoerg /// printInstructionLine - Print an instruction and a newline character.
printInstructionLine(const Instruction & I)39077330f729Sjoerg void AssemblyWriter::printInstructionLine(const Instruction &I) {
39087330f729Sjoerg printInstruction(I);
39097330f729Sjoerg Out << '\n';
39107330f729Sjoerg }
39117330f729Sjoerg
39127330f729Sjoerg /// printGCRelocateComment - print comment after call to the gc.relocate
39137330f729Sjoerg /// intrinsic indicating base and derived pointer names.
printGCRelocateComment(const GCRelocateInst & Relocate)39147330f729Sjoerg void AssemblyWriter::printGCRelocateComment(const GCRelocateInst &Relocate) {
39157330f729Sjoerg Out << " ; (";
39167330f729Sjoerg writeOperand(Relocate.getBasePtr(), false);
39177330f729Sjoerg Out << ", ";
39187330f729Sjoerg writeOperand(Relocate.getDerivedPtr(), false);
39197330f729Sjoerg Out << ")";
39207330f729Sjoerg }
39217330f729Sjoerg
39227330f729Sjoerg /// printInfoComment - Print a little comment after the instruction indicating
39237330f729Sjoerg /// which slot it occupies.
printInfoComment(const Value & V)39247330f729Sjoerg void AssemblyWriter::printInfoComment(const Value &V) {
39257330f729Sjoerg if (const auto *Relocate = dyn_cast<GCRelocateInst>(&V))
39267330f729Sjoerg printGCRelocateComment(*Relocate);
39277330f729Sjoerg
39287330f729Sjoerg if (AnnotationWriter)
39297330f729Sjoerg AnnotationWriter->printInfoComment(V, Out);
39307330f729Sjoerg }
39317330f729Sjoerg
maybePrintCallAddrSpace(const Value * Operand,const Instruction * I,raw_ostream & Out)39327330f729Sjoerg static void maybePrintCallAddrSpace(const Value *Operand, const Instruction *I,
39337330f729Sjoerg raw_ostream &Out) {
39347330f729Sjoerg // We print the address space of the call if it is non-zero.
39357330f729Sjoerg unsigned CallAddrSpace = Operand->getType()->getPointerAddressSpace();
39367330f729Sjoerg bool PrintAddrSpace = CallAddrSpace != 0;
39377330f729Sjoerg if (!PrintAddrSpace) {
39387330f729Sjoerg const Module *Mod = getModuleFromVal(I);
39397330f729Sjoerg // We also print it if it is zero but not equal to the program address space
39407330f729Sjoerg // or if we can't find a valid Module* to make it possible to parse
39417330f729Sjoerg // the resulting file even without a datalayout string.
39427330f729Sjoerg if (!Mod || Mod->getDataLayout().getProgramAddressSpace() != 0)
39437330f729Sjoerg PrintAddrSpace = true;
39447330f729Sjoerg }
39457330f729Sjoerg if (PrintAddrSpace)
39467330f729Sjoerg Out << " addrspace(" << CallAddrSpace << ")";
39477330f729Sjoerg }
39487330f729Sjoerg
39497330f729Sjoerg // This member is called for each Instruction in a function..
printInstruction(const Instruction & I)39507330f729Sjoerg void AssemblyWriter::printInstruction(const Instruction &I) {
39517330f729Sjoerg if (AnnotationWriter) AnnotationWriter->emitInstructionAnnot(&I, Out);
39527330f729Sjoerg
39537330f729Sjoerg // Print out indentation for an instruction.
39547330f729Sjoerg Out << " ";
39557330f729Sjoerg
39567330f729Sjoerg // Print out name if it exists...
39577330f729Sjoerg if (I.hasName()) {
39587330f729Sjoerg PrintLLVMName(Out, &I);
39597330f729Sjoerg Out << " = ";
39607330f729Sjoerg } else if (!I.getType()->isVoidTy()) {
39617330f729Sjoerg // Print out the def slot taken.
39627330f729Sjoerg int SlotNum = Machine.getLocalSlot(&I);
39637330f729Sjoerg if (SlotNum == -1)
39647330f729Sjoerg Out << "<badref> = ";
39657330f729Sjoerg else
39667330f729Sjoerg Out << '%' << SlotNum << " = ";
39677330f729Sjoerg }
39687330f729Sjoerg
39697330f729Sjoerg if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
39707330f729Sjoerg if (CI->isMustTailCall())
39717330f729Sjoerg Out << "musttail ";
39727330f729Sjoerg else if (CI->isTailCall())
39737330f729Sjoerg Out << "tail ";
39747330f729Sjoerg else if (CI->isNoTailCall())
39757330f729Sjoerg Out << "notail ";
39767330f729Sjoerg }
39777330f729Sjoerg
39787330f729Sjoerg // Print out the opcode...
39797330f729Sjoerg Out << I.getOpcodeName();
39807330f729Sjoerg
39817330f729Sjoerg // If this is an atomic load or store, print out the atomic marker.
39827330f729Sjoerg if ((isa<LoadInst>(I) && cast<LoadInst>(I).isAtomic()) ||
39837330f729Sjoerg (isa<StoreInst>(I) && cast<StoreInst>(I).isAtomic()))
39847330f729Sjoerg Out << " atomic";
39857330f729Sjoerg
39867330f729Sjoerg if (isa<AtomicCmpXchgInst>(I) && cast<AtomicCmpXchgInst>(I).isWeak())
39877330f729Sjoerg Out << " weak";
39887330f729Sjoerg
39897330f729Sjoerg // If this is a volatile operation, print out the volatile marker.
39907330f729Sjoerg if ((isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) ||
39917330f729Sjoerg (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()) ||
39927330f729Sjoerg (isa<AtomicCmpXchgInst>(I) && cast<AtomicCmpXchgInst>(I).isVolatile()) ||
39937330f729Sjoerg (isa<AtomicRMWInst>(I) && cast<AtomicRMWInst>(I).isVolatile()))
39947330f729Sjoerg Out << " volatile";
39957330f729Sjoerg
39967330f729Sjoerg // Print out optimization information.
39977330f729Sjoerg WriteOptimizationInfo(Out, &I);
39987330f729Sjoerg
39997330f729Sjoerg // Print out the compare instruction predicates
40007330f729Sjoerg if (const CmpInst *CI = dyn_cast<CmpInst>(&I))
40017330f729Sjoerg Out << ' ' << CmpInst::getPredicateName(CI->getPredicate());
40027330f729Sjoerg
40037330f729Sjoerg // Print out the atomicrmw operation
40047330f729Sjoerg if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&I))
40057330f729Sjoerg Out << ' ' << AtomicRMWInst::getOperationName(RMWI->getOperation());
40067330f729Sjoerg
40077330f729Sjoerg // Print out the type of the operands...
40087330f729Sjoerg const Value *Operand = I.getNumOperands() ? I.getOperand(0) : nullptr;
40097330f729Sjoerg
40107330f729Sjoerg // Special case conditional branches to swizzle the condition out to the front
40117330f729Sjoerg if (isa<BranchInst>(I) && cast<BranchInst>(I).isConditional()) {
40127330f729Sjoerg const BranchInst &BI(cast<BranchInst>(I));
40137330f729Sjoerg Out << ' ';
40147330f729Sjoerg writeOperand(BI.getCondition(), true);
40157330f729Sjoerg Out << ", ";
40167330f729Sjoerg writeOperand(BI.getSuccessor(0), true);
40177330f729Sjoerg Out << ", ";
40187330f729Sjoerg writeOperand(BI.getSuccessor(1), true);
40197330f729Sjoerg
40207330f729Sjoerg } else if (isa<SwitchInst>(I)) {
40217330f729Sjoerg const SwitchInst& SI(cast<SwitchInst>(I));
40227330f729Sjoerg // Special case switch instruction to get formatting nice and correct.
40237330f729Sjoerg Out << ' ';
40247330f729Sjoerg writeOperand(SI.getCondition(), true);
40257330f729Sjoerg Out << ", ";
40267330f729Sjoerg writeOperand(SI.getDefaultDest(), true);
40277330f729Sjoerg Out << " [";
40287330f729Sjoerg for (auto Case : SI.cases()) {
40297330f729Sjoerg Out << "\n ";
40307330f729Sjoerg writeOperand(Case.getCaseValue(), true);
40317330f729Sjoerg Out << ", ";
40327330f729Sjoerg writeOperand(Case.getCaseSuccessor(), true);
40337330f729Sjoerg }
40347330f729Sjoerg Out << "\n ]";
40357330f729Sjoerg } else if (isa<IndirectBrInst>(I)) {
40367330f729Sjoerg // Special case indirectbr instruction to get formatting nice and correct.
40377330f729Sjoerg Out << ' ';
40387330f729Sjoerg writeOperand(Operand, true);
40397330f729Sjoerg Out << ", [";
40407330f729Sjoerg
40417330f729Sjoerg for (unsigned i = 1, e = I.getNumOperands(); i != e; ++i) {
40427330f729Sjoerg if (i != 1)
40437330f729Sjoerg Out << ", ";
40447330f729Sjoerg writeOperand(I.getOperand(i), true);
40457330f729Sjoerg }
40467330f729Sjoerg Out << ']';
40477330f729Sjoerg } else if (const PHINode *PN = dyn_cast<PHINode>(&I)) {
40487330f729Sjoerg Out << ' ';
40497330f729Sjoerg TypePrinter.print(I.getType(), Out);
40507330f729Sjoerg Out << ' ';
40517330f729Sjoerg
40527330f729Sjoerg for (unsigned op = 0, Eop = PN->getNumIncomingValues(); op < Eop; ++op) {
40537330f729Sjoerg if (op) Out << ", ";
40547330f729Sjoerg Out << "[ ";
40557330f729Sjoerg writeOperand(PN->getIncomingValue(op), false); Out << ", ";
40567330f729Sjoerg writeOperand(PN->getIncomingBlock(op), false); Out << " ]";
40577330f729Sjoerg }
40587330f729Sjoerg } else if (const ExtractValueInst *EVI = dyn_cast<ExtractValueInst>(&I)) {
40597330f729Sjoerg Out << ' ';
40607330f729Sjoerg writeOperand(I.getOperand(0), true);
4061*82d56013Sjoerg for (unsigned i : EVI->indices())
4062*82d56013Sjoerg Out << ", " << i;
40637330f729Sjoerg } else if (const InsertValueInst *IVI = dyn_cast<InsertValueInst>(&I)) {
40647330f729Sjoerg Out << ' ';
40657330f729Sjoerg writeOperand(I.getOperand(0), true); Out << ", ";
40667330f729Sjoerg writeOperand(I.getOperand(1), true);
4067*82d56013Sjoerg for (unsigned i : IVI->indices())
4068*82d56013Sjoerg Out << ", " << i;
40697330f729Sjoerg } else if (const LandingPadInst *LPI = dyn_cast<LandingPadInst>(&I)) {
40707330f729Sjoerg Out << ' ';
40717330f729Sjoerg TypePrinter.print(I.getType(), Out);
40727330f729Sjoerg if (LPI->isCleanup() || LPI->getNumClauses() != 0)
40737330f729Sjoerg Out << '\n';
40747330f729Sjoerg
40757330f729Sjoerg if (LPI->isCleanup())
40767330f729Sjoerg Out << " cleanup";
40777330f729Sjoerg
40787330f729Sjoerg for (unsigned i = 0, e = LPI->getNumClauses(); i != e; ++i) {
40797330f729Sjoerg if (i != 0 || LPI->isCleanup()) Out << "\n";
40807330f729Sjoerg if (LPI->isCatch(i))
40817330f729Sjoerg Out << " catch ";
40827330f729Sjoerg else
40837330f729Sjoerg Out << " filter ";
40847330f729Sjoerg
40857330f729Sjoerg writeOperand(LPI->getClause(i), true);
40867330f729Sjoerg }
40877330f729Sjoerg } else if (const auto *CatchSwitch = dyn_cast<CatchSwitchInst>(&I)) {
40887330f729Sjoerg Out << " within ";
40897330f729Sjoerg writeOperand(CatchSwitch->getParentPad(), /*PrintType=*/false);
40907330f729Sjoerg Out << " [";
40917330f729Sjoerg unsigned Op = 0;
40927330f729Sjoerg for (const BasicBlock *PadBB : CatchSwitch->handlers()) {
40937330f729Sjoerg if (Op > 0)
40947330f729Sjoerg Out << ", ";
40957330f729Sjoerg writeOperand(PadBB, /*PrintType=*/true);
40967330f729Sjoerg ++Op;
40977330f729Sjoerg }
40987330f729Sjoerg Out << "] unwind ";
40997330f729Sjoerg if (const BasicBlock *UnwindDest = CatchSwitch->getUnwindDest())
41007330f729Sjoerg writeOperand(UnwindDest, /*PrintType=*/true);
41017330f729Sjoerg else
41027330f729Sjoerg Out << "to caller";
41037330f729Sjoerg } else if (const auto *FPI = dyn_cast<FuncletPadInst>(&I)) {
41047330f729Sjoerg Out << " within ";
41057330f729Sjoerg writeOperand(FPI->getParentPad(), /*PrintType=*/false);
41067330f729Sjoerg Out << " [";
41077330f729Sjoerg for (unsigned Op = 0, NumOps = FPI->getNumArgOperands(); Op < NumOps;
41087330f729Sjoerg ++Op) {
41097330f729Sjoerg if (Op > 0)
41107330f729Sjoerg Out << ", ";
41117330f729Sjoerg writeOperand(FPI->getArgOperand(Op), /*PrintType=*/true);
41127330f729Sjoerg }
41137330f729Sjoerg Out << ']';
41147330f729Sjoerg } else if (isa<ReturnInst>(I) && !Operand) {
41157330f729Sjoerg Out << " void";
41167330f729Sjoerg } else if (const auto *CRI = dyn_cast<CatchReturnInst>(&I)) {
41177330f729Sjoerg Out << " from ";
41187330f729Sjoerg writeOperand(CRI->getOperand(0), /*PrintType=*/false);
41197330f729Sjoerg
41207330f729Sjoerg Out << " to ";
41217330f729Sjoerg writeOperand(CRI->getOperand(1), /*PrintType=*/true);
41227330f729Sjoerg } else if (const auto *CRI = dyn_cast<CleanupReturnInst>(&I)) {
41237330f729Sjoerg Out << " from ";
41247330f729Sjoerg writeOperand(CRI->getOperand(0), /*PrintType=*/false);
41257330f729Sjoerg
41267330f729Sjoerg Out << " unwind ";
41277330f729Sjoerg if (CRI->hasUnwindDest())
41287330f729Sjoerg writeOperand(CRI->getOperand(1), /*PrintType=*/true);
41297330f729Sjoerg else
41307330f729Sjoerg Out << "to caller";
41317330f729Sjoerg } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
41327330f729Sjoerg // Print the calling convention being used.
41337330f729Sjoerg if (CI->getCallingConv() != CallingConv::C) {
41347330f729Sjoerg Out << " ";
41357330f729Sjoerg PrintCallingConv(CI->getCallingConv(), Out);
41367330f729Sjoerg }
41377330f729Sjoerg
4138*82d56013Sjoerg Operand = CI->getCalledOperand();
41397330f729Sjoerg FunctionType *FTy = CI->getFunctionType();
41407330f729Sjoerg Type *RetTy = FTy->getReturnType();
41417330f729Sjoerg const AttributeList &PAL = CI->getAttributes();
41427330f729Sjoerg
41437330f729Sjoerg if (PAL.hasAttributes(AttributeList::ReturnIndex))
41447330f729Sjoerg Out << ' ' << PAL.getAsString(AttributeList::ReturnIndex);
41457330f729Sjoerg
41467330f729Sjoerg // Only print addrspace(N) if necessary:
41477330f729Sjoerg maybePrintCallAddrSpace(Operand, &I, Out);
41487330f729Sjoerg
41497330f729Sjoerg // If possible, print out the short form of the call instruction. We can
41507330f729Sjoerg // only do this if the first argument is a pointer to a nonvararg function,
41517330f729Sjoerg // and if the return type is not a pointer to a function.
41527330f729Sjoerg //
41537330f729Sjoerg Out << ' ';
41547330f729Sjoerg TypePrinter.print(FTy->isVarArg() ? FTy : RetTy, Out);
41557330f729Sjoerg Out << ' ';
41567330f729Sjoerg writeOperand(Operand, false);
41577330f729Sjoerg Out << '(';
41587330f729Sjoerg for (unsigned op = 0, Eop = CI->getNumArgOperands(); op < Eop; ++op) {
41597330f729Sjoerg if (op > 0)
41607330f729Sjoerg Out << ", ";
41617330f729Sjoerg writeParamOperand(CI->getArgOperand(op), PAL.getParamAttributes(op));
41627330f729Sjoerg }
41637330f729Sjoerg
41647330f729Sjoerg // Emit an ellipsis if this is a musttail call in a vararg function. This
41657330f729Sjoerg // is only to aid readability, musttail calls forward varargs by default.
41667330f729Sjoerg if (CI->isMustTailCall() && CI->getParent() &&
41677330f729Sjoerg CI->getParent()->getParent() &&
41687330f729Sjoerg CI->getParent()->getParent()->isVarArg())
41697330f729Sjoerg Out << ", ...";
41707330f729Sjoerg
41717330f729Sjoerg Out << ')';
41727330f729Sjoerg if (PAL.hasAttributes(AttributeList::FunctionIndex))
41737330f729Sjoerg Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes());
41747330f729Sjoerg
41757330f729Sjoerg writeOperandBundles(CI);
41767330f729Sjoerg } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
4177*82d56013Sjoerg Operand = II->getCalledOperand();
41787330f729Sjoerg FunctionType *FTy = II->getFunctionType();
41797330f729Sjoerg Type *RetTy = FTy->getReturnType();
41807330f729Sjoerg const AttributeList &PAL = II->getAttributes();
41817330f729Sjoerg
41827330f729Sjoerg // Print the calling convention being used.
41837330f729Sjoerg if (II->getCallingConv() != CallingConv::C) {
41847330f729Sjoerg Out << " ";
41857330f729Sjoerg PrintCallingConv(II->getCallingConv(), Out);
41867330f729Sjoerg }
41877330f729Sjoerg
41887330f729Sjoerg if (PAL.hasAttributes(AttributeList::ReturnIndex))
41897330f729Sjoerg Out << ' ' << PAL.getAsString(AttributeList::ReturnIndex);
41907330f729Sjoerg
41917330f729Sjoerg // Only print addrspace(N) if necessary:
41927330f729Sjoerg maybePrintCallAddrSpace(Operand, &I, Out);
41937330f729Sjoerg
41947330f729Sjoerg // If possible, print out the short form of the invoke instruction. We can
41957330f729Sjoerg // only do this if the first argument is a pointer to a nonvararg function,
41967330f729Sjoerg // and if the return type is not a pointer to a function.
41977330f729Sjoerg //
41987330f729Sjoerg Out << ' ';
41997330f729Sjoerg TypePrinter.print(FTy->isVarArg() ? FTy : RetTy, Out);
42007330f729Sjoerg Out << ' ';
42017330f729Sjoerg writeOperand(Operand, false);
42027330f729Sjoerg Out << '(';
42037330f729Sjoerg for (unsigned op = 0, Eop = II->getNumArgOperands(); op < Eop; ++op) {
42047330f729Sjoerg if (op)
42057330f729Sjoerg Out << ", ";
42067330f729Sjoerg writeParamOperand(II->getArgOperand(op), PAL.getParamAttributes(op));
42077330f729Sjoerg }
42087330f729Sjoerg
42097330f729Sjoerg Out << ')';
42107330f729Sjoerg if (PAL.hasAttributes(AttributeList::FunctionIndex))
42117330f729Sjoerg Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes());
42127330f729Sjoerg
42137330f729Sjoerg writeOperandBundles(II);
42147330f729Sjoerg
42157330f729Sjoerg Out << "\n to ";
42167330f729Sjoerg writeOperand(II->getNormalDest(), true);
42177330f729Sjoerg Out << " unwind ";
42187330f729Sjoerg writeOperand(II->getUnwindDest(), true);
42197330f729Sjoerg } else if (const CallBrInst *CBI = dyn_cast<CallBrInst>(&I)) {
4220*82d56013Sjoerg Operand = CBI->getCalledOperand();
42217330f729Sjoerg FunctionType *FTy = CBI->getFunctionType();
42227330f729Sjoerg Type *RetTy = FTy->getReturnType();
42237330f729Sjoerg const AttributeList &PAL = CBI->getAttributes();
42247330f729Sjoerg
42257330f729Sjoerg // Print the calling convention being used.
42267330f729Sjoerg if (CBI->getCallingConv() != CallingConv::C) {
42277330f729Sjoerg Out << " ";
42287330f729Sjoerg PrintCallingConv(CBI->getCallingConv(), Out);
42297330f729Sjoerg }
42307330f729Sjoerg
42317330f729Sjoerg if (PAL.hasAttributes(AttributeList::ReturnIndex))
42327330f729Sjoerg Out << ' ' << PAL.getAsString(AttributeList::ReturnIndex);
42337330f729Sjoerg
42347330f729Sjoerg // If possible, print out the short form of the callbr instruction. We can
42357330f729Sjoerg // only do this if the first argument is a pointer to a nonvararg function,
42367330f729Sjoerg // and if the return type is not a pointer to a function.
42377330f729Sjoerg //
42387330f729Sjoerg Out << ' ';
42397330f729Sjoerg TypePrinter.print(FTy->isVarArg() ? FTy : RetTy, Out);
42407330f729Sjoerg Out << ' ';
42417330f729Sjoerg writeOperand(Operand, false);
42427330f729Sjoerg Out << '(';
42437330f729Sjoerg for (unsigned op = 0, Eop = CBI->getNumArgOperands(); op < Eop; ++op) {
42447330f729Sjoerg if (op)
42457330f729Sjoerg Out << ", ";
42467330f729Sjoerg writeParamOperand(CBI->getArgOperand(op), PAL.getParamAttributes(op));
42477330f729Sjoerg }
42487330f729Sjoerg
42497330f729Sjoerg Out << ')';
42507330f729Sjoerg if (PAL.hasAttributes(AttributeList::FunctionIndex))
42517330f729Sjoerg Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes());
42527330f729Sjoerg
42537330f729Sjoerg writeOperandBundles(CBI);
42547330f729Sjoerg
42557330f729Sjoerg Out << "\n to ";
42567330f729Sjoerg writeOperand(CBI->getDefaultDest(), true);
42577330f729Sjoerg Out << " [";
42587330f729Sjoerg for (unsigned i = 0, e = CBI->getNumIndirectDests(); i != e; ++i) {
42597330f729Sjoerg if (i != 0)
42607330f729Sjoerg Out << ", ";
42617330f729Sjoerg writeOperand(CBI->getIndirectDest(i), true);
42627330f729Sjoerg }
42637330f729Sjoerg Out << ']';
42647330f729Sjoerg } else if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
42657330f729Sjoerg Out << ' ';
42667330f729Sjoerg if (AI->isUsedWithInAlloca())
42677330f729Sjoerg Out << "inalloca ";
42687330f729Sjoerg if (AI->isSwiftError())
42697330f729Sjoerg Out << "swifterror ";
42707330f729Sjoerg TypePrinter.print(AI->getAllocatedType(), Out);
42717330f729Sjoerg
42727330f729Sjoerg // Explicitly write the array size if the code is broken, if it's an array
42737330f729Sjoerg // allocation, or if the type is not canonical for scalar allocations. The
42747330f729Sjoerg // latter case prevents the type from mutating when round-tripping through
42757330f729Sjoerg // assembly.
42767330f729Sjoerg if (!AI->getArraySize() || AI->isArrayAllocation() ||
42777330f729Sjoerg !AI->getArraySize()->getType()->isIntegerTy(32)) {
42787330f729Sjoerg Out << ", ";
42797330f729Sjoerg writeOperand(AI->getArraySize(), true);
42807330f729Sjoerg }
42817330f729Sjoerg if (AI->getAlignment()) {
42827330f729Sjoerg Out << ", align " << AI->getAlignment();
42837330f729Sjoerg }
42847330f729Sjoerg
42857330f729Sjoerg unsigned AddrSpace = AI->getType()->getAddressSpace();
42867330f729Sjoerg if (AddrSpace != 0) {
42877330f729Sjoerg Out << ", addrspace(" << AddrSpace << ')';
42887330f729Sjoerg }
42897330f729Sjoerg } else if (isa<CastInst>(I)) {
42907330f729Sjoerg if (Operand) {
42917330f729Sjoerg Out << ' ';
42927330f729Sjoerg writeOperand(Operand, true); // Work with broken code
42937330f729Sjoerg }
42947330f729Sjoerg Out << " to ";
42957330f729Sjoerg TypePrinter.print(I.getType(), Out);
42967330f729Sjoerg } else if (isa<VAArgInst>(I)) {
42977330f729Sjoerg if (Operand) {
42987330f729Sjoerg Out << ' ';
42997330f729Sjoerg writeOperand(Operand, true); // Work with broken code
43007330f729Sjoerg }
43017330f729Sjoerg Out << ", ";
43027330f729Sjoerg TypePrinter.print(I.getType(), Out);
43037330f729Sjoerg } else if (Operand) { // Print the normal way.
43047330f729Sjoerg if (const auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
43057330f729Sjoerg Out << ' ';
43067330f729Sjoerg TypePrinter.print(GEP->getSourceElementType(), Out);
43077330f729Sjoerg Out << ',';
43087330f729Sjoerg } else if (const auto *LI = dyn_cast<LoadInst>(&I)) {
43097330f729Sjoerg Out << ' ';
43107330f729Sjoerg TypePrinter.print(LI->getType(), Out);
43117330f729Sjoerg Out << ',';
43127330f729Sjoerg }
43137330f729Sjoerg
43147330f729Sjoerg // PrintAllTypes - Instructions who have operands of all the same type
43157330f729Sjoerg // omit the type from all but the first operand. If the instruction has
43167330f729Sjoerg // different type operands (for example br), then they are all printed.
43177330f729Sjoerg bool PrintAllTypes = false;
43187330f729Sjoerg Type *TheType = Operand->getType();
43197330f729Sjoerg
43207330f729Sjoerg // Select, Store and ShuffleVector always print all types.
43217330f729Sjoerg if (isa<SelectInst>(I) || isa<StoreInst>(I) || isa<ShuffleVectorInst>(I)
43227330f729Sjoerg || isa<ReturnInst>(I)) {
43237330f729Sjoerg PrintAllTypes = true;
43247330f729Sjoerg } else {
43257330f729Sjoerg for (unsigned i = 1, E = I.getNumOperands(); i != E; ++i) {
43267330f729Sjoerg Operand = I.getOperand(i);
43277330f729Sjoerg // note that Operand shouldn't be null, but the test helps make dump()
43287330f729Sjoerg // more tolerant of malformed IR
43297330f729Sjoerg if (Operand && Operand->getType() != TheType) {
43307330f729Sjoerg PrintAllTypes = true; // We have differing types! Print them all!
43317330f729Sjoerg break;
43327330f729Sjoerg }
43337330f729Sjoerg }
43347330f729Sjoerg }
43357330f729Sjoerg
43367330f729Sjoerg if (!PrintAllTypes) {
43377330f729Sjoerg Out << ' ';
43387330f729Sjoerg TypePrinter.print(TheType, Out);
43397330f729Sjoerg }
43407330f729Sjoerg
43417330f729Sjoerg Out << ' ';
43427330f729Sjoerg for (unsigned i = 0, E = I.getNumOperands(); i != E; ++i) {
43437330f729Sjoerg if (i) Out << ", ";
43447330f729Sjoerg writeOperand(I.getOperand(i), PrintAllTypes);
43457330f729Sjoerg }
43467330f729Sjoerg }
43477330f729Sjoerg
43487330f729Sjoerg // Print atomic ordering/alignment for memory operations
43497330f729Sjoerg if (const LoadInst *LI = dyn_cast<LoadInst>(&I)) {
43507330f729Sjoerg if (LI->isAtomic())
43517330f729Sjoerg writeAtomic(LI->getContext(), LI->getOrdering(), LI->getSyncScopeID());
43527330f729Sjoerg if (LI->getAlignment())
43537330f729Sjoerg Out << ", align " << LI->getAlignment();
43547330f729Sjoerg } else if (const StoreInst *SI = dyn_cast<StoreInst>(&I)) {
43557330f729Sjoerg if (SI->isAtomic())
43567330f729Sjoerg writeAtomic(SI->getContext(), SI->getOrdering(), SI->getSyncScopeID());
43577330f729Sjoerg if (SI->getAlignment())
43587330f729Sjoerg Out << ", align " << SI->getAlignment();
43597330f729Sjoerg } else if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&I)) {
43607330f729Sjoerg writeAtomicCmpXchg(CXI->getContext(), CXI->getSuccessOrdering(),
43617330f729Sjoerg CXI->getFailureOrdering(), CXI->getSyncScopeID());
4362*82d56013Sjoerg Out << ", align " << CXI->getAlign().value();
43637330f729Sjoerg } else if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&I)) {
43647330f729Sjoerg writeAtomic(RMWI->getContext(), RMWI->getOrdering(),
43657330f729Sjoerg RMWI->getSyncScopeID());
4366*82d56013Sjoerg Out << ", align " << RMWI->getAlign().value();
43677330f729Sjoerg } else if (const FenceInst *FI = dyn_cast<FenceInst>(&I)) {
43687330f729Sjoerg writeAtomic(FI->getContext(), FI->getOrdering(), FI->getSyncScopeID());
4369*82d56013Sjoerg } else if (const ShuffleVectorInst *SVI = dyn_cast<ShuffleVectorInst>(&I)) {
4370*82d56013Sjoerg PrintShuffleMask(Out, SVI->getType(), SVI->getShuffleMask());
43717330f729Sjoerg }
43727330f729Sjoerg
43737330f729Sjoerg // Print Metadata info.
43747330f729Sjoerg SmallVector<std::pair<unsigned, MDNode *>, 4> InstMD;
43757330f729Sjoerg I.getAllMetadata(InstMD);
43767330f729Sjoerg printMetadataAttachments(InstMD, ", ");
43777330f729Sjoerg
43787330f729Sjoerg // Print a nice comment.
43797330f729Sjoerg printInfoComment(I);
43807330f729Sjoerg }
43817330f729Sjoerg
printMetadataAttachments(const SmallVectorImpl<std::pair<unsigned,MDNode * >> & MDs,StringRef Separator)43827330f729Sjoerg void AssemblyWriter::printMetadataAttachments(
43837330f729Sjoerg const SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs,
43847330f729Sjoerg StringRef Separator) {
43857330f729Sjoerg if (MDs.empty())
43867330f729Sjoerg return;
43877330f729Sjoerg
43887330f729Sjoerg if (MDNames.empty())
43897330f729Sjoerg MDs[0].second->getContext().getMDKindNames(MDNames);
43907330f729Sjoerg
43917330f729Sjoerg for (const auto &I : MDs) {
43927330f729Sjoerg unsigned Kind = I.first;
43937330f729Sjoerg Out << Separator;
43947330f729Sjoerg if (Kind < MDNames.size()) {
43957330f729Sjoerg Out << "!";
43967330f729Sjoerg printMetadataIdentifier(MDNames[Kind], Out);
43977330f729Sjoerg } else
43987330f729Sjoerg Out << "!<unknown kind #" << Kind << ">";
43997330f729Sjoerg Out << ' ';
44007330f729Sjoerg WriteAsOperandInternal(Out, I.second, &TypePrinter, &Machine, TheModule);
44017330f729Sjoerg }
44027330f729Sjoerg }
44037330f729Sjoerg
writeMDNode(unsigned Slot,const MDNode * Node)44047330f729Sjoerg void AssemblyWriter::writeMDNode(unsigned Slot, const MDNode *Node) {
44057330f729Sjoerg Out << '!' << Slot << " = ";
44067330f729Sjoerg printMDNodeBody(Node);
44077330f729Sjoerg Out << "\n";
44087330f729Sjoerg }
44097330f729Sjoerg
writeAllMDNodes()44107330f729Sjoerg void AssemblyWriter::writeAllMDNodes() {
44117330f729Sjoerg SmallVector<const MDNode *, 16> Nodes;
44127330f729Sjoerg Nodes.resize(Machine.mdn_size());
4413*82d56013Sjoerg for (auto &I : llvm::make_range(Machine.mdn_begin(), Machine.mdn_end()))
4414*82d56013Sjoerg Nodes[I.second] = cast<MDNode>(I.first);
44157330f729Sjoerg
44167330f729Sjoerg for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
44177330f729Sjoerg writeMDNode(i, Nodes[i]);
44187330f729Sjoerg }
44197330f729Sjoerg }
44207330f729Sjoerg
printMDNodeBody(const MDNode * Node)44217330f729Sjoerg void AssemblyWriter::printMDNodeBody(const MDNode *Node) {
44227330f729Sjoerg WriteMDNodeBodyInternal(Out, Node, &TypePrinter, &Machine, TheModule);
44237330f729Sjoerg }
44247330f729Sjoerg
writeAttribute(const Attribute & Attr,bool InAttrGroup)4425*82d56013Sjoerg void AssemblyWriter::writeAttribute(const Attribute &Attr, bool InAttrGroup) {
4426*82d56013Sjoerg if (!Attr.isTypeAttribute()) {
4427*82d56013Sjoerg Out << Attr.getAsString(InAttrGroup);
4428*82d56013Sjoerg return;
4429*82d56013Sjoerg }
4430*82d56013Sjoerg
4431*82d56013Sjoerg if (Attr.hasAttribute(Attribute::ByVal)) {
4432*82d56013Sjoerg Out << "byval";
4433*82d56013Sjoerg } else if (Attr.hasAttribute(Attribute::StructRet)) {
4434*82d56013Sjoerg Out << "sret";
4435*82d56013Sjoerg } else if (Attr.hasAttribute(Attribute::ByRef)) {
4436*82d56013Sjoerg Out << "byref";
4437*82d56013Sjoerg } else if (Attr.hasAttribute(Attribute::Preallocated)) {
4438*82d56013Sjoerg Out << "preallocated";
4439*82d56013Sjoerg } else if (Attr.hasAttribute(Attribute::InAlloca)) {
4440*82d56013Sjoerg Out << "inalloca";
4441*82d56013Sjoerg } else {
4442*82d56013Sjoerg llvm_unreachable("unexpected type attr");
4443*82d56013Sjoerg }
4444*82d56013Sjoerg
4445*82d56013Sjoerg if (Type *Ty = Attr.getValueAsType()) {
4446*82d56013Sjoerg Out << '(';
4447*82d56013Sjoerg TypePrinter.print(Ty, Out);
4448*82d56013Sjoerg Out << ')';
4449*82d56013Sjoerg }
4450*82d56013Sjoerg }
4451*82d56013Sjoerg
writeAttributeSet(const AttributeSet & AttrSet,bool InAttrGroup)4452*82d56013Sjoerg void AssemblyWriter::writeAttributeSet(const AttributeSet &AttrSet,
4453*82d56013Sjoerg bool InAttrGroup) {
4454*82d56013Sjoerg bool FirstAttr = true;
4455*82d56013Sjoerg for (const auto &Attr : AttrSet) {
4456*82d56013Sjoerg if (!FirstAttr)
4457*82d56013Sjoerg Out << ' ';
4458*82d56013Sjoerg writeAttribute(Attr, InAttrGroup);
4459*82d56013Sjoerg FirstAttr = false;
4460*82d56013Sjoerg }
4461*82d56013Sjoerg }
4462*82d56013Sjoerg
writeAllAttributeGroups()44637330f729Sjoerg void AssemblyWriter::writeAllAttributeGroups() {
44647330f729Sjoerg std::vector<std::pair<AttributeSet, unsigned>> asVec;
44657330f729Sjoerg asVec.resize(Machine.as_size());
44667330f729Sjoerg
4467*82d56013Sjoerg for (auto &I : llvm::make_range(Machine.as_begin(), Machine.as_end()))
4468*82d56013Sjoerg asVec[I.second] = I;
44697330f729Sjoerg
44707330f729Sjoerg for (const auto &I : asVec)
44717330f729Sjoerg Out << "attributes #" << I.second << " = { "
44727330f729Sjoerg << I.first.getAsString(true) << " }\n";
44737330f729Sjoerg }
44747330f729Sjoerg
printUseListOrder(const UseListOrder & Order)44757330f729Sjoerg void AssemblyWriter::printUseListOrder(const UseListOrder &Order) {
44767330f729Sjoerg bool IsInFunction = Machine.getFunction();
44777330f729Sjoerg if (IsInFunction)
44787330f729Sjoerg Out << " ";
44797330f729Sjoerg
44807330f729Sjoerg Out << "uselistorder";
44817330f729Sjoerg if (const BasicBlock *BB =
44827330f729Sjoerg IsInFunction ? nullptr : dyn_cast<BasicBlock>(Order.V)) {
44837330f729Sjoerg Out << "_bb ";
44847330f729Sjoerg writeOperand(BB->getParent(), false);
44857330f729Sjoerg Out << ", ";
44867330f729Sjoerg writeOperand(BB, false);
44877330f729Sjoerg } else {
44887330f729Sjoerg Out << " ";
44897330f729Sjoerg writeOperand(Order.V, true);
44907330f729Sjoerg }
44917330f729Sjoerg Out << ", { ";
44927330f729Sjoerg
44937330f729Sjoerg assert(Order.Shuffle.size() >= 2 && "Shuffle too small");
44947330f729Sjoerg Out << Order.Shuffle[0];
44957330f729Sjoerg for (unsigned I = 1, E = Order.Shuffle.size(); I != E; ++I)
44967330f729Sjoerg Out << ", " << Order.Shuffle[I];
44977330f729Sjoerg Out << " }\n";
44987330f729Sjoerg }
44997330f729Sjoerg
printUseLists(const Function * F)45007330f729Sjoerg void AssemblyWriter::printUseLists(const Function *F) {
45017330f729Sjoerg auto hasMore =
45027330f729Sjoerg [&]() { return !UseListOrders.empty() && UseListOrders.back().F == F; };
45037330f729Sjoerg if (!hasMore())
45047330f729Sjoerg // Nothing to do.
45057330f729Sjoerg return;
45067330f729Sjoerg
45077330f729Sjoerg Out << "\n; uselistorder directives\n";
45087330f729Sjoerg while (hasMore()) {
45097330f729Sjoerg printUseListOrder(UseListOrders.back());
45107330f729Sjoerg UseListOrders.pop_back();
45117330f729Sjoerg }
45127330f729Sjoerg }
45137330f729Sjoerg
45147330f729Sjoerg //===----------------------------------------------------------------------===//
45157330f729Sjoerg // External Interface declarations
45167330f729Sjoerg //===----------------------------------------------------------------------===//
45177330f729Sjoerg
print(raw_ostream & ROS,AssemblyAnnotationWriter * AAW,bool ShouldPreserveUseListOrder,bool IsForDebug) const45187330f729Sjoerg void Function::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
45197330f729Sjoerg bool ShouldPreserveUseListOrder,
45207330f729Sjoerg bool IsForDebug) const {
45217330f729Sjoerg SlotTracker SlotTable(this->getParent());
45227330f729Sjoerg formatted_raw_ostream OS(ROS);
45237330f729Sjoerg AssemblyWriter W(OS, SlotTable, this->getParent(), AAW,
45247330f729Sjoerg IsForDebug,
45257330f729Sjoerg ShouldPreserveUseListOrder);
45267330f729Sjoerg W.printFunction(this);
45277330f729Sjoerg }
45287330f729Sjoerg
print(raw_ostream & ROS,AssemblyAnnotationWriter * AAW,bool ShouldPreserveUseListOrder,bool IsForDebug) const4529*82d56013Sjoerg void BasicBlock::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
4530*82d56013Sjoerg bool ShouldPreserveUseListOrder,
4531*82d56013Sjoerg bool IsForDebug) const {
4532*82d56013Sjoerg SlotTracker SlotTable(this->getParent());
4533*82d56013Sjoerg formatted_raw_ostream OS(ROS);
4534*82d56013Sjoerg AssemblyWriter W(OS, SlotTable, this->getModule(), AAW,
4535*82d56013Sjoerg IsForDebug,
4536*82d56013Sjoerg ShouldPreserveUseListOrder);
4537*82d56013Sjoerg W.printBasicBlock(this);
4538*82d56013Sjoerg }
4539*82d56013Sjoerg
print(raw_ostream & ROS,AssemblyAnnotationWriter * AAW,bool ShouldPreserveUseListOrder,bool IsForDebug) const45407330f729Sjoerg void Module::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW,
45417330f729Sjoerg bool ShouldPreserveUseListOrder, bool IsForDebug) const {
45427330f729Sjoerg SlotTracker SlotTable(this);
45437330f729Sjoerg formatted_raw_ostream OS(ROS);
45447330f729Sjoerg AssemblyWriter W(OS, SlotTable, this, AAW, IsForDebug,
45457330f729Sjoerg ShouldPreserveUseListOrder);
45467330f729Sjoerg W.printModule(this);
45477330f729Sjoerg }
45487330f729Sjoerg
print(raw_ostream & ROS,bool IsForDebug) const45497330f729Sjoerg void NamedMDNode::print(raw_ostream &ROS, bool IsForDebug) const {
45507330f729Sjoerg SlotTracker SlotTable(getParent());
45517330f729Sjoerg formatted_raw_ostream OS(ROS);
45527330f729Sjoerg AssemblyWriter W(OS, SlotTable, getParent(), nullptr, IsForDebug);
45537330f729Sjoerg W.printNamedMDNode(this);
45547330f729Sjoerg }
45557330f729Sjoerg
print(raw_ostream & ROS,ModuleSlotTracker & MST,bool IsForDebug) const45567330f729Sjoerg void NamedMDNode::print(raw_ostream &ROS, ModuleSlotTracker &MST,
45577330f729Sjoerg bool IsForDebug) const {
45587330f729Sjoerg Optional<SlotTracker> LocalST;
45597330f729Sjoerg SlotTracker *SlotTable;
45607330f729Sjoerg if (auto *ST = MST.getMachine())
45617330f729Sjoerg SlotTable = ST;
45627330f729Sjoerg else {
45637330f729Sjoerg LocalST.emplace(getParent());
45647330f729Sjoerg SlotTable = &*LocalST;
45657330f729Sjoerg }
45667330f729Sjoerg
45677330f729Sjoerg formatted_raw_ostream OS(ROS);
45687330f729Sjoerg AssemblyWriter W(OS, *SlotTable, getParent(), nullptr, IsForDebug);
45697330f729Sjoerg W.printNamedMDNode(this);
45707330f729Sjoerg }
45717330f729Sjoerg
print(raw_ostream & ROS,bool) const45727330f729Sjoerg void Comdat::print(raw_ostream &ROS, bool /*IsForDebug*/) const {
45737330f729Sjoerg PrintLLVMName(ROS, getName(), ComdatPrefix);
45747330f729Sjoerg ROS << " = comdat ";
45757330f729Sjoerg
45767330f729Sjoerg switch (getSelectionKind()) {
45777330f729Sjoerg case Comdat::Any:
45787330f729Sjoerg ROS << "any";
45797330f729Sjoerg break;
45807330f729Sjoerg case Comdat::ExactMatch:
45817330f729Sjoerg ROS << "exactmatch";
45827330f729Sjoerg break;
45837330f729Sjoerg case Comdat::Largest:
45847330f729Sjoerg ROS << "largest";
45857330f729Sjoerg break;
45867330f729Sjoerg case Comdat::NoDuplicates:
45877330f729Sjoerg ROS << "noduplicates";
45887330f729Sjoerg break;
45897330f729Sjoerg case Comdat::SameSize:
45907330f729Sjoerg ROS << "samesize";
45917330f729Sjoerg break;
45927330f729Sjoerg }
45937330f729Sjoerg
45947330f729Sjoerg ROS << '\n';
45957330f729Sjoerg }
45967330f729Sjoerg
print(raw_ostream & OS,bool,bool NoDetails) const45977330f729Sjoerg void Type::print(raw_ostream &OS, bool /*IsForDebug*/, bool NoDetails) const {
45987330f729Sjoerg TypePrinting TP;
45997330f729Sjoerg TP.print(const_cast<Type*>(this), OS);
46007330f729Sjoerg
46017330f729Sjoerg if (NoDetails)
46027330f729Sjoerg return;
46037330f729Sjoerg
46047330f729Sjoerg // If the type is a named struct type, print the body as well.
46057330f729Sjoerg if (StructType *STy = dyn_cast<StructType>(const_cast<Type*>(this)))
46067330f729Sjoerg if (!STy->isLiteral()) {
46077330f729Sjoerg OS << " = type ";
46087330f729Sjoerg TP.printStructBody(STy, OS);
46097330f729Sjoerg }
46107330f729Sjoerg }
46117330f729Sjoerg
isReferencingMDNode(const Instruction & I)46127330f729Sjoerg static bool isReferencingMDNode(const Instruction &I) {
46137330f729Sjoerg if (const auto *CI = dyn_cast<CallInst>(&I))
46147330f729Sjoerg if (Function *F = CI->getCalledFunction())
46157330f729Sjoerg if (F->isIntrinsic())
46167330f729Sjoerg for (auto &Op : I.operands())
46177330f729Sjoerg if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
46187330f729Sjoerg if (isa<MDNode>(V->getMetadata()))
46197330f729Sjoerg return true;
46207330f729Sjoerg return false;
46217330f729Sjoerg }
46227330f729Sjoerg
print(raw_ostream & ROS,bool IsForDebug) const46237330f729Sjoerg void Value::print(raw_ostream &ROS, bool IsForDebug) const {
46247330f729Sjoerg bool ShouldInitializeAllMetadata = false;
46257330f729Sjoerg if (auto *I = dyn_cast<Instruction>(this))
46267330f729Sjoerg ShouldInitializeAllMetadata = isReferencingMDNode(*I);
46277330f729Sjoerg else if (isa<Function>(this) || isa<MetadataAsValue>(this))
46287330f729Sjoerg ShouldInitializeAllMetadata = true;
46297330f729Sjoerg
46307330f729Sjoerg ModuleSlotTracker MST(getModuleFromVal(this), ShouldInitializeAllMetadata);
46317330f729Sjoerg print(ROS, MST, IsForDebug);
46327330f729Sjoerg }
46337330f729Sjoerg
print(raw_ostream & ROS,ModuleSlotTracker & MST,bool IsForDebug) const46347330f729Sjoerg void Value::print(raw_ostream &ROS, ModuleSlotTracker &MST,
46357330f729Sjoerg bool IsForDebug) const {
46367330f729Sjoerg formatted_raw_ostream OS(ROS);
46377330f729Sjoerg SlotTracker EmptySlotTable(static_cast<const Module *>(nullptr));
46387330f729Sjoerg SlotTracker &SlotTable =
46397330f729Sjoerg MST.getMachine() ? *MST.getMachine() : EmptySlotTable;
46407330f729Sjoerg auto incorporateFunction = [&](const Function *F) {
46417330f729Sjoerg if (F)
46427330f729Sjoerg MST.incorporateFunction(*F);
46437330f729Sjoerg };
46447330f729Sjoerg
46457330f729Sjoerg if (const Instruction *I = dyn_cast<Instruction>(this)) {
46467330f729Sjoerg incorporateFunction(I->getParent() ? I->getParent()->getParent() : nullptr);
46477330f729Sjoerg AssemblyWriter W(OS, SlotTable, getModuleFromVal(I), nullptr, IsForDebug);
46487330f729Sjoerg W.printInstruction(*I);
46497330f729Sjoerg } else if (const BasicBlock *BB = dyn_cast<BasicBlock>(this)) {
46507330f729Sjoerg incorporateFunction(BB->getParent());
46517330f729Sjoerg AssemblyWriter W(OS, SlotTable, getModuleFromVal(BB), nullptr, IsForDebug);
46527330f729Sjoerg W.printBasicBlock(BB);
46537330f729Sjoerg } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(this)) {
46547330f729Sjoerg AssemblyWriter W(OS, SlotTable, GV->getParent(), nullptr, IsForDebug);
46557330f729Sjoerg if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
46567330f729Sjoerg W.printGlobal(V);
46577330f729Sjoerg else if (const Function *F = dyn_cast<Function>(GV))
46587330f729Sjoerg W.printFunction(F);
46597330f729Sjoerg else
46607330f729Sjoerg W.printIndirectSymbol(cast<GlobalIndirectSymbol>(GV));
46617330f729Sjoerg } else if (const MetadataAsValue *V = dyn_cast<MetadataAsValue>(this)) {
46627330f729Sjoerg V->getMetadata()->print(ROS, MST, getModuleFromVal(V));
46637330f729Sjoerg } else if (const Constant *C = dyn_cast<Constant>(this)) {
46647330f729Sjoerg TypePrinting TypePrinter;
46657330f729Sjoerg TypePrinter.print(C->getType(), OS);
46667330f729Sjoerg OS << ' ';
46677330f729Sjoerg WriteConstantInternal(OS, C, TypePrinter, MST.getMachine(), nullptr);
46687330f729Sjoerg } else if (isa<InlineAsm>(this) || isa<Argument>(this)) {
46697330f729Sjoerg this->printAsOperand(OS, /* PrintType */ true, MST);
46707330f729Sjoerg } else {
46717330f729Sjoerg llvm_unreachable("Unknown value to print out!");
46727330f729Sjoerg }
46737330f729Sjoerg }
46747330f729Sjoerg
46757330f729Sjoerg /// Print without a type, skipping the TypePrinting object.
46767330f729Sjoerg ///
46777330f729Sjoerg /// \return \c true iff printing was successful.
printWithoutType(const Value & V,raw_ostream & O,SlotTracker * Machine,const Module * M)46787330f729Sjoerg static bool printWithoutType(const Value &V, raw_ostream &O,
46797330f729Sjoerg SlotTracker *Machine, const Module *M) {
46807330f729Sjoerg if (V.hasName() || isa<GlobalValue>(V) ||
46817330f729Sjoerg (!isa<Constant>(V) && !isa<MetadataAsValue>(V))) {
46827330f729Sjoerg WriteAsOperandInternal(O, &V, nullptr, Machine, M);
46837330f729Sjoerg return true;
46847330f729Sjoerg }
46857330f729Sjoerg return false;
46867330f729Sjoerg }
46877330f729Sjoerg
printAsOperandImpl(const Value & V,raw_ostream & O,bool PrintType,ModuleSlotTracker & MST)46887330f729Sjoerg static void printAsOperandImpl(const Value &V, raw_ostream &O, bool PrintType,
46897330f729Sjoerg ModuleSlotTracker &MST) {
46907330f729Sjoerg TypePrinting TypePrinter(MST.getModule());
46917330f729Sjoerg if (PrintType) {
46927330f729Sjoerg TypePrinter.print(V.getType(), O);
46937330f729Sjoerg O << ' ';
46947330f729Sjoerg }
46957330f729Sjoerg
46967330f729Sjoerg WriteAsOperandInternal(O, &V, &TypePrinter, MST.getMachine(),
46977330f729Sjoerg MST.getModule());
46987330f729Sjoerg }
46997330f729Sjoerg
printAsOperand(raw_ostream & O,bool PrintType,const Module * M) const47007330f729Sjoerg void Value::printAsOperand(raw_ostream &O, bool PrintType,
47017330f729Sjoerg const Module *M) const {
47027330f729Sjoerg if (!M)
47037330f729Sjoerg M = getModuleFromVal(this);
47047330f729Sjoerg
47057330f729Sjoerg if (!PrintType)
47067330f729Sjoerg if (printWithoutType(*this, O, nullptr, M))
47077330f729Sjoerg return;
47087330f729Sjoerg
47097330f729Sjoerg SlotTracker Machine(
47107330f729Sjoerg M, /* ShouldInitializeAllMetadata */ isa<MetadataAsValue>(this));
47117330f729Sjoerg ModuleSlotTracker MST(Machine, M);
47127330f729Sjoerg printAsOperandImpl(*this, O, PrintType, MST);
47137330f729Sjoerg }
47147330f729Sjoerg
printAsOperand(raw_ostream & O,bool PrintType,ModuleSlotTracker & MST) const47157330f729Sjoerg void Value::printAsOperand(raw_ostream &O, bool PrintType,
47167330f729Sjoerg ModuleSlotTracker &MST) const {
47177330f729Sjoerg if (!PrintType)
47187330f729Sjoerg if (printWithoutType(*this, O, MST.getMachine(), MST.getModule()))
47197330f729Sjoerg return;
47207330f729Sjoerg
47217330f729Sjoerg printAsOperandImpl(*this, O, PrintType, MST);
47227330f729Sjoerg }
47237330f729Sjoerg
printMetadataImpl(raw_ostream & ROS,const Metadata & MD,ModuleSlotTracker & MST,const Module * M,bool OnlyAsOperand)47247330f729Sjoerg static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,
47257330f729Sjoerg ModuleSlotTracker &MST, const Module *M,
47267330f729Sjoerg bool OnlyAsOperand) {
47277330f729Sjoerg formatted_raw_ostream OS(ROS);
47287330f729Sjoerg
47297330f729Sjoerg TypePrinting TypePrinter(M);
47307330f729Sjoerg
47317330f729Sjoerg WriteAsOperandInternal(OS, &MD, &TypePrinter, MST.getMachine(), M,
47327330f729Sjoerg /* FromValue */ true);
47337330f729Sjoerg
47347330f729Sjoerg auto *N = dyn_cast<MDNode>(&MD);
4735*82d56013Sjoerg if (OnlyAsOperand || !N || isa<DIExpression>(MD) || isa<DIArgList>(MD))
47367330f729Sjoerg return;
47377330f729Sjoerg
47387330f729Sjoerg OS << " = ";
47397330f729Sjoerg WriteMDNodeBodyInternal(OS, N, &TypePrinter, MST.getMachine(), M);
47407330f729Sjoerg }
47417330f729Sjoerg
printAsOperand(raw_ostream & OS,const Module * M) const47427330f729Sjoerg void Metadata::printAsOperand(raw_ostream &OS, const Module *M) const {
47437330f729Sjoerg ModuleSlotTracker MST(M, isa<MDNode>(this));
47447330f729Sjoerg printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ true);
47457330f729Sjoerg }
47467330f729Sjoerg
printAsOperand(raw_ostream & OS,ModuleSlotTracker & MST,const Module * M) const47477330f729Sjoerg void Metadata::printAsOperand(raw_ostream &OS, ModuleSlotTracker &MST,
47487330f729Sjoerg const Module *M) const {
47497330f729Sjoerg printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ true);
47507330f729Sjoerg }
47517330f729Sjoerg
print(raw_ostream & OS,const Module * M,bool) const47527330f729Sjoerg void Metadata::print(raw_ostream &OS, const Module *M,
47537330f729Sjoerg bool /*IsForDebug*/) const {
47547330f729Sjoerg ModuleSlotTracker MST(M, isa<MDNode>(this));
47557330f729Sjoerg printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false);
47567330f729Sjoerg }
47577330f729Sjoerg
print(raw_ostream & OS,ModuleSlotTracker & MST,const Module * M,bool) const47587330f729Sjoerg void Metadata::print(raw_ostream &OS, ModuleSlotTracker &MST,
47597330f729Sjoerg const Module *M, bool /*IsForDebug*/) const {
47607330f729Sjoerg printMetadataImpl(OS, *this, MST, M, /* OnlyAsOperand */ false);
47617330f729Sjoerg }
47627330f729Sjoerg
print(raw_ostream & ROS,bool IsForDebug) const47637330f729Sjoerg void ModuleSummaryIndex::print(raw_ostream &ROS, bool IsForDebug) const {
47647330f729Sjoerg SlotTracker SlotTable(this);
47657330f729Sjoerg formatted_raw_ostream OS(ROS);
47667330f729Sjoerg AssemblyWriter W(OS, SlotTable, this, IsForDebug);
47677330f729Sjoerg W.printModuleSummaryIndex();
47687330f729Sjoerg }
47697330f729Sjoerg
47707330f729Sjoerg #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
47717330f729Sjoerg // Value::dump - allow easy printing of Values from the debugger.
47727330f729Sjoerg LLVM_DUMP_METHOD
dump() const47737330f729Sjoerg void Value::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; }
47747330f729Sjoerg
47757330f729Sjoerg // Type::dump - allow easy printing of Types from the debugger.
47767330f729Sjoerg LLVM_DUMP_METHOD
dump() const47777330f729Sjoerg void Type::dump() const { print(dbgs(), /*IsForDebug=*/true); dbgs() << '\n'; }
47787330f729Sjoerg
47797330f729Sjoerg // Module::dump() - Allow printing of Modules from the debugger.
47807330f729Sjoerg LLVM_DUMP_METHOD
dump() const47817330f729Sjoerg void Module::dump() const {
47827330f729Sjoerg print(dbgs(), nullptr,
47837330f729Sjoerg /*ShouldPreserveUseListOrder=*/false, /*IsForDebug=*/true);
47847330f729Sjoerg }
47857330f729Sjoerg
47867330f729Sjoerg // Allow printing of Comdats from the debugger.
47877330f729Sjoerg LLVM_DUMP_METHOD
dump() const47887330f729Sjoerg void Comdat::dump() const { print(dbgs(), /*IsForDebug=*/true); }
47897330f729Sjoerg
47907330f729Sjoerg // NamedMDNode::dump() - Allow printing of NamedMDNodes from the debugger.
47917330f729Sjoerg LLVM_DUMP_METHOD
dump() const47927330f729Sjoerg void NamedMDNode::dump() const { print(dbgs(), /*IsForDebug=*/true); }
47937330f729Sjoerg
47947330f729Sjoerg LLVM_DUMP_METHOD
dump() const47957330f729Sjoerg void Metadata::dump() const { dump(nullptr); }
47967330f729Sjoerg
47977330f729Sjoerg LLVM_DUMP_METHOD
dump(const Module * M) const47987330f729Sjoerg void Metadata::dump(const Module *M) const {
47997330f729Sjoerg print(dbgs(), M, /*IsForDebug=*/true);
48007330f729Sjoerg dbgs() << '\n';
48017330f729Sjoerg }
48027330f729Sjoerg
48037330f729Sjoerg // Allow printing of ModuleSummaryIndex from the debugger.
48047330f729Sjoerg LLVM_DUMP_METHOD
dump() const48057330f729Sjoerg void ModuleSummaryIndex::dump() const { print(dbgs(), /*IsForDebug=*/true); }
48067330f729Sjoerg #endif
4807