// Helper Functions
//===----------------------------------------------------------------------===//
+namespace {
+struct OrderMap {
+ DenseMap<const Value *, std::pair<unsigned, bool>> IDs;
+
+ unsigned size() const { return IDs.size(); }
+ std::pair<unsigned, bool> &operator[](const Value *V) { return IDs[V]; }
+ std::pair<unsigned, bool> lookup(const Value *V) const {
+ return IDs.lookup(V);
+ }
+ void index(const Value *V) {
+ // Explicitly sequence get-size and insert-value operations to avoid UB.
+ unsigned ID = IDs.size() + 1;
+ IDs[V].first = ID;
+ }
+};
+}
+
+static void orderValue(const Value *V, OrderMap &OM) {
+ if (OM.lookup(V).first)
+ return;
+
+ if (const Constant *C = dyn_cast<Constant>(V))
+ if (C->getNumOperands() && !isa<GlobalValue>(C))
+ for (const Value *Op : C->operands())
+ if (!isa<BasicBlock>(Op) && !isa<GlobalValue>(Op))
+ orderValue(Op, OM);
+
+ // Note: we cannot cache this lookup above, since inserting into the map
+ // changes the map's size, and thus affects the other IDs.
+ OM.index(V);
+}
+
+static OrderMap orderModule(const Module *M) {
+ // This needs to match the order used by ValueEnumerator::ValueEnumerator()
+ // and ValueEnumerator::incorporateFunction().
+ OrderMap OM;
+
+ for (const GlobalVariable &G : M->globals()) {
+ if (G.hasInitializer())
+ if (!isa<GlobalValue>(G.getInitializer()))
+ orderValue(G.getInitializer(), OM);
+ orderValue(&G, OM);
+ }
+ for (const GlobalAlias &A : M->aliases()) {
+ if (!isa<GlobalValue>(A.getAliasee()))
+ orderValue(A.getAliasee(), OM);
+ orderValue(&A, OM);
+ }
+ for (const Function &F : *M) {
+ if (F.hasPrefixData())
+ if (!isa<GlobalValue>(F.getPrefixData()))
+ orderValue(F.getPrefixData(), OM);
+
+ if (F.hasPrologueData())
+ if (!isa<GlobalValue>(F.getPrologueData()))
+ orderValue(F.getPrologueData(), OM);
+
+ orderValue(&F, OM);
+
+ if (F.isDeclaration())
+ continue;
+
+ for (const Argument &A : F.args())
+ orderValue(&A, OM);
+ for (const BasicBlock &BB : F) {
+ orderValue(&BB, OM);
+ for (const Instruction &I : BB) {
+ for (const Value *Op : I.operands())
+ if ((isa<Constant>(*Op) && !isa<GlobalValue>(*Op)) ||
+ isa<InlineAsm>(*Op))
+ orderValue(Op, OM);
+ orderValue(&I, OM);
+ }
+ }
+ }
+ return OM;
+}
+
+static void predictValueUseListOrderImpl(const Value *V, const Function *F,
+ unsigned ID, const OrderMap &OM,
+ UseListOrderStack &Stack) {
+ // Predict use-list order for this one.
+ typedef std::pair<const Use *, unsigned> Entry;
+ SmallVector<Entry, 64> List;
+ for (const Use &U : V->uses())
+ // Check if this user will be serialized.
+ if (OM.lookup(U.getUser()).first)
+ List.push_back(std::make_pair(&U, List.size()));
+
+ if (List.size() < 2)
+ // We may have lost some users.
+ return;
+
+ bool GetsReversed =
+ !isa<GlobalVariable>(V) && !isa<Function>(V) && !isa<BasicBlock>(V);
+ if (auto *BA = dyn_cast<BlockAddress>(V))
+ ID = OM.lookup(BA->getBasicBlock()).first;
+ std::sort(List.begin(), List.end(), [&](const Entry &L, const Entry &R) {
+ const Use *LU = L.first;
+ const Use *RU = R.first;
+ if (LU == RU)
+ return false;
+
+ auto LID = OM.lookup(LU->getUser()).first;
+ auto RID = OM.lookup(RU->getUser()).first;
+
+ // If ID is 4, then expect: 7 6 5 1 2 3.
+ if (LID < RID) {
+ if (GetsReversed)
+ if (RID <= ID)
+ return true;
+ return false;
+ }
+ if (RID < LID) {
+ if (GetsReversed)
+ if (LID <= ID)
+ return false;
+ return true;
+ }
+
+ // LID and RID are equal, so we have different operands of the same user.
+ // Assume operands are added in order for all instructions.
+ if (GetsReversed)
+ if (LID <= ID)
+ return LU->getOperandNo() < RU->getOperandNo();
+ return LU->getOperandNo() > RU->getOperandNo();
+ });
+
+ if (std::is_sorted(
+ List.begin(), List.end(),
+ [](const Entry &L, const Entry &R) { return L.second < R.second; }))
+ // Order is already correct.
+ return;
+
+ // Store the shuffle.
+ Stack.emplace_back(V, F, List.size());
+ assert(List.size() == Stack.back().Shuffle.size() && "Wrong size");
+ for (size_t I = 0, E = List.size(); I != E; ++I)
+ Stack.back().Shuffle[I] = List[I].second;
+}
+
+static void predictValueUseListOrder(const Value *V, const Function *F,
+ OrderMap &OM, UseListOrderStack &Stack) {
+ auto &IDPair = OM[V];
+ assert(IDPair.first && "Unmapped value");
+ if (IDPair.second)
+ // Already predicted.
+ return;
+
+ // Do the actual prediction.
+ IDPair.second = true;
+ if (!V->use_empty() && std::next(V->use_begin()) != V->use_end())
+ predictValueUseListOrderImpl(V, F, IDPair.first, OM, Stack);
+
+ // Recursive descent into constants.
+ if (const Constant *C = dyn_cast<Constant>(V))
+ if (C->getNumOperands()) // Visit GlobalValues.
+ for (const Value *Op : C->operands())
+ if (isa<Constant>(Op)) // Visit GlobalValues.
+ predictValueUseListOrder(Op, F, OM, Stack);
+}
+
+static UseListOrderStack predictUseListOrder(const Module *M) {
+ OrderMap OM = orderModule(M);
+
+ // Use-list orders need to be serialized after all the users have been added
+ // to a value, or else the shuffles will be incomplete. Store them per
+ // function in a stack.
+ //
+ // Aside from function order, the order of values doesn't matter much here.
+ UseListOrderStack Stack;
+
+ // We want to visit the functions backward now so we can list function-local
+ // constants in the last Function they're used in. Module-level constants
+ // have already been visited above.
+ for (auto I = M->rbegin(), E = M->rend(); I != E; ++I) {
+ const Function &F = *I;
+ if (F.isDeclaration())
+ continue;
+ for (const BasicBlock &BB : F)
+ predictValueUseListOrder(&BB, &F, OM, Stack);
+ for (const Argument &A : F.args())
+ predictValueUseListOrder(&A, &F, OM, Stack);
+ for (const BasicBlock &BB : F)
+ for (const Instruction &I : BB)
+ for (const Value *Op : I.operands())
+ if (isa<Constant>(*Op) || isa<InlineAsm>(*Op)) // Visit GlobalValues.
+ predictValueUseListOrder(Op, &F, OM, Stack);
+ for (const BasicBlock &BB : F)
+ for (const Instruction &I : BB)
+ predictValueUseListOrder(&I, &F, OM, Stack);
+ }
+
+ // Visit globals last.
+ for (const GlobalVariable &G : M->globals())
+ predictValueUseListOrder(&G, nullptr, OM, Stack);
+ for (const Function &F : *M)
+ predictValueUseListOrder(&F, nullptr, OM, Stack);
+ for (const GlobalAlias &A : M->aliases())
+ predictValueUseListOrder(&A, nullptr, OM, Stack);
+ for (const GlobalVariable &G : M->globals())
+ if (G.hasInitializer())
+ predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack);
+ for (const GlobalAlias &A : M->aliases())
+ predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack);
+ for (const Function &F : *M)
+ if (F.hasPrefixData())
+ predictValueUseListOrder(F.getPrefixData(), nullptr, OM, Stack);
+
+ return Stack;
+}
+
static const Module *getModuleFromVal(const Value *V) {
if (const Argument *MA = dyn_cast<Argument>(V))
return MA->getParent() ? MA->getParent()->getParent() : nullptr;
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
return GV->getParent();
+
+ if (const auto *MAV = dyn_cast<MetadataAsValue>(V)) {
+ for (const User *U : MAV->users())
+ if (isa<Instruction>(U))
+ if (const Module *M = getModuleFromVal(U))
+ return M;
+ return nullptr;
+ }
+
return nullptr;
}
case CallingConv::AnyReg: Out << "anyregcc"; break;
case CallingConv::PreserveMost: Out << "preserve_mostcc"; break;
case CallingConv::PreserveAll: Out << "preserve_allcc"; break;
+ case CallingConv::GHC: Out << "ghccc"; break;
case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break;
case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break;
case CallingConv::X86_ThisCall: Out << "x86_thiscallcc"; break;
+ case CallingConv::X86_VectorCall:Out << "x86_vectorcallcc"; break;
case CallingConv::Intel_OCL_BI: Out << "intel_ocl_bicc"; break;
case CallingConv::ARM_APCS: Out << "arm_apcscc"; break;
case CallingConv::ARM_AAPCS: Out << "arm_aapcscc"; break;
enum PrefixType {
GlobalPrefix,
+ ComdatPrefix,
LabelPrefix,
LocalPrefix,
NoPrefix
switch (Prefix) {
case NoPrefix: break;
case GlobalPrefix: OS << '@'; break;
+ case ComdatPrefix: OS << '$'; break;
case LabelPrefix: break;
case LocalPrefix: OS << '%'; break;
}
/// TheFunction - The function for which we are holding slot numbers.
const Function* TheFunction;
bool FunctionProcessed;
+ bool ShouldInitializeAllMetadata;
/// mMap - The slot map for the module level data.
ValueMap mMap;
DenseMap<AttributeSet, unsigned> asMap;
unsigned asNext;
public:
- /// Construct from a module
- explicit SlotTracker(const Module *M);
+ /// Construct from a module.
+ ///
+ /// If \c ShouldInitializeAllMetadata, initializes all metadata in all
+ /// functions, giving correct numbering for metadata referenced only from
+ /// within a function (even if no functions have been initialized).
+ explicit SlotTracker(const Module *M,
+ bool ShouldInitializeAllMetadata = false);
/// Construct from a function, starting out in incorp state.
- explicit SlotTracker(const Function *F);
+ ///
+ /// If \c ShouldInitializeAllMetadata, initializes all metadata in all
+ /// functions, giving correct numbering for metadata referenced only from
+ /// within a function (even if no functions have been initialized).
+ explicit SlotTracker(const Function *F,
+ bool ShouldInitializeAllMetadata = false);
/// Return the slot number of the specified value in it's type
/// plane. If something is not in the SlotTracker, return -1.
FunctionProcessed = false;
}
+ const Function *getFunction() const { return TheFunction; }
+
/// After calling incorporateFunction, use this method to remove the
/// most recently incorporated function from the SlotTracker. This
/// will reset the state of the machine back to just the module contents.
/// Add all of the functions arguments, basic blocks, and instructions.
void processFunction();
- SlotTracker(const SlotTracker &) LLVM_DELETED_FUNCTION;
- void operator=(const SlotTracker &) LLVM_DELETED_FUNCTION;
+ /// Add all of the metadata from a function.
+ void processFunctionMetadata(const Function &F);
+
+ /// Add all of the metadata from an instruction.
+ void processInstructionMetadata(const Instruction &I);
+
+ SlotTracker(const SlotTracker &) = delete;
+ void operator=(const SlotTracker &) = delete;
};
SlotTracker *createSlotTracker(const Module *M) {
if (const Function *Func = dyn_cast<Function>(V))
return new SlotTracker(Func);
- if (const MDNode *MD = dyn_cast<MDNode>(V)) {
- if (!MD->isFunctionLocal())
- return new SlotTracker(MD->getFunction());
-
- return new SlotTracker((Function *)nullptr);
- }
-
return nullptr;
}
// Module level constructor. Causes the contents of the Module (sans functions)
// to be added to the slot table.
-SlotTracker::SlotTracker(const Module *M)
- : TheModule(M), TheFunction(nullptr), FunctionProcessed(false),
- mNext(0), fNext(0), mdnNext(0), asNext(0) {
-}
+SlotTracker::SlotTracker(const Module *M, bool ShouldInitializeAllMetadata)
+ : TheModule(M), TheFunction(nullptr), FunctionProcessed(false),
+ ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0),
+ fNext(0), mdnNext(0), asNext(0) {}
// Function level constructor. Causes the contents of the Module and the one
// function provided to be added to the slot table.
-SlotTracker::SlotTracker(const Function *F)
- : TheModule(F ? F->getParent() : nullptr), TheFunction(F),
- FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) {
-}
+SlotTracker::SlotTracker(const Function *F, bool ShouldInitializeAllMetadata)
+ : TheModule(F ? F->getParent() : nullptr), TheFunction(F),
+ FunctionProcessed(false),
+ ShouldInitializeAllMetadata(ShouldInitializeAllMetadata), mNext(0),
+ fNext(0), mdnNext(0), asNext(0) {}
inline void SlotTracker::initialize() {
if (TheModule) {
// Add all the unnamed functions to the table.
CreateModuleSlot(I);
+ if (ShouldInitializeAllMetadata)
+ processFunctionMetadata(*I);
+
// Add all the function attributes to the table.
// FIXME: Add attributes of other objects?
AttributeSet FnAttrs = I->getAttributes().getFnAttributes();
ST_DEBUG("Inserting Instructions:\n");
- SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst;
-
// Add all of the basic blocks and instructions with no names.
- for (Function::const_iterator BB = TheFunction->begin(),
- E = TheFunction->end(); BB != E; ++BB) {
- if (!BB->hasName())
- CreateFunctionSlot(BB);
-
- for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E;
- ++I) {
- if (!I->getType()->isVoidTy() && !I->hasName())
- CreateFunctionSlot(I);
-
- // Intrinsics can directly use metadata. We allow direct calls to any
- // llvm.foo function here, because the target may not be linked into the
- // optimizer.
- if (const CallInst *CI = dyn_cast<CallInst>(I)) {
- if (Function *F = CI->getCalledFunction())
- if (F->isIntrinsic())
- for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
- if (MDNode *N = dyn_cast_or_null<MDNode>(I->getOperand(i)))
- CreateMetadataSlot(N);
+ for (auto &BB : *TheFunction) {
+ if (!BB.hasName())
+ CreateFunctionSlot(&BB);
+
+ for (auto &I : BB) {
+ if (!I.getType()->isVoidTy() && !I.hasName())
+ CreateFunctionSlot(&I);
+ processInstructionMetadata(I);
+
+ // We allow direct calls to any llvm.foo function here, because the
+ // target may not be linked into the optimizer.
+ if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
// Add all the call attributes to the table.
AttributeSet Attrs = CI->getAttributes().getFnAttributes();
if (Attrs.hasAttributes(AttributeSet::FunctionIndex))
CreateAttributeSetSlot(Attrs);
- } else if (const InvokeInst *II = dyn_cast<InvokeInst>(I)) {
+ } else if (const InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
// Add all the call attributes to the table.
AttributeSet Attrs = II->getAttributes().getFnAttributes();
if (Attrs.hasAttributes(AttributeSet::FunctionIndex))
CreateAttributeSetSlot(Attrs);
}
-
- // Process metadata attached with this instruction.
- I->getAllMetadata(MDForInst);
- for (unsigned i = 0, e = MDForInst.size(); i != e; ++i)
- CreateMetadataSlot(MDForInst[i].second);
- MDForInst.clear();
}
}
ST_DEBUG("end processFunction!\n");
}
+void SlotTracker::processFunctionMetadata(const Function &F) {
+ for (auto &BB : F)
+ for (auto &I : BB)
+ processInstructionMetadata(I);
+}
+
+void SlotTracker::processInstructionMetadata(const Instruction &I) {
+ // Process metadata used directly by intrinsics.
+ if (const CallInst *CI = dyn_cast<CallInst>(&I))
+ if (Function *F = CI->getCalledFunction())
+ if (F->isIntrinsic())
+ for (auto &Op : I.operands())
+ if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
+ if (MDNode *N = dyn_cast<MDNode>(V->getMetadata()))
+ CreateMetadataSlot(N);
+
+ // Process metadata attached to this instruction.
+ SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+ I.getAllMetadata(MDs);
+ for (auto &MD : MDs)
+ CreateMetadataSlot(MD.second);
+}
+
/// Clean up after incorporating a function. This is the only way to get out of
/// the function incorporation state that affects get*Slot/Create*Slot. Function
/// incorporation state is indicated by TheFunction != 0.
void SlotTracker::CreateMetadataSlot(const MDNode *N) {
assert(N && "Can't insert a null Value into SlotTracker!");
- // Don't insert if N is a function-local metadata, these are always printed
- // inline.
- if (!N->isFunctionLocal()) {
- mdn_iterator I = mdnMap.find(N);
- if (I != mdnMap.end())
- return;
-
- unsigned DestSlot = mdnNext++;
- mdnMap[N] = DestSlot;
- }
+ unsigned DestSlot = mdnNext;
+ if (!mdnMap.insert(std::make_pair(N, DestSlot)).second)
+ return;
+ ++mdnNext;
// Recursively add any MDNodes referenced by operands.
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
SlotTracker *Machine,
const Module *Context);
+static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context,
+ bool FromValue = false);
+
static const char *getPredicateText(unsigned predicate) {
const char * pred = "unknown";
switch (predicate) {
(StrVal[1] >= '0' && StrVal[1] <= '9'))) {
// Reparse stringized version!
if (APFloat(APFloat::IEEEdouble, StrVal).convertToDouble() == Val) {
- Out << StrVal.str();
+ Out << StrVal;
return;
}
}
Out << ' ' << getPredicateText(CE->getPredicate());
Out << " (";
+ if (const GEPOperator *GEP = dyn_cast<GEPOperator>(CE)) {
+ TypePrinter.print(
+ cast<PointerType>(GEP->getPointerOperandType()->getScalarType())
+ ->getElementType(),
+ Out);
+ Out << ", ";
+ }
+
for (User::const_op_iterator OI=CE->op_begin(); OI != CE->op_end(); ++OI) {
TypePrinter.print((*OI)->getType(), Out);
Out << ' ';
Out << "<placeholder or erroneous Constant>";
}
-static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
- TypePrinting *TypePrinter,
- SlotTracker *Machine,
- const Module *Context) {
+static void writeMDTuple(raw_ostream &Out, const MDTuple *Node,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
Out << "!{";
for (unsigned mi = 0, me = Node->getNumOperands(); mi != me; ++mi) {
- const Value *V = Node->getOperand(mi);
- if (!V)
+ const Metadata *MD = Node->getOperand(mi);
+ if (!MD)
Out << "null";
- else {
+ else if (auto *MDV = dyn_cast<ValueAsMetadata>(MD)) {
+ Value *V = MDV->getValue();
TypePrinter->print(V->getType(), Out);
Out << ' ';
- WriteAsOperandInternal(Out, Node->getOperand(mi),
- TypePrinter, Machine, Context);
+ WriteAsOperandInternal(Out, V, TypePrinter, Machine, Context);
+ } else {
+ WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context);
}
if (mi + 1 != me)
Out << ", ";
Out << "}";
}
+namespace {
+struct FieldSeparator {
+ bool Skip;
+ const char *Sep;
+ FieldSeparator(const char *Sep = ", ") : Skip(true), Sep(Sep) {}
+};
+raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) {
+ if (FS.Skip) {
+ FS.Skip = false;
+ return OS;
+ }
+ return OS << FS.Sep;
+}
+} // end namespace
+
+static void writeMetadataAsOperand(raw_ostream &Out, const Metadata *MD,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine,
+ const Module *Context) {
+ if (!MD) {
+ Out << "null";
+ return;
+ }
+ WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context);
+}
+
+static void writeTag(raw_ostream &Out, FieldSeparator &FS, const DebugNode *N) {
+ Out << FS << "tag: ";
+ if (const char *Tag = dwarf::TagString(N->getTag()))
+ Out << Tag;
+ else
+ Out << N->getTag();
+}
+
+static void writeStringField(raw_ostream &Out, FieldSeparator &FS,
+ StringRef Name, StringRef Value,
+ bool ShouldSkipEmpty = true) {
+ if (ShouldSkipEmpty && Value.empty())
+ return;
+
+ Out << FS << Name << ": \"";
+ PrintEscapedString(Value, Out);
+ Out << "\"";
+}
+
+static void writeGenericDebugNode(raw_ostream &Out, const GenericDebugNode *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context) {
+ Out << "!GenericDebugNode(";
+ FieldSeparator FS;
+ writeTag(Out, FS, N);
+ writeStringField(Out, FS, "header", N->getHeader());
+ if (N->getNumDwarfOperands()) {
+ Out << FS << "operands: {";
+ FieldSeparator IFS;
+ for (auto &I : N->dwarf_operands()) {
+ Out << IFS;
+ writeMetadataAsOperand(Out, I, TypePrinter, Machine, Context);
+ }
+ Out << "}";
+ }
+ Out << ")";
+}
+
+static void writeMDLocation(raw_ostream &Out, const MDLocation *DL,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDLocation(";
+ FieldSeparator FS;
+ // Always output the line, since 0 is a relevant and important value for it.
+ Out << FS << "line: " << DL->getLine();
+ if (DL->getColumn())
+ Out << FS << "column: " << DL->getColumn();
+ Out << FS << "scope: ";
+ WriteAsOperandInternal(Out, DL->getScope(), TypePrinter, Machine, Context);
+ if (DL->getInlinedAt()) {
+ Out << FS << "inlinedAt: ";
+ WriteAsOperandInternal(Out, DL->getInlinedAt(), TypePrinter, Machine,
+ Context);
+ }
+ Out << ")";
+}
+
+static void writeMDSubrange(raw_ostream &Out, const MDSubrange *N,
+ TypePrinting *, SlotTracker *, const Module *) {
+ Out << "!MDSubrange(";
+ FieldSeparator FS;
+ Out << FS << "count: " << N->getCount();
+ if (N->getLo())
+ Out << FS << "lowerBound: " << N->getLo();
+ Out << ")";
+}
+
+static void writeMDEnumerator(raw_ostream &Out, const MDEnumerator *N,
+ TypePrinting *, SlotTracker *, const Module *) {
+ Out << "!MDEnumerator(";
+ FieldSeparator FS;
+ writeStringField(Out, FS, "name", N->getName(), /* ShouldSkipEmpty */ false);
+ Out << FS << "value: " << N->getValue();
+ Out << ")";
+}
+
+static void writeMDBasicType(raw_ostream &Out, const MDBasicType *N,
+ TypePrinting *, SlotTracker *, const Module *) {
+ Out << "!MDBasicType(";
+ FieldSeparator FS;
+ if (N->getTag() != dwarf::DW_TAG_base_type)
+ writeTag(Out, FS, N);
+ writeStringField(Out, FS, "name", N->getName());
+ if (N->getSizeInBits())
+ Out << FS << "size: " << N->getSizeInBits();
+ if (N->getAlignInBits())
+ Out << FS << "align: " << N->getAlignInBits();
+ if (unsigned Encoding = N->getEncoding()) {
+ Out << FS << "encoding: ";
+ if (const char *S = dwarf::AttributeEncodingString(Encoding))
+ Out << S;
+ else
+ Out << Encoding;
+ }
+ Out << ")";
+}
+
+static void writeDIFlags(raw_ostream &Out, unsigned Flags) {
+ SmallVector<unsigned, 8> SplitFlags;
+ unsigned Extra = DIDescriptor::splitFlags(Flags, SplitFlags);
+
+ FieldSeparator FS(" | ");
+ for (unsigned F : SplitFlags) {
+ const char *StringF = DIDescriptor::getFlagString(F);
+ assert(StringF && "Expected valid flag");
+ Out << FS << StringF;
+ }
+ if (Extra || SplitFlags.empty())
+ Out << FS << Extra;
+}
+
+static void writeMDDerivedType(raw_ostream &Out, const MDDerivedType *N,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDDerivedType(";
+ FieldSeparator FS;
+ writeTag(Out, FS, N);
+ writeStringField(Out, FS, "name", N->getName());
+ if (N->getScope()) {
+ Out << FS << "scope: ";
+ writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+ }
+ if (N->getFile()) {
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getLine())
+ Out << FS << "line: " << N->getLine();
+ Out << FS << "baseType: ";
+ writeMetadataAsOperand(Out, N->getBaseType(), TypePrinter, Machine, Context);
+ if (N->getSizeInBits())
+ Out << FS << "size: " << N->getSizeInBits();
+ if (N->getAlignInBits())
+ Out << FS << "align: " << N->getAlignInBits();
+ if (N->getOffsetInBits())
+ Out << FS << "offset: " << N->getOffsetInBits();
+ if (auto Flags = N->getFlags()) {
+ Out << FS << "flags: ";
+ writeDIFlags(Out, Flags);
+ }
+ if (N->getExtraData()) {
+ Out << FS << "extraData: ";
+ writeMetadataAsOperand(Out, N->getExtraData(), TypePrinter, Machine,
+ Context);
+ }
+ Out << ")";
+}
+
+static void writeMDCompositeType(raw_ostream &Out, const MDCompositeType *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context) {
+ Out << "!MDCompositeType(";
+ FieldSeparator FS;
+ writeTag(Out, FS, N);
+ writeStringField(Out, FS, "name", N->getName());
+ if (N->getScope()) {
+ Out << FS << "scope: ";
+ writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+ }
+ if (N->getFile()) {
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getLine())
+ Out << FS << "line: " << N->getLine();
+ if (N->getBaseType()) {
+ Out << FS << "baseType: ";
+ writeMetadataAsOperand(Out, N->getBaseType(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getSizeInBits())
+ Out << FS << "size: " << N->getSizeInBits();
+ if (N->getAlignInBits())
+ Out << FS << "align: " << N->getAlignInBits();
+ if (N->getOffsetInBits())
+ Out << FS << "offset: " << N->getOffsetInBits();
+ if (auto Flags = N->getFlags()) {
+ Out << FS << "flags: ";
+ writeDIFlags(Out, Flags);
+ }
+ if (N->getElements()) {
+ Out << FS << "elements: ";
+ writeMetadataAsOperand(Out, N->getElements(), TypePrinter, Machine,
+ Context);
+ }
+ if (unsigned Lang = N->getRuntimeLang()) {
+ Out << FS << "runtimeLang: ";
+ if (const char *S = dwarf::LanguageString(Lang))
+ Out << S;
+ else
+ Out << Lang;
+ }
+
+ if (N->getVTableHolder()) {
+ Out << FS << "vtableHolder: ";
+ writeMetadataAsOperand(Out, N->getVTableHolder(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getTemplateParams()) {
+ Out << FS << "templateParams: ";
+ writeMetadataAsOperand(Out, N->getTemplateParams(), TypePrinter, Machine,
+ Context);
+ }
+ writeStringField(Out, FS, "identifier", N->getIdentifier());
+ Out << ")";
+}
+
+static void writeMDSubroutineType(raw_ostream &Out, const MDSubroutineType *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context) {
+ Out << "!MDSubroutineType(";
+ FieldSeparator FS;
+ if (auto Flags = N->getFlags()) {
+ Out << FS << "flags: ";
+ writeDIFlags(Out, Flags);
+ }
+ Out << FS << "types: ";
+ writeMetadataAsOperand(Out, N->getTypeArray(), TypePrinter, Machine, Context);
+ Out << ")";
+}
+
+static void writeMDFile(raw_ostream &Out, const MDFile *N, TypePrinting *,
+ SlotTracker *, const Module *) {
+ Out << "!MDFile(";
+ FieldSeparator FS;
+ writeStringField(Out, FS, "filename", N->getFilename(),
+ /* ShouldSkipEmpty */ false);
+ writeStringField(Out, FS, "directory", N->getDirectory(),
+ /* ShouldSkipEmpty */ false);
+ Out << ")";
+}
+
+static void writeMDCompileUnit(raw_ostream &Out, const MDCompileUnit *N,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDCompileUnit(";
+ FieldSeparator FS;
+ Out << FS << "language: ";
+ if (const char *Lang = dwarf::LanguageString(N->getSourceLanguage()))
+ Out << Lang;
+ else
+ Out << N->getSourceLanguage();
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, Context);
+ writeStringField(Out, FS, "producer", N->getProducer());
+ Out << FS << "isOptimized: " << (N->isOptimized() ? "true" : "false");
+ writeStringField(Out, FS, "flags", N->getFlags());
+ Out << FS << "runtimeVersion: " << N->getRuntimeVersion();
+ writeStringField(Out, FS, "splitDebugFilename", N->getSplitDebugFilename());
+ Out << FS << "emissionKind: " << N->getEmissionKind();
+ if (N->getEnumTypes()) {
+ Out << FS << "enums: ";
+ writeMetadataAsOperand(Out, N->getEnumTypes(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getRetainedTypes()) {
+ Out << FS << "retainedTypes: ";
+ writeMetadataAsOperand(Out, N->getRetainedTypes(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getSubprograms()) {
+ Out << FS << "subprograms: ";
+ writeMetadataAsOperand(Out, N->getSubprograms(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getGlobalVariables()) {
+ Out << FS << "globals: ";
+ writeMetadataAsOperand(Out, N->getGlobalVariables(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getImportedEntities()) {
+ Out << FS << "imports: ";
+ writeMetadataAsOperand(Out, N->getImportedEntities(), TypePrinter, Machine,
+ Context);
+ }
+ Out << ")";
+}
+
+static void writeMDSubprogram(raw_ostream &Out, const MDSubprogram *N,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDSubprogram(";
+ FieldSeparator FS;
+ writeStringField(Out, FS, "name", N->getName());
+ writeStringField(Out, FS, "linkageName", N->getLinkageName());
+ Out << FS << "scope: ";
+ writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+ if (N->getFile()) {
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getLine())
+ Out << FS << "line: " << N->getLine();
+ if (N->getType()) {
+ Out << FS << "type: ";
+ writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine,
+ Context);
+ }
+ Out << FS << "isLocal: " << (N->isLocalToUnit() ? "true" : "false");
+ Out << FS << "isDefinition: " << (N->isDefinition() ? "true" : "false");
+ if (N->getScopeLine())
+ Out << FS << "scopeLine: " << N->getScopeLine();
+ if (N->getContainingType()) {
+ Out << FS << "containingType: ";
+ writeMetadataAsOperand(Out, N->getContainingType(), TypePrinter, Machine,
+ Context);
+ }
+ if (unsigned V = N->getVirtuality()) {
+ Out << FS << "virtuality: ";
+ if (const char *S = dwarf::VirtualityString(V))
+ Out << S;
+ else
+ Out << V;
+ }
+ if (N->getVirtualIndex())
+ Out << FS << "virtualIndex: " << N->getVirtualIndex();
+ if (auto Flags = N->getFlags()) {
+ Out << FS << "flags: ";
+ writeDIFlags(Out, Flags);
+ }
+ Out << FS << "isOptimized: " << (N->isOptimized() ? "true" : "false");
+ if (N->getFunction()) {
+ Out << FS << "function: ";
+ writeMetadataAsOperand(Out, N->getFunction(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getTemplateParams()) {
+ Out << FS << "templateParams: ";
+ writeMetadataAsOperand(Out, N->getTemplateParams(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getDeclaration()) {
+ Out << FS << "declaration: ";
+ writeMetadataAsOperand(Out, N->getDeclaration(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getVariables()) {
+ Out << FS << "variables: ";
+ writeMetadataAsOperand(Out, N->getVariables(), TypePrinter, Machine,
+ Context);
+ }
+ Out << ")";
+}
+
+static void writeMDLexicalBlock(raw_ostream &Out, const MDLexicalBlock *N,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDLexicalBlock(";
+ FieldSeparator FS;
+ Out << FS << "scope: ";
+ writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+ if (N->getFile()) {
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getLine())
+ Out << FS << "line: " << N->getLine();
+ if (N->getColumn())
+ Out << FS << "column: " << N->getColumn();
+ Out << ")";
+}
+
+static void writeMDLexicalBlockFile(raw_ostream &Out,
+ const MDLexicalBlockFile *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDLexicalBlockFile(";
+ FieldSeparator FS;
+ Out << FS << "scope: ";
+ writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+ if (N->getFile()) {
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine,
+ Context);
+ }
+ Out << FS << "discriminator: " << N->getDiscriminator();
+ Out << ")";
+}
+
+static void writeMDNamespace(raw_ostream &Out, const MDNamespace *N,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDNamespace(";
+ FieldSeparator FS;
+ writeStringField(Out, FS, "name", N->getName());
+ Out << FS << "scope: ";
+ writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+ if (N->getFile()) {
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, Context);
+ }
+ if (N->getLine())
+ Out << FS << "line: " << N->getLine();
+ Out << ")";
+}
+
+static void writeMDTemplateTypeParameter(raw_ostream &Out,
+ const MDTemplateTypeParameter *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDTemplateTypeParameter(";
+ FieldSeparator FS;
+ writeStringField(Out, FS, "name", N->getName());
+ Out << FS << "type: ";
+ writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, Context);
+ Out << ")";
+}
+
+static void writeMDTemplateValueParameter(raw_ostream &Out,
+ const MDTemplateValueParameter *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDTemplateValueParameter(";
+ FieldSeparator FS;
+ if (N->getTag() != dwarf::DW_TAG_template_value_parameter)
+ writeTag(Out, FS, N);
+ writeStringField(Out, FS, "name", N->getName());
+ if (auto *Type = N->getType()) {
+ Out << FS << "type: ";
+ writeMetadataAsOperand(Out, Type, TypePrinter, Machine, Context);
+ }
+ Out << FS << "value: ";
+ writeMetadataAsOperand(Out, N->getValue(), TypePrinter, Machine, Context);
+ Out << ")";
+}
+
+static void writeMDGlobalVariable(raw_ostream &Out, const MDGlobalVariable *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context) {
+ Out << "!MDGlobalVariable(";
+ FieldSeparator FS;
+ writeStringField(Out, FS, "name", N->getName());
+ writeStringField(Out, FS, "linkageName", N->getLinkageName());
+ Out << FS << "scope: ";
+ writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+ if (N->getFile()) {
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getLine())
+ Out << FS << "line: " << N->getLine();
+ if (N->getType()) {
+ Out << FS << "type: ";
+ writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine,
+ Context);
+ }
+ Out << FS << "isLocal: " << (N->isLocalToUnit() ? "true" : "false");
+ Out << FS << "isDefinition: " << (N->isDefinition() ? "true" : "false");
+ if (N->getVariable()) {
+ Out << FS << "variable: ";
+ writeMetadataAsOperand(Out, N->getVariable(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getStaticDataMemberDeclaration()) {
+ Out << FS << "declaration: ";
+ writeMetadataAsOperand(Out, N->getStaticDataMemberDeclaration(),
+ TypePrinter, Machine, Context);
+ }
+ Out << ")";
+}
+
+static void writeMDLocalVariable(raw_ostream &Out, const MDLocalVariable *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context) {
+ Out << "!MDLocalVariable(";
+ FieldSeparator FS;
+ writeTag(Out, FS, N);
+ writeStringField(Out, FS, "name", N->getName());
+ if (N->getTag() == dwarf::DW_TAG_arg_variable || N->getArg())
+ Out << FS << "arg: " << N->getArg();
+ Out << FS << "scope: ";
+ writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+ if (N->getFile()) {
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine,
+ Context);
+ }
+ if (N->getLine())
+ Out << FS << "line: " << N->getLine();
+ if (N->getType()) {
+ Out << FS << "type: ";
+ writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine,
+ Context);
+ }
+ if (auto Flags = N->getFlags()) {
+ Out << FS << "flags: ";
+ writeDIFlags(Out, Flags);
+ }
+ if (N->getInlinedAt()) {
+ Out << FS << "inlinedAt: ";
+ writeMetadataAsOperand(Out, N->getInlinedAt(), TypePrinter, Machine,
+ Context);
+ }
+ Out << ")";
+}
+
+static void writeMDExpression(raw_ostream &Out, const MDExpression *N,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDExpression(";
+ FieldSeparator FS;
+ if (N->isValid()) {
+ for (auto I = N->expr_op_begin(), E = N->expr_op_end(); I != E; ++I) {
+ const char *OpStr = dwarf::OperationEncodingString(I->getOp());
+ assert(OpStr && "Expected valid opcode");
+
+ Out << FS << OpStr;
+ for (unsigned A = 0, AE = I->getNumArgs(); A != AE; ++A)
+ Out << FS << I->getArg(A);
+ }
+ } else {
+ for (const auto &I : N->getElements())
+ Out << FS << I;
+ }
+ Out << ")";
+}
+
+static void writeMDObjCProperty(raw_ostream &Out, const MDObjCProperty *N,
+ TypePrinting *TypePrinter, SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!MDObjCProperty(";
+ FieldSeparator FS;
+ writeStringField(Out, FS, "name", N->getName());
+ if (N->getFile()) {
+ Out << FS << "file: ";
+ writeMetadataAsOperand(Out, N->getFile(), TypePrinter, Machine, Context);
+ }
+ if (N->getLine())
+ Out << FS << "line: " << N->getLine();
+ writeStringField(Out, FS, "setter", N->getSetterName());
+ writeStringField(Out, FS, "getter", N->getGetterName());
+ if (N->getAttributes())
+ Out << FS << "attributes: " << N->getAttributes();
+ if (N->getType()) {
+ Out << FS << "type: ";
+ writeMetadataAsOperand(Out, N->getType(), TypePrinter, Machine, Context);
+ }
+ Out << ")";
+}
+
+static void writeMDImportedEntity(raw_ostream &Out, const MDImportedEntity *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context) {
+ Out << "!MDImportedEntity(";
+ FieldSeparator FS;
+ writeTag(Out, FS, N);
+ writeStringField(Out, FS, "name", N->getName());
+ Out << FS << "scope: ";
+ writeMetadataAsOperand(Out, N->getScope(), TypePrinter, Machine, Context);
+ if (N->getEntity()) {
+ Out << FS << "entity: ";
+ writeMetadataAsOperand(Out, N->getEntity(), TypePrinter, Machine, Context);
+ }
+ if (N->getLine())
+ Out << FS << "line: " << N->getLine();
+ Out << ")";
+}
+
+
+static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine,
+ const Module *Context) {
+ assert(!Node->isTemporary() && "Unexpected forward declaration");
+
+ if (Node->isDistinct())
+ Out << "distinct ";
+
+ switch (Node->getMetadataID()) {
+ default:
+ llvm_unreachable("Expected uniquable MDNode");
+#define HANDLE_MDNODE_LEAF(CLASS) \
+ case Metadata::CLASS##Kind: \
+ write##CLASS(Out, cast<CLASS>(Node), TypePrinter, Machine, Context); \
+ break;
+#include "llvm/IR/Metadata.def"
+ }
+}
+
// Full implementation of printing a Value as an operand with support for
// TypePrinting, etc.
static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
return;
}
- if (const MDNode *N = dyn_cast<MDNode>(V)) {
- if (N->isFunctionLocal()) {
- // Print metadata inline, not via slot reference number.
- WriteMDNodeBodyInternal(Out, N, TypePrinter, Machine, Context);
- return;
- }
-
- if (!Machine) {
- if (N->isFunctionLocal())
- Machine = new SlotTracker(N->getFunction());
- else
- Machine = new SlotTracker(Context);
- }
- int Slot = Machine->getMetadataSlot(N);
- if (Slot == -1)
- Out << "<badref>";
- else
- Out << '!' << Slot;
- return;
- }
-
- if (const MDString *MDS = dyn_cast<MDString>(V)) {
- Out << "!\"";
- PrintEscapedString(MDS->getString(), Out);
- Out << '"';
+ if (auto *MD = dyn_cast<MetadataAsValue>(V)) {
+ WriteAsOperandInternal(Out, MD->getMetadata(), TypePrinter, Machine,
+ Context, /* FromValue */ true);
return;
}
Out << "<badref>";
}
+static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context,
+ bool FromValue) {
+ if (const MDNode *N = dyn_cast<MDNode>(MD)) {
+ if (!Machine)
+ Machine = new SlotTracker(Context);
+ int Slot = Machine->getMetadataSlot(N);
+ if (Slot == -1)
+ // Give the pointer value instead of "badref", since this comes up all
+ // the time when debugging.
+ Out << "<" << N << ">";
+ else
+ Out << '!' << Slot;
+ return;
+ }
+
+ if (const MDString *MDS = dyn_cast<MDString>(MD)) {
+ Out << "!\"";
+ PrintEscapedString(MDS->getString(), Out);
+ Out << '"';
+ return;
+ }
+
+ auto *V = cast<ValueAsMetadata>(MD);
+ assert(TypePrinter && "TypePrinter required for metadata values");
+ assert((FromValue || !isa<LocalAsMetadata>(V)) &&
+ "Unexpected function-local metadata outside of value argument");
+
+ TypePrinter->print(V->getValue()->getType(), Out);
+ Out << ' ';
+ WriteAsOperandInternal(Out, V->getValue(), TypePrinter, Machine, Context);
+}
+
void AssemblyWriter::init() {
- if (TheModule)
- TypePrinter.incorporateTypes(*TheModule);
+ if (!TheModule)
+ return;
+ TypePrinter.incorporateTypes(*TheModule);
+ for (const Function &F : *TheModule)
+ if (const Comdat *C = F.getComdat())
+ Comdats.insert(C);
+ for (const GlobalVariable &GV : TheModule->globals())
+ if (const Comdat *C = GV.getComdat())
+ Comdats.insert(C);
}
void AssemblyWriter::printModule(const Module *M) {
Machine.initialize();
+ if (shouldPreserveAssemblyUseListOrder())
+ UseListOrders = predictUseListOrder(M);
+
if (!M->getModuleIdentifier().empty() &&
// Don't print the ID if it will start a new line (which would
// require a comment char before it).
printTypeIdentities();
+ // Output all comdats.
+ if (!Comdats.empty())
+ Out << '\n';
+ for (const Comdat *C : Comdats) {
+ printComdat(C);
+ if (C != Comdats.back())
+ Out << '\n';
+ }
+
// Output all globals.
if (!M->global_empty()) Out << '\n';
for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
I != E; ++I)
printAlias(I);
+ // Output global use-lists.
+ printUseLists(nullptr);
+
// Output all of the functions.
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
printFunction(I);
+ assert(UseListOrders.empty() && "All use-lists should have been consumed");
// Output all attribute groups.
if (!Machine.as_empty()) {
}
}
+static void maybePrintComdat(formatted_raw_ostream &Out,
+ const GlobalObject &GO) {
+ const Comdat *C = GO.getComdat();
+ if (!C)
+ return;
+
+ if (isa<GlobalVariable>(GO))
+ Out << ',';
+ Out << " comdat";
+
+ if (GO.getName() == C->getName())
+ return;
+
+ Out << '(';
+ PrintLLVMName(Out, C->getName(), ComdatPrefix);
+ Out << ')';
+}
+
void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
if (GV->isMaterializable())
Out << "; Materializable\n";
PrintEscapedString(GV->getSection(), Out);
Out << '"';
}
+ maybePrintComdat(Out, *GV);
if (GV->getAlignment())
Out << ", align " << GV->getAlignment();
PrintLLVMName(Out, GA);
Out << " = ";
}
+ PrintLinkage(GA->getLinkage(), Out);
PrintVisibility(GA->getVisibility(), Out);
PrintDLLStorageClass(GA->getDLLStorageClass(), Out);
PrintThreadLocalModel(GA->getThreadLocalMode(), Out);
Out << "alias ";
- PrintLinkage(GA->getLinkage(), Out);
-
const Constant *Aliasee = GA->getAliasee();
if (!Aliasee) {
Out << '\n';
}
+void AssemblyWriter::printComdat(const Comdat *C) {
+ C->print(Out);
+}
+
void AssemblyWriter::printTypeIdentities() {
if (TypePrinter.NumberedTypes.empty() &&
TypePrinter.NamedTypes.empty())
PrintEscapedString(F->getSection(), Out);
Out << '"';
}
+ maybePrintComdat(Out, *F);
if (F->getAlignment())
Out << " align " << F->getAlignment();
if (F->hasGC())
Out << " prefix ";
writeOperand(F->getPrefixData(), true);
}
+ if (F->hasPrologueData()) {
+ Out << " prologue ";
+ writeOperand(F->getPrologueData(), true);
+ }
+
if (F->isDeclaration()) {
Out << '\n';
} else {
for (Function::const_iterator I = F->begin(), E = F->end(); I != E; ++I)
printBasicBlock(I);
+ // Output the function's use-lists.
+ printUseLists(F);
+
Out << "}\n";
}
Out << ", ";
writeParamOperand(CI->getArgOperand(op), PAL, op + 1);
}
+
+ // Emit an ellipsis if this is a musttail call in a vararg function. This
+ // is only to aid readability, musttail calls forward varargs by default.
+ if (CI->isMustTailCall() && CI->getParent() &&
+ CI->getParent()->getParent() &&
+ CI->getParent()->getParent()->isVarArg())
+ Out << ", ...";
+
Out << ')';
if (PAL.hasAttributes(AttributeSet::FunctionIndex))
Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes());
if (AI->isUsedWithInAlloca())
Out << "inalloca ";
TypePrinter.print(AI->getAllocatedType(), Out);
- if (!AI->getArraySize() || AI->isArrayAllocation()) {
+
+ // Explicitly write the array size if the code is broken, if it's an array
+ // allocation, or if the type is not canonical for scalar allocations. The
+ // latter case prevents the type from mutating when round-tripping through
+ // assembly.
+ if (!AI->getArraySize() || AI->isArrayAllocation() ||
+ !AI->getArraySize()->getType()->isIntegerTy(32)) {
Out << ", ";
writeOperand(AI->getArraySize(), true);
}
Out << ", ";
TypePrinter.print(I.getType(), Out);
} else if (Operand) { // Print the normal way.
+ if (const auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
+ Out << ' ';
+ TypePrinter.print(GEP->getSourceElementType(), Out);
+ Out << ',';
+ } else if (const auto *LI = dyn_cast<LoadInst>(&I)) {
+ Out << ' ';
+ TypePrinter.print(LI->getType(), Out);
+ Out << ',';
+ }
// PrintAllTypes - Instructions who have operands of all the same type
// omit the type from all but the first operand. If the instruction has
}
// Print Metadata info.
- SmallVector<std::pair<unsigned, MDNode*>, 4> InstMD;
+ SmallVector<std::pair<unsigned, MDNode *>, 4> InstMD;
I.getAllMetadata(InstMD);
if (!InstMD.empty()) {
SmallVector<StringRef, 8> MDNames;
printInfoComment(I);
}
-static void WriteMDNodeComment(const MDNode *Node,
- formatted_raw_ostream &Out) {
- if (Node->getNumOperands() < 1)
- return;
-
- Value *Op = Node->getOperand(0);
- if (!Op || !isa<ConstantInt>(Op) || cast<ConstantInt>(Op)->getBitWidth() < 32)
- return;
-
- DIDescriptor Desc(Node);
- if (!Desc.Verify())
- return;
-
- unsigned Tag = Desc.getTag();
- Out.PadToColumn(50);
- if (dwarf::TagString(Tag)) {
- Out << "; ";
- Desc.print(Out);
- } else if (Tag == dwarf::DW_TAG_user_base) {
- Out << "; [ DW_TAG_user_base ]";
- }
-}
-
void AssemblyWriter::writeMDNode(unsigned Slot, const MDNode *Node) {
- Out << '!' << Slot << " = metadata ";
+ Out << '!' << Slot << " = ";
printMDNodeBody(Node);
+ Out << "\n";
}
void AssemblyWriter::writeAllMDNodes() {
void AssemblyWriter::printMDNodeBody(const MDNode *Node) {
WriteMDNodeBodyInternal(Out, Node, &TypePrinter, &Machine, TheModule);
- WriteMDNodeComment(Node, Out);
- Out << "\n";
}
void AssemblyWriter::writeAllAttributeGroups() {
} // namespace llvm
+void AssemblyWriter::printUseListOrder(const UseListOrder &Order) {
+ bool IsInFunction = Machine.getFunction();
+ if (IsInFunction)
+ Out << " ";
+
+ Out << "uselistorder";
+ if (const BasicBlock *BB =
+ IsInFunction ? nullptr : dyn_cast<BasicBlock>(Order.V)) {
+ Out << "_bb ";
+ writeOperand(BB->getParent(), false);
+ Out << ", ";
+ writeOperand(BB, false);
+ } else {
+ Out << " ";
+ writeOperand(Order.V, true);
+ }
+ Out << ", { ";
+
+ assert(Order.Shuffle.size() >= 2 && "Shuffle too small");
+ Out << Order.Shuffle[0];
+ for (unsigned I = 1, E = Order.Shuffle.size(); I != E; ++I)
+ Out << ", " << Order.Shuffle[I];
+ Out << " }\n";
+}
+
+void AssemblyWriter::printUseLists(const Function *F) {
+ auto hasMore =
+ [&]() { return !UseListOrders.empty() && UseListOrders.back().F == F; };
+ if (!hasMore())
+ // Nothing to do.
+ return;
+
+ Out << "\n; uselistorder directives\n";
+ while (hasMore()) {
+ printUseListOrder(UseListOrders.back());
+ UseListOrders.pop_back();
+ }
+}
+
//===----------------------------------------------------------------------===//
// External Interface declarations
//===----------------------------------------------------------------------===//
W.printNamedMDNode(this);
}
+void Comdat::print(raw_ostream &ROS) const {
+ PrintLLVMName(ROS, getName(), ComdatPrefix);
+ ROS << " = comdat ";
+
+ switch (getSelectionKind()) {
+ case Comdat::Any:
+ ROS << "any";
+ break;
+ case Comdat::ExactMatch:
+ ROS << "exactmatch";
+ break;
+ case Comdat::Largest:
+ ROS << "largest";
+ break;
+ case Comdat::NoDuplicates:
+ ROS << "noduplicates";
+ break;
+ case Comdat::SameSize:
+ ROS << "samesize";
+ break;
+ }
+
+ ROS << '\n';
+}
+
void Type::print(raw_ostream &OS) const {
TypePrinting TP;
TP.print(const_cast<Type*>(this), OS);
}
}
+static bool isReferencingMDNode(const Instruction &I) {
+ if (const auto *CI = dyn_cast<CallInst>(&I))
+ if (Function *F = CI->getCalledFunction())
+ if (F->isIntrinsic())
+ for (auto &Op : I.operands())
+ if (auto *V = dyn_cast_or_null<MetadataAsValue>(Op))
+ if (isa<MDNode>(V->getMetadata()))
+ return true;
+ return false;
+}
+
void Value::print(raw_ostream &ROS) const {
formatted_raw_ostream OS(ROS);
if (const Instruction *I = dyn_cast<Instruction>(this)) {
const Function *F = I->getParent() ? I->getParent()->getParent() : nullptr;
- SlotTracker SlotTable(F);
+ SlotTracker SlotTable(
+ F,
+ /* ShouldInitializeAllMetadata */ isReferencingMDNode(*I));
AssemblyWriter W(OS, SlotTable, getModuleFromVal(I), nullptr);
W.printInstruction(*I);
} else if (const BasicBlock *BB = dyn_cast<BasicBlock>(this)) {
AssemblyWriter W(OS, SlotTable, getModuleFromVal(BB), nullptr);
W.printBasicBlock(BB);
} else if (const GlobalValue *GV = dyn_cast<GlobalValue>(this)) {
- SlotTracker SlotTable(GV->getParent());
+ SlotTracker SlotTable(GV->getParent(),
+ /* ShouldInitializeAllMetadata */ isa<Function>(GV));
AssemblyWriter W(OS, SlotTable, GV->getParent(), nullptr);
if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
W.printGlobal(V);
W.printFunction(F);
else
W.printAlias(cast<GlobalAlias>(GV));
- } else if (const MDNode *N = dyn_cast<MDNode>(this)) {
- const Function *F = N->getFunction();
- SlotTracker SlotTable(F);
- AssemblyWriter W(OS, SlotTable, F ? F->getParent() : nullptr, nullptr);
- W.printMDNodeBody(N);
+ } else if (const MetadataAsValue *V = dyn_cast<MetadataAsValue>(this)) {
+ V->getMetadata()->print(ROS, getModuleFromVal(V));
} else if (const Constant *C = dyn_cast<Constant>(this)) {
TypePrinting TypePrinter;
TypePrinter.print(C->getType(), OS);
OS << ' ';
WriteConstantInternal(OS, C, TypePrinter, nullptr, nullptr);
- } else if (isa<InlineAsm>(this) || isa<MDString>(this) ||
- isa<Argument>(this)) {
+ } else if (isa<InlineAsm>(this) || isa<Argument>(this)) {
this->printAsOperand(OS);
} else {
llvm_unreachable("Unknown value to print out!");
void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) const {
// Fast path: Don't construct and populate a TypePrinting object if we
// won't be needing any types printed.
- if (!PrintType &&
- ((!isa<Constant>(this) && !isa<MDNode>(this)) ||
- hasName() || isa<GlobalValue>(this))) {
+ bool IsMetadata = isa<MetadataAsValue>(this);
+ if (!PrintType && ((!isa<Constant>(this) && !IsMetadata) || hasName() ||
+ isa<GlobalValue>(this))) {
WriteAsOperandInternal(O, this, nullptr, nullptr, M);
return;
}
O << ' ';
}
- WriteAsOperandInternal(O, this, &TypePrinter, nullptr, M);
+ SlotTracker Machine(M, /* ShouldInitializeAllMetadata */ IsMetadata);
+ WriteAsOperandInternal(O, this, &TypePrinter, &Machine, M);
+}
+
+static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,
+ const Module *M, bool OnlyAsOperand) {
+ formatted_raw_ostream OS(ROS);
+
+ auto *N = dyn_cast<MDNode>(&MD);
+ TypePrinting TypePrinter;
+ SlotTracker Machine(M, /* ShouldInitializeAllMetadata */ N);
+ if (M)
+ TypePrinter.incorporateTypes(*M);
+
+ WriteAsOperandInternal(OS, &MD, &TypePrinter, &Machine, M,
+ /* FromValue */ true);
+ if (OnlyAsOperand || !N)
+ return;
+
+ OS << " = ";
+ WriteMDNodeBodyInternal(OS, N, &TypePrinter, &Machine, M);
+}
+
+void Metadata::printAsOperand(raw_ostream &OS, const Module *M) const {
+ printMetadataImpl(OS, *this, M, /* OnlyAsOperand */ true);
+}
+
+void Metadata::print(raw_ostream &OS, const Module *M) const {
+ printMetadataImpl(OS, *this, M, /* OnlyAsOperand */ false);
}
// Value::dump - allow easy printing of Values from the debugger.
+LLVM_DUMP_METHOD
void Value::dump() const { print(dbgs()); dbgs() << '\n'; }
// Type::dump - allow easy printing of Types from the debugger.
-void Type::dump() const { print(dbgs()); }
+LLVM_DUMP_METHOD
+void Type::dump() const { print(dbgs()); dbgs() << '\n'; }
// Module::dump() - Allow printing of Modules from the debugger.
+LLVM_DUMP_METHOD
void Module::dump() const { print(dbgs(), nullptr); }
+// \brief Allow printing of Comdats from the debugger.
+LLVM_DUMP_METHOD
+void Comdat::dump() const { print(dbgs()); }
+
// NamedMDNode::dump() - Allow printing of NamedMDNodes from the debugger.
+LLVM_DUMP_METHOD
void NamedMDNode::dump() const { print(dbgs()); }
+
+LLVM_DUMP_METHOD
+void Metadata::dump(const Module *M) const {
+ print(dbgs(), M);
+ dbgs() << '\n';
+}