//
//===----------------------------------------------------------------------===//
//
-// This library implements the functionality defined in llvm/Assembly/Writer.h
+// This library implements the functionality defined in llvm/IR/Writer.h
//
// Note that these routines must be extremely tolerant of various errors in the
// LLVM code, because it can be used for debugging transformations.
//===----------------------------------------------------------------------===//
#include "AsmWriter.h"
-
-#include "llvm/Assembly/Writer.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Assembly/AssemblyAnnotationWriter.h"
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/DebugInfo.h"
+#include "llvm/IR/AssemblyAnnotationWriter.h"
+#include "llvm/IR/CFG.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/TypeFinder.h"
#include "llvm/IR/ValueSymbolTable.h"
-#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MathExtras.h"
-
#include <algorithm>
#include <cctype>
using namespace llvm;
// 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);
+ 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() : 0;
+ return MA->getParent() ? MA->getParent()->getParent() : nullptr;
if (const BasicBlock *BB = dyn_cast<BasicBlock>(V))
- return BB->getParent() ? BB->getParent()->getParent() : 0;
+ return BB->getParent() ? BB->getParent()->getParent() : nullptr;
if (const Instruction *I = dyn_cast<Instruction>(V)) {
- const Function *M = I->getParent() ? I->getParent()->getParent() : 0;
- return M ? M->getParent() : 0;
+ const Function *M = I->getParent() ? I->getParent()->getParent() : nullptr;
+ return M ? M->getParent() : nullptr;
}
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
return GV->getParent();
- return 0;
+ return nullptr;
}
static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
default: Out << "cc" << cc; break;
case CallingConv::Fast: Out << "fastcc"; break;
case CallingConv::Cold: Out << "coldcc"; break;
+ case CallingConv::WebKit_JS: Out << "webkit_jscc"; break;
+ case CallingConv::AnyReg: Out << "anyregcc"; break;
+ case CallingConv::PreserveMost: Out << "preserve_mostcc"; break;
+ case CallingConv::PreserveAll: Out << "preserve_allcc"; 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::MSP430_INTR: Out << "msp430_intrcc"; break;
case CallingConv::PTX_Kernel: Out << "ptx_kernel"; break;
case CallingConv::PTX_Device: Out << "ptx_device"; break;
+ case CallingConv::X86_64_SysV: Out << "x86_64_sysvcc"; break;
+ case CallingConv::X86_64_Win64: Out << "x86_64_win64cc"; break;
+ case CallingConv::SPIR_FUNC: Out << "spir_func"; break;
+ case CallingConv::SPIR_KERNEL: Out << "spir_kernel"; 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;
}
/// use of type names or up references to shorten the type name where possible.
void TypePrinting::print(Type *Ty, raw_ostream &OS) {
switch (Ty->getTypeID()) {
- case Type::VoidTyID: OS << "void"; break;
- case Type::HalfTyID: OS << "half"; break;
- case Type::FloatTyID: OS << "float"; break;
- case Type::DoubleTyID: OS << "double"; break;
- case Type::X86_FP80TyID: OS << "x86_fp80"; break;
- case Type::FP128TyID: OS << "fp128"; break;
- case Type::PPC_FP128TyID: OS << "ppc_fp128"; break;
- case Type::LabelTyID: OS << "label"; break;
- case Type::MetadataTyID: OS << "metadata"; break;
- case Type::X86_MMXTyID: OS << "x86_mmx"; break;
+ case Type::VoidTyID: OS << "void"; return;
+ case Type::HalfTyID: OS << "half"; return;
+ case Type::FloatTyID: OS << "float"; return;
+ case Type::DoubleTyID: OS << "double"; return;
+ case Type::X86_FP80TyID: OS << "x86_fp80"; return;
+ case Type::FP128TyID: OS << "fp128"; return;
+ case Type::PPC_FP128TyID: OS << "ppc_fp128"; return;
+ case Type::LabelTyID: OS << "label"; return;
+ case Type::MetadataTyID: OS << "metadata"; return;
+ case Type::X86_MMXTyID: OS << "x86_mmx"; return;
case Type::IntegerTyID:
OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
return;
OS << '>';
return;
}
- default:
- OS << "<unrecognized-type>";
- return;
}
+ llvm_unreachable("Invalid TypeID");
}
void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) {
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.
if (!MD->isFunctionLocal())
return new SlotTracker(MD->getFunction());
- return new SlotTracker((Function *)0);
+ return new SlotTracker((Function *)nullptr);
}
- return 0;
+ return nullptr;
}
#if 0
// 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(0), FunctionProcessed(false),
+ : TheModule(M), TheFunction(nullptr), FunctionProcessed(false),
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() : 0), TheFunction(F), FunctionProcessed(false),
- mNext(0), fNext(0), mdnNext(0), asNext(0) {
+ : TheModule(F ? F->getParent() : nullptr), TheFunction(F),
+ FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) {
}
inline void SlotTracker::initialize() {
if (TheModule) {
processModule();
- TheModule = 0; ///< Prevent re-processing next time we're called.
+ TheModule = nullptr; ///< Prevent re-processing next time we're called.
}
if (TheFunction && !FunctionProcessed)
// optimizer.
if (const CallInst *CI = dyn_cast<CallInst>(I)) {
if (Function *F = CI->getCalledFunction())
- if (F->getName().startswith("llvm."))
+ 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);
void SlotTracker::purgeFunction() {
ST_DEBUG("begin purgeFunction!\n");
fMap.clear(); // Simply discard the function level map
- TheFunction = 0;
+ TheFunction = nullptr;
FunctionProcessed = false;
ST_DEBUG("end purgeFunction!\n");
}
SlotTracker *Machine,
const Module *Context);
-
-
static const char *getPredicateText(unsigned predicate) {
const char * pred = "unknown";
switch (predicate) {
// output the string in hexadecimal format! Note that loading and storing
// floating point types changes the bits of NaNs on some hosts, notably
// x86, so we must not use these types.
- assert(sizeof(double) == sizeof(uint64_t) &&
- "assuming that double is 64 bits!");
+ static_assert(sizeof(double) == sizeof(uint64_t),
+ "assuming that double is 64 bits!");
char Buffer[40];
APFloat apf = CFP->getValueAPF();
// Halves and floats are represented in ASCII IR as double, convert.
Out << "!{";
for (unsigned mi = 0, me = Node->getNumOperands(); mi != me; ++mi) {
const Value *V = Node->getOperand(mi);
- if (V == 0)
+ if (!V)
Out << "null";
else {
TypePrinter->print(V->getType(), Out);
Out << "}";
}
-
-/// WriteAsOperand - Write the name of the specified value out to the specified
-/// ostream. This can be useful when you just want to print int %reg126, not
-/// the whole instruction that generated it.
-///
+// Full implementation of printing a Value as an operand with support for
+// TypePrinting, etc.
static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
TypePrinting *TypePrinter,
SlotTracker *Machine,
return;
}
- if (V->getValueID() == Value::PseudoSourceValueVal ||
- V->getValueID() == Value::FixedStackPseudoSourceValueVal) {
- V->print(Out);
- return;
- }
-
char Prefix = '%';
int Slot;
// If we have a SlotTracker, use it.
Slot = Machine->getLocalSlot(V);
}
delete Machine;
- Machine = 0;
+ Machine = nullptr;
} else {
Slot = -1;
}
Out << "<badref>";
}
-void WriteAsOperand(raw_ostream &Out, const Value *V,
- bool PrintType, const Module *Context) {
-
- // Fast path: Don't construct and populate a TypePrinting object if we
- // won't be needing any types printed.
- if (!PrintType &&
- ((!isa<Constant>(V) && !isa<MDNode>(V)) ||
- V->hasName() || isa<GlobalValue>(V))) {
- WriteAsOperandInternal(Out, V, 0, 0, Context);
- return;
- }
-
- if (Context == 0) Context = getModuleFromVal(V);
-
- TypePrinting TypePrinter;
- if (Context)
- TypePrinter.incorporateTypes(*Context);
- if (PrintType) {
- TypePrinter.print(V->getType(), Out);
- Out << ' ';
- }
-
- WriteAsOperandInternal(Out, V, &TypePrinter, 0, 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);
}
AssemblyWriter::~AssemblyWriter() { }
void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) {
- if (Operand == 0) {
+ if (!Operand) {
Out << "<null operand!>";
return;
}
}
}
+void AssemblyWriter::writeAtomicCmpXchg(AtomicOrdering SuccessOrdering,
+ AtomicOrdering FailureOrdering,
+ SynchronizationScope SynchScope) {
+ assert(SuccessOrdering != NotAtomic && FailureOrdering != NotAtomic);
+
+ switch (SynchScope) {
+ case SingleThread: Out << " singlethread"; break;
+ case CrossThread: break;
+ }
+
+ switch (SuccessOrdering) {
+ default: Out << " <bad ordering " << int(SuccessOrdering) << ">"; break;
+ case Unordered: Out << " unordered"; break;
+ case Monotonic: Out << " monotonic"; break;
+ case Acquire: Out << " acquire"; break;
+ case Release: Out << " release"; break;
+ case AcquireRelease: Out << " acq_rel"; break;
+ case SequentiallyConsistent: Out << " seq_cst"; break;
+ }
+
+ switch (FailureOrdering) {
+ default: Out << " <bad ordering " << int(FailureOrdering) << ">"; break;
+ case Unordered: Out << " unordered"; break;
+ case Monotonic: Out << " monotonic"; break;
+ case Acquire: Out << " acquire"; break;
+ case Release: Out << " release"; break;
+ case AcquireRelease: Out << " acq_rel"; break;
+ case SequentiallyConsistent: Out << " seq_cst"; break;
+ }
+}
+
void AssemblyWriter::writeParamOperand(const Value *Operand,
AttributeSet Attrs, unsigned Idx) {
- if (Operand == 0) {
+ if (!Operand) {
Out << "<null operand!>";
return;
}
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).
M->getModuleIdentifier().find('\n') == std::string::npos)
Out << "; ModuleID = '" << M->getModuleIdentifier() << "'\n";
- if (!M->getDataLayout().empty())
- Out << "target datalayout = \"" << M->getDataLayout() << "\"\n";
+ const std::string &DL = M->getDataLayoutStr();
+ if (!DL.empty())
+ Out << "target datalayout = \"" << DL << "\"\n";
if (!M->getTargetTriple().empty())
Out << "target triple = \"" << M->getTargetTriple() << "\"\n";
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()) {
switch (LT) {
case GlobalValue::ExternalLinkage: break;
case GlobalValue::PrivateLinkage: Out << "private "; break;
- case GlobalValue::LinkerPrivateLinkage: Out << "linker_private "; break;
- case GlobalValue::LinkerPrivateWeakLinkage:
- Out << "linker_private_weak ";
- break;
case GlobalValue::InternalLinkage: Out << "internal "; break;
case GlobalValue::LinkOnceAnyLinkage: Out << "linkonce "; break;
case GlobalValue::LinkOnceODRLinkage: Out << "linkonce_odr "; break;
- case GlobalValue::LinkOnceODRAutoHideLinkage:
- Out << "linkonce_odr_auto_hide ";
- break;
case GlobalValue::WeakAnyLinkage: Out << "weak "; break;
case GlobalValue::WeakODRLinkage: Out << "weak_odr "; break;
case GlobalValue::CommonLinkage: Out << "common "; break;
case GlobalValue::AppendingLinkage: Out << "appending "; break;
- case GlobalValue::DLLImportLinkage: Out << "dllimport "; break;
- case GlobalValue::DLLExportLinkage: Out << "dllexport "; break;
case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break;
case GlobalValue::AvailableExternallyLinkage:
Out << "available_externally ";
}
}
+static void PrintDLLStorageClass(GlobalValue::DLLStorageClassTypes SCT,
+ formatted_raw_ostream &Out) {
+ switch (SCT) {
+ case GlobalValue::DefaultStorageClass: break;
+ case GlobalValue::DLLImportStorageClass: Out << "dllimport "; break;
+ case GlobalValue::DLLExportStorageClass: Out << "dllexport "; break;
+ }
+}
+
static void PrintThreadLocalModel(GlobalVariable::ThreadLocalMode TLM,
formatted_raw_ostream &Out) {
switch (TLM) {
PrintLinkage(GV->getLinkage(), Out);
PrintVisibility(GV->getVisibility(), Out);
+ PrintDLLStorageClass(GV->getDLLStorageClass(), Out);
PrintThreadLocalModel(GV->getThreadLocalMode(), Out);
+ if (GV->hasUnnamedAddr())
+ Out << "unnamed_addr ";
if (unsigned AddressSpace = GV->getType()->getAddressSpace())
Out << "addrspace(" << AddressSpace << ") ";
- if (GV->hasUnnamedAddr()) Out << "unnamed_addr ";
if (GV->isExternallyInitialized()) Out << "externally_initialized ";
Out << (GV->isConstant() ? "constant " : "global ");
TypePrinter.print(GV->getType()->getElementType(), Out);
PrintEscapedString(GV->getSection(), Out);
Out << '"';
}
+ if (GV->hasComdat()) {
+ Out << ", comdat ";
+ PrintLLVMName(Out, GV->getComdat()->getName(), ComdatPrefix);
+ }
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);
+ if (GA->hasUnnamedAddr())
+ Out << "unnamed_addr ";
Out << "alias ";
- PrintLinkage(GA->getLinkage(), Out);
-
const Constant *Aliasee = GA->getAliasee();
- if (Aliasee == 0) {
+ if (!Aliasee) {
TypePrinter.print(GA->getType(), Out);
Out << " <<NULL ALIASEE>>";
} else {
Out << '\n';
}
+void AssemblyWriter::printComdat(const Comdat *C) {
+ C->print(Out);
+}
+
void AssemblyWriter::printTypeIdentities() {
if (TypePrinter.NumberedTypes.empty() &&
TypePrinter.NamedTypes.empty())
PrintLinkage(F->getLinkage(), Out);
PrintVisibility(F->getVisibility(), Out);
+ PrintDLLStorageClass(F->getDLLStorageClass(), Out);
// Print the calling convention.
if (F->getCallingConv() != CallingConv::C) {
PrintEscapedString(F->getSection(), Out);
Out << '"';
}
+ if (F->hasComdat()) {
+ Out << " comdat ";
+ PrintLLVMName(Out, F->getComdat()->getName(), ComdatPrefix);
+ }
if (F->getAlignment())
Out << " align " << F->getAlignment();
if (F->hasGC())
Out << " gc \"" << F->getGC() << '"';
+ if (F->hasPrefixData()) {
+ Out << " prefix ";
+ writeOperand(F->getPrefixData(), 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 << "<badref>";
}
- if (BB->getParent() == 0) {
+ if (!BB->getParent()) {
Out.PadToColumn(50);
Out << "; Error: Block without parent!";
} else if (BB != &BB->getParent()->getEntryBlock()) { // Not the entry block?
Out << '%' << SlotNum << " = ";
}
- if (isa<CallInst>(I) && cast<CallInst>(I).isTailCall())
- Out << "tail ";
+ if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
+ if (CI->isMustTailCall())
+ Out << "musttail ";
+ else if (CI->isTailCall())
+ Out << "tail ";
+ }
// Print out the opcode...
Out << I.getOpcodeName();
(isa<StoreInst>(I) && cast<StoreInst>(I).isAtomic()))
Out << " atomic";
+ if (isa<AtomicCmpXchgInst>(I) && cast<AtomicCmpXchgInst>(I).isWeak())
+ Out << " weak";
+
// If this is a volatile operation, print out the volatile marker.
if ((isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) ||
(isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()) ||
writeAtomicRMWOperation(Out, RMWI->getOperation());
// Print out the type of the operands...
- const Value *Operand = I.getNumOperands() ? I.getOperand(0) : 0;
+ const Value *Operand = I.getNumOperands() ? I.getOperand(0) : nullptr;
// Special case conditional branches to swizzle the condition out to the front
if (isa<BranchInst>(I) && cast<BranchInst>(I).isConditional()) {
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());
} else if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
Out << ' ';
+ if (AI->isUsedWithInAlloca())
+ Out << "inalloca ";
TypePrinter.print(AI->getAllocatedType(), Out);
if (!AI->getArraySize() || AI->isArrayAllocation()) {
Out << ", ";
if (SI->getAlignment())
Out << ", align " << SI->getAlignment();
} else if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&I)) {
- writeAtomic(CXI->getOrdering(), CXI->getSynchScope());
+ writeAtomicCmpXchg(CXI->getSuccessOrdering(), CXI->getFailureOrdering(),
+ CXI->getSynchScope());
} else if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&I)) {
writeAtomic(RMWI->getOrdering(), RMWI->getSynchScope());
} else if (const FenceInst *FI = dyn_cast<FenceInst>(&I)) {
} // 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.printModule(this);
}
-void NamedMDNode::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const {
+void NamedMDNode::print(raw_ostream &ROS) const {
SlotTracker SlotTable(getParent());
formatted_raw_ostream OS(ROS);
- AssemblyWriter W(OS, SlotTable, getParent(), AAW);
+ AssemblyWriter W(OS, SlotTable, getParent(), nullptr);
W.printNamedMDNode(this);
}
-void Type::print(raw_ostream &OS) const {
- if (this == 0) {
- OS << "<null Type>";
- return;
+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);
}
}
-void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const {
- if (this == 0) {
- ROS << "printing a <null> value\n";
- return;
- }
+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() : 0;
+ const Function *F = I->getParent() ? I->getParent()->getParent() : nullptr;
SlotTracker SlotTable(F);
- AssemblyWriter W(OS, SlotTable, getModuleFromVal(I), AAW);
+ AssemblyWriter W(OS, SlotTable, getModuleFromVal(I), nullptr);
W.printInstruction(*I);
} else if (const BasicBlock *BB = dyn_cast<BasicBlock>(this)) {
SlotTracker SlotTable(BB->getParent());
- AssemblyWriter W(OS, SlotTable, getModuleFromVal(BB), AAW);
+ AssemblyWriter W(OS, SlotTable, getModuleFromVal(BB), nullptr);
W.printBasicBlock(BB);
} else if (const GlobalValue *GV = dyn_cast<GlobalValue>(this)) {
SlotTracker SlotTable(GV->getParent());
- AssemblyWriter W(OS, SlotTable, GV->getParent(), AAW);
+ AssemblyWriter W(OS, SlotTable, GV->getParent(), nullptr);
if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
W.printGlobal(V);
else if (const Function *F = dyn_cast<Function>(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() : 0, AAW);
+ AssemblyWriter W(OS, SlotTable, F ? F->getParent() : nullptr, nullptr);
W.printMDNodeBody(N);
} else if (const Constant *C = dyn_cast<Constant>(this)) {
TypePrinting TypePrinter;
TypePrinter.print(C->getType(), OS);
OS << ' ';
- WriteConstantInternal(OS, C, TypePrinter, 0, 0);
+ WriteConstantInternal(OS, C, TypePrinter, nullptr, nullptr);
} else if (isa<InlineAsm>(this) || isa<MDString>(this) ||
isa<Argument>(this)) {
- WriteAsOperand(OS, this, true, 0);
+ this->printAsOperand(OS);
} else {
- // Otherwise we don't know what it is. Call the virtual function to
- // allow a subclass to print itself.
- printCustom(OS);
+ llvm_unreachable("Unknown value to print out!");
}
}
-// Value::printCustom - subclasses should override this to implement printing.
-void Value::printCustom(raw_ostream &OS) const {
- 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))) {
+ WriteAsOperandInternal(O, this, nullptr, nullptr, M);
+ return;
+ }
+
+ if (!M)
+ M = getModuleFromVal(this);
+
+ TypePrinting TypePrinter;
+ if (M)
+ TypePrinter.incorporateTypes(*M);
+ if (PrintType) {
+ TypePrinter.print(getType(), O);
+ O << ' ';
+ }
+
+ WriteAsOperandInternal(O, this, &TypePrinter, nullptr, M);
}
// Value::dump - allow easy printing of Values from the debugger.
void Value::dump() const { print(dbgs()); dbgs() << '\n'; }
// Type::dump - allow easy printing of Types from the debugger.
-void Type::dump() const { print(dbgs()); }
+void Type::dump() const { print(dbgs()); dbgs() << '\n'; }
// Module::dump() - Allow printing of Modules from the debugger.
-void Module::dump() const { print(dbgs(), 0); }
+void Module::dump() const { print(dbgs(), nullptr); }
+
+// \brief Allow printing of Comdats from the debugger.
+void Comdat::dump() const { print(dbgs()); }
// NamedMDNode::dump() - Allow printing of NamedMDNodes from the debugger.
-void NamedMDNode::dump() const { print(dbgs(), 0); }
+void NamedMDNode::dump() const { print(dbgs()); }