X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FIR%2FAsmWriter.cpp;h=8f9122558d31b9dc46042e30f9d4cee64af07715;hb=77327b8520d8d0b69f45a812c7d354bbead6c1c1;hp=1c46a9414ae4c9f6a75a6442609fb1c2f492c12a;hpb=4068e1af9ff68b6b5fdb3233f1304e53f1bf179a;p=oota-llvm.git diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 1c46a9414ae..8f9122558d3 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -7,24 +7,25 @@ // //===----------------------------------------------------------------------===// // -// 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 "llvm/Assembly/Writer.h" +#include "AsmWriter.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" @@ -32,7 +33,6 @@ #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" @@ -51,37 +51,44 @@ AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {} static const Module *getModuleFromVal(const Value *V) { if (const Argument *MA = dyn_cast(V)) - return MA->getParent() ? MA->getParent()->getParent() : 0; + return MA->getParent() ? MA->getParent()->getParent() : nullptr; if (const BasicBlock *BB = dyn_cast(V)) - return BB->getParent() ? BB->getParent()->getParent() : 0; + return BB->getParent() ? BB->getParent()->getParent() : nullptr; if (const Instruction *I = dyn_cast(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(V)) return GV->getParent(); - return 0; + return nullptr; } -static void PrintCallingConv(unsigned cc, raw_ostream &Out) -{ +static void PrintCallingConv(unsigned cc, raw_ostream &Out) { switch (cc) { - case CallingConv::Fast: Out << "fastcc"; break; - case CallingConv::Cold: Out << "coldcc"; 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::Intel_OCL_BI: Out << "intel_ocl_bicc"; break; - case CallingConv::ARM_APCS: Out << "arm_apcscc"; break; - case CallingConv::ARM_AAPCS: Out << "arm_aapcscc"; break; - case CallingConv::ARM_AAPCS_VFP:Out << "arm_aapcs_vfpcc"; 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; - default: Out << "cc" << cc; break; + 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::Intel_OCL_BI: Out << "intel_ocl_bicc"; break; + case CallingConv::ARM_APCS: Out << "arm_apcscc"; break; + case CallingConv::ARM_AAPCS: Out << "arm_aapcscc"; break; + case CallingConv::ARM_AAPCS_VFP: Out << "arm_aapcs_vfpcc"; 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; } } @@ -99,6 +106,7 @@ static void PrintEscapedString(StringRef Name, raw_ostream &Out) { enum PrefixType { GlobalPrefix, + ComdatPrefix, LabelPrefix, LocalPrefix, NoPrefix @@ -112,12 +120,13 @@ static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) { switch (Prefix) { case NoPrefix: break; case GlobalPrefix: OS << '@'; break; + case ComdatPrefix: OS << '$'; break; case LabelPrefix: break; case LocalPrefix: OS << '%'; break; } // Scan the name to see if it needs quotes first. - bool NeedsQuotes = isdigit(Name[0]); + bool NeedsQuotes = isdigit(static_cast(Name[0])); if (!NeedsQuotes) { for (unsigned i = 0, e = Name.size(); i != e; ++i) { // By making this unsigned, the value passed in to isalnum will always be @@ -125,7 +134,8 @@ static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) { // its implementation will assert. This situation can arise when dealing // with UTF-8 multibyte characters. unsigned char C = Name[i]; - if (!isalnum(C) && C != '-' && C != '.' && C != '_') { + if (!isalnum(static_cast(C)) && C != '-' && C != '.' && + C != '_') { NeedsQuotes = true; break; } @@ -153,35 +163,8 @@ static void PrintLLVMName(raw_ostream &OS, const Value *V) { isa(V) ? GlobalPrefix : LocalPrefix); } -//===----------------------------------------------------------------------===// -// TypePrinting Class: Type printing machinery -//===----------------------------------------------------------------------===// - -/// TypePrinting - Type printing machinery. -namespace { -class TypePrinting { - TypePrinting(const TypePrinting &) LLVM_DELETED_FUNCTION; - void operator=(const TypePrinting&) LLVM_DELETED_FUNCTION; -public: - - /// NamedTypes - The named types that are used by the current module. - TypeFinder NamedTypes; - - /// NumberedTypes - The numbered types, along with their value. - DenseMap NumberedTypes; - - - TypePrinting() {} - ~TypePrinting() {} - - void incorporateTypes(const Module &M); - - void print(Type *Ty, raw_ostream &OS); - - void printStructBody(StructType *Ty, raw_ostream &OS); -}; -} // end anonymous namespace. +namespace llvm { void TypePrinting::incorporateTypes(const Module &M) { NamedTypes.run(M, false); @@ -212,16 +195,16 @@ void TypePrinting::incorporateTypes(const Module &M) { /// 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(Ty)->getBitWidth(); return; @@ -281,10 +264,8 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) { OS << '>'; return; } - default: - OS << ""; - return; } + llvm_unreachable("Invalid TypeID"); } void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) { @@ -313,14 +294,9 @@ void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) { OS << '>'; } - - //===----------------------------------------------------------------------===// // SlotTracker Class: Enumerate slot numbers for unnamed values //===----------------------------------------------------------------------===// - -namespace { - /// This class provides computation of slot numbers for LLVM Assembly writing. /// class SlotTracker { @@ -347,6 +323,10 @@ private: /// mdnMap - Map for MDNodes. DenseMap mdnMap; unsigned mdnNext; + + /// asMap - The slot map for attribute sets. + DenseMap asMap; + unsigned asNext; public: /// Construct from a module explicit SlotTracker(const Module *M); @@ -358,6 +338,7 @@ public: int getLocalSlot(const Value *V); int getGlobalSlot(const GlobalValue *V); int getMetadataSlot(const MDNode *N); + int getAttributeGroupSlot(AttributeSet AS); /// If you'd like to deal with a function instead of just a module, use /// this method to get its data into the SlotTracker. @@ -378,6 +359,13 @@ public: unsigned mdn_size() const { return mdnMap.size(); } bool mdn_empty() const { return mdnMap.empty(); } + /// AttributeSet map iterators. + typedef DenseMap::iterator as_iterator; + as_iterator as_begin() { return asMap.begin(); } + as_iterator as_end() { return asMap.end(); } + unsigned as_size() const { return asMap.size(); } + bool as_empty() const { return asMap.empty(); } + /// This function does the actual initialization. inline void initialize(); @@ -392,6 +380,9 @@ private: /// CreateFunctionSlot - Insert the specified Value* into the slot table. void CreateFunctionSlot(const Value *V); + /// \brief Insert the specified AttributeSet into the slot table. + void CreateAttributeSetSlot(AttributeSet AS); + /// Add all of the module level global variables (and their initializers) /// and function declarations, but not the contents of those functions. void processModule(); @@ -403,8 +394,9 @@ private: void operator=(const SlotTracker &) LLVM_DELETED_FUNCTION; }; -} // end anonymous namespace - +SlotTracker *createSlotTracker(const Module *M) { + return new SlotTracker(M); +} static SlotTracker *createSlotTracker(const Value *V) { if (const Argument *FA = dyn_cast(V)) @@ -430,10 +422,10 @@ static SlotTracker *createSlotTracker(const Value *V) { if (!MD->isFunctionLocal()) return new SlotTracker(MD->getFunction()); - return new SlotTracker((Function *)0); + return new SlotTracker((Function *)nullptr); } - return 0; + return nullptr; } #if 0 @@ -445,21 +437,21 @@ static SlotTracker *createSlotTracker(const Value *V) { // 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), - mNext(0), fNext(0), mdnNext(0) { + : 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) { + : 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) @@ -487,12 +479,19 @@ void SlotTracker::processModule() { CreateMetadataSlot(NMD->getOperand(i)); } - // Add all the unnamed functions to the table. for (Module::const_iterator I = TheModule->begin(), E = TheModule->end(); - I != E; ++I) + I != E; ++I) { if (!I->hasName()) + // Add all the unnamed functions to the table. CreateModuleSlot(I); + // Add all the function attributes to the table. + // FIXME: Add attributes of other objects? + AttributeSet FnAttrs = I->getAttributes().getFnAttributes(); + if (FnAttrs.hasAttributes(AttributeSet::FunctionIndex)) + CreateAttributeSetSlot(FnAttrs); + } + ST_DEBUG("end processModule!\n"); } @@ -527,10 +526,20 @@ void SlotTracker::processFunction() { // optimizer. if (const CallInst *CI = dyn_cast(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(I->getOperand(i))) CreateMetadataSlot(N); + + // 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(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. @@ -552,7 +561,7 @@ void SlotTracker::processFunction() { 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"); } @@ -589,6 +598,14 @@ int SlotTracker::getLocalSlot(const Value *V) { return FI == fMap.end() ? -1 : (int)FI->second; } +int SlotTracker::getAttributeGroupSlot(AttributeSet AS) { + // Check for uninitialized state and do lazy initialization. + initialize(); + + // Find the AttributeSet in the module map. + as_iterator AI = asMap.find(AS); + return AI == asMap.end() ? -1 : (int)AI->second; +} /// CreateModuleSlot - Insert the specified GlobalValue* into the slot table. void SlotTracker::CreateModuleSlot(const GlobalValue *V) { @@ -640,6 +657,18 @@ void SlotTracker::CreateMetadataSlot(const MDNode *N) { CreateMetadataSlot(Op); } +void SlotTracker::CreateAttributeSetSlot(AttributeSet AS) { + assert(AS.hasAttributes(AttributeSet::FunctionIndex) && + "Doesn't need a slot!"); + + as_iterator I = asMap.find(AS); + if (I != asMap.end()) + return; + + unsigned DestSlot = asNext++; + asMap[AS] = DestSlot; +} + //===----------------------------------------------------------------------===// // AsmWriter Implementation //===----------------------------------------------------------------------===// @@ -649,8 +678,6 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, SlotTracker *Machine, const Module *Context); - - static const char *getPredicateText(unsigned predicate) { const char * pred = "unknown"; switch (predicate) { @@ -785,8 +812,8 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, // 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. @@ -1022,7 +1049,7 @@ static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, 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); @@ -1037,11 +1064,8 @@ static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, 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, @@ -1103,12 +1127,6 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, 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. @@ -1137,7 +1155,7 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, Slot = Machine->getLocalSlot(V); } delete Machine; - Machine = 0; + Machine = nullptr; } else { Slot = -1; } @@ -1148,77 +1166,37 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, Out << ""; } -void llvm::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(V) && !isa(V)) || - V->hasName() || isa(V))) { - WriteAsOperandInternal(Out, V, 0, 0, Context); +void AssemblyWriter::init() { + if (!TheModule) 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); + 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); } -namespace { - -class AssemblyWriter { - formatted_raw_ostream &Out; - SlotTracker &Machine; - const Module *TheModule; - TypePrinting TypePrinter; - AssemblyAnnotationWriter *AnnotationWriter; - -public: - inline AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, - const Module *M, - AssemblyAnnotationWriter *AAW) - : Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW) { - if (M) - TypePrinter.incorporateTypes(*M); - } - - void printMDNodeBody(const MDNode *MD); - void printNamedMDNode(const NamedMDNode *NMD); - - void printModule(const Module *M); - void writeOperand(const Value *Op, bool PrintType); - void writeParamOperand(const Value *Operand, AttributeSet Attrs,unsigned Idx); - void writeAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope); - - void writeAllMDNodes(); +AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, + const Module *M, + AssemblyAnnotationWriter *AAW) + : Out(o), TheModule(M), Machine(Mac), AnnotationWriter(AAW) { + init(); +} - void printTypeIdentities(); - void printGlobal(const GlobalVariable *GV); - void printAlias(const GlobalAlias *GV); - void printFunction(const Function *F); - void printArgument(const Argument *FA, AttributeSet Attrs, unsigned Idx); - void printBasicBlock(const BasicBlock *BB); - void printInstruction(const Instruction &I); +AssemblyWriter::AssemblyWriter(formatted_raw_ostream &o, const Module *M, + AssemblyAnnotationWriter *AAW) + : Out(o), TheModule(M), ModuleSlotTracker(createSlotTracker(M)), + Machine(*ModuleSlotTracker), AnnotationWriter(AAW) { + init(); +} -private: - // printInfoComment - Print a little comment after the instruction indicating - // which slot it occupies. - void printInfoComment(const Value &V); -}; -} // end of anonymous namespace +AssemblyWriter::~AssemblyWriter() { } void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) { - if (Operand == 0) { + if (!Operand) { Out << ""; return; } @@ -1250,9 +1228,40 @@ void AssemblyWriter::writeAtomic(AtomicOrdering Ordering, } } +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 << " "; 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 << " "; 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 << ""; return; } @@ -1268,14 +1277,17 @@ void AssemblyWriter::writeParamOperand(const Value *Operand, } void AssemblyWriter::printModule(const Module *M) { + Machine.initialize(); + 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"; @@ -1305,6 +1317,15 @@ void AssemblyWriter::printModule(const Module *M) { 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(); @@ -1322,6 +1343,12 @@ void AssemblyWriter::printModule(const Module *M) { for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) printFunction(I); + // Output all attribute groups. + if (!Machine.as_empty()) { + Out << '\n'; + writeAllAttributeGroups(); + } + // Output named metadata. if (!M->named_metadata_empty()) Out << '\n'; @@ -1342,14 +1369,16 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) { if (Name.empty()) { Out << " "; } else { - if (isalpha(Name[0]) || Name[0] == '-' || Name[0] == '$' || + if (isalpha(static_cast(Name[0])) || + Name[0] == '-' || Name[0] == '$' || Name[0] == '.' || Name[0] == '_') Out << Name[0]; else Out << '\\' << hexdigit(Name[0] >> 4) << hexdigit(Name[0] & 0x0F); for (unsigned i = 1, e = Name.size(); i != e; ++i) { unsigned char C = Name[i]; - if (isalnum(C) || C == '-' || C == '$' || C == '.' || C == '_') + if (isalnum(static_cast(C)) || C == '-' || C == '$' || + C == '.' || C == '_') Out << C; else Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F); @@ -1373,22 +1402,13 @@ static void PrintLinkage(GlobalValue::LinkageTypes LT, 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 "; @@ -1406,6 +1426,15 @@ static void PrintVisibility(GlobalValue::VisibilityTypes Vis, } } +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) { @@ -1438,11 +1467,14 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { 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); @@ -1456,6 +1488,10 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { PrintEscapedString(GV->getSection(), Out); Out << '"'; } + if (GV->hasComdat()) { + Out << ", comdat "; + PrintLLVMName(Out, GV->getComdat()->getName(), ComdatPrefix); + } if (GV->getAlignment()) Out << ", align " << GV->getAlignment(); @@ -1473,15 +1509,18 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { 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 << " <>"; } else { @@ -1492,6 +1531,10 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { Out << '\n'; } +void AssemblyWriter::printComdat(const Comdat *C) { + C->print(Out); +} + void AssemblyWriter::printTypeIdentities() { if (TypePrinter.NumberedTypes.empty() && TypePrinter.NamedTypes.empty()) @@ -1541,6 +1584,29 @@ void AssemblyWriter::printFunction(const Function *F) { if (F->isMaterializable()) Out << "; Materializable\n"; + const AttributeSet &Attrs = F->getAttributes(); + if (Attrs.hasAttributes(AttributeSet::FunctionIndex)) { + AttributeSet AS = Attrs.getFnAttributes(); + std::string AttrStr; + + unsigned Idx = 0; + for (unsigned E = AS.getNumSlots(); Idx != E; ++Idx) + if (AS.getSlotIndex(Idx) == AttributeSet::FunctionIndex) + break; + + for (AttributeSet::iterator I = AS.begin(Idx), E = AS.end(Idx); + I != E; ++I) { + Attribute Attr = *I; + if (!Attr.isStringAttribute()) { + if (!AttrStr.empty()) AttrStr += ' '; + AttrStr += Attr.getAsString(); + } + } + + if (!AttrStr.empty()) + Out << "; Function Attrs: " << AttrStr << '\n'; + } + if (F->isDeclaration()) Out << "declare "; else @@ -1548,6 +1614,7 @@ void AssemblyWriter::printFunction(const Function *F) { PrintLinkage(F->getLinkage(), Out); PrintVisibility(F->getVisibility(), Out); + PrintDLLStorageClass(F->getDLLStorageClass(), Out); // Print the calling convention. if (F->getCallingConv() != CallingConv::C) { @@ -1556,10 +1623,8 @@ void AssemblyWriter::printFunction(const Function *F) { } FunctionType *FT = F->getFunctionType(); - const AttributeSet &Attrs = F->getAttributes(); - Attribute RetAttrs = Attrs.getRetAttributes(); - if (RetAttrs.hasAttributes()) - Out << Attrs.getRetAttributes().getAsString() << ' '; + if (Attrs.hasAttributes(AttributeSet::ReturnIndex)) + Out << Attrs.getAsString(AttributeSet::ReturnIndex) << ' '; TypePrinter.print(F->getReturnType(), Out); Out << ' '; WriteAsOperandInternal(Out, F, &TypePrinter, &Machine, F->getParent()); @@ -1601,16 +1666,24 @@ void AssemblyWriter::printFunction(const Function *F) { if (F->hasUnnamedAddr()) Out << " unnamed_addr"; if (Attrs.hasAttributes(AttributeSet::FunctionIndex)) - Out << ' ' << Attrs.getAsString(AttributeSet::FunctionIndex); + Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttributes()); if (F->hasSection()) { Out << " section \""; 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 { @@ -1660,7 +1733,7 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { Out << ""; } - 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? @@ -1687,21 +1760,24 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { // Output all of the instructions in the basic block... for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) { - printInstruction(*I); - Out << '\n'; + printInstructionLine(*I); } if (AnnotationWriter) AnnotationWriter->emitBasicBlockEndAnnot(BB, Out); } +/// printInstructionLine - Print an instruction and a newline character. +void AssemblyWriter::printInstructionLine(const Instruction &I) { + printInstruction(I); + Out << '\n'; +} + /// printInfoComment - Print a little comment after the instruction indicating /// which slot it occupies. /// void AssemblyWriter::printInfoComment(const Value &V) { - if (AnnotationWriter) { + if (AnnotationWriter) AnnotationWriter->printInfoComment(V, Out); - return; - } } // This member is called for each Instruction in a function.. @@ -1724,8 +1800,12 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << '%' << SlotNum << " = "; } - if (isa(I) && cast(I).isTailCall()) - Out << "tail "; + if (const CallInst *CI = dyn_cast(&I)) { + if (CI->isMustTailCall()) + Out << "musttail "; + else if (CI->isTailCall()) + Out << "tail "; + } // Print out the opcode... Out << I.getOpcodeName(); @@ -1735,6 +1815,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) { (isa(I) && cast(I).isAtomic())) Out << " atomic"; + if (isa(I) && cast(I).isWeak()) + Out << " weak"; + // If this is a volatile operation, print out the volatile marker. if ((isa(I) && cast(I).isVolatile()) || (isa(I) && cast(I).isVolatile()) || @@ -1754,11 +1837,11 @@ void AssemblyWriter::printInstruction(const Instruction &I) { 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(I) && cast(I).isConditional()) { - BranchInst &BI(cast(I)); + const BranchInst &BI(cast(I)); Out << ' '; writeOperand(BI.getCondition(), true); Out << ", "; @@ -1767,14 +1850,14 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(BI.getSuccessor(1), true); } else if (isa(I)) { - SwitchInst& SI(cast(I)); + const SwitchInst& SI(cast(I)); // Special case switch instruction to get formatting nice and correct. Out << ' '; writeOperand(SI.getCondition(), true); Out << ", "; writeOperand(SI.getDefaultDest(), true); Out << " ["; - for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); + for (SwitchInst::ConstCaseIt i = SI.case_begin(), e = SI.case_end(); i != e; ++i) { Out << "\n "; writeOperand(i.getCaseValue(), true); @@ -1849,8 +1932,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Type *RetTy = FTy->getReturnType(); const AttributeSet &PAL = CI->getAttributes(); - if (PAL.getRetAttributes().hasAttributes()) - Out << ' ' << PAL.getRetAttributes().getAsString(); + if (PAL.hasAttributes(AttributeSet::ReturnIndex)) + Out << ' ' << PAL.getAsString(AttributeSet::ReturnIndex); // If possible, print out the short form of the call instruction. We can // only do this if the first argument is a pointer to a nonvararg function, @@ -1874,7 +1957,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { } Out << ')'; if (PAL.hasAttributes(AttributeSet::FunctionIndex)) - Out << ' ' << PAL.getAsString(AttributeSet::FunctionIndex); + Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes()); } else if (const InvokeInst *II = dyn_cast(&I)) { Operand = II->getCalledValue(); PointerType *PTy = cast(Operand->getType()); @@ -1888,8 +1971,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) { PrintCallingConv(II->getCallingConv(), Out); } - if (PAL.getRetAttributes().hasAttributes()) - Out << ' ' << PAL.getRetAttributes().getAsString(); + if (PAL.hasAttributes(AttributeSet::ReturnIndex)) + Out << ' ' << PAL.getAsString(AttributeSet::ReturnIndex); // If possible, print out the short form of the invoke instruction. We can // only do this if the first argument is a pointer to a nonvararg function, @@ -1914,7 +1997,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << ')'; if (PAL.hasAttributes(AttributeSet::FunctionIndex)) - Out << ' ' << PAL.getAsString(AttributeSet::FunctionIndex); + Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes()); Out << "\n to "; writeOperand(II->getNormalDest(), true); @@ -1923,7 +2006,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) { } else if (const AllocaInst *AI = dyn_cast(&I)) { Out << ' '; - TypePrinter.print(AI->getType()->getElementType(), Out); + if (AI->isUsedWithInAlloca()) + Out << "inalloca "; + TypePrinter.print(AI->getAllocatedType(), Out); if (!AI->getArraySize() || AI->isArrayAllocation()) { Out << ", "; writeOperand(AI->getArraySize(), true); @@ -1993,7 +2078,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) { if (SI->getAlignment()) Out << ", align " << SI->getAlignment(); } else if (const AtomicCmpXchgInst *CXI = dyn_cast(&I)) { - writeAtomic(CXI->getOrdering(), CXI->getSynchScope()); + writeAtomicCmpXchg(CXI->getSuccessOrdering(), CXI->getFailureOrdering(), + CXI->getSynchScope()); } else if (const AtomicRMWInst *RMWI = dyn_cast(&I)) { writeAtomic(RMWI->getOrdering(), RMWI->getSynchScope()); } else if (const FenceInst *FI = dyn_cast(&I)) { @@ -2010,9 +2096,9 @@ void AssemblyWriter::printInstruction(const Instruction &I) { unsigned Kind = InstMD[i].first; if (Kind < MDNames.size()) { Out << ", !" << MDNames[Kind]; - } else { - Out << ", !"; - } + } else { + Out << ", !"; + } Out << ' '; WriteAsOperandInternal(Out, InstMD[i].second, &TypePrinter, &Machine, TheModule); @@ -2031,7 +2117,7 @@ static void WriteMDNodeComment(const MDNode *Node, return; DIDescriptor Desc(Node); - if (Desc.getVersion() < LLVMDebugVersion11) + if (!Desc.Verify()) return; unsigned Tag = Desc.getTag(); @@ -2044,6 +2130,11 @@ static void WriteMDNodeComment(const MDNode *Node, } } +void AssemblyWriter::writeMDNode(unsigned Slot, const MDNode *Node) { + Out << '!' << Slot << " = metadata "; + printMDNodeBody(Node); +} + void AssemblyWriter::writeAllMDNodes() { SmallVector Nodes; Nodes.resize(Machine.mdn_size()); @@ -2052,8 +2143,7 @@ void AssemblyWriter::writeAllMDNodes() { Nodes[I->second] = cast(I->first); for (unsigned i = 0, e = Nodes.size(); i != e; ++i) { - Out << '!' << i << " = metadata "; - printMDNodeBody(Nodes[i]); + writeMDNode(i, Nodes[i]); } } @@ -2063,6 +2153,22 @@ void AssemblyWriter::printMDNodeBody(const MDNode *Node) { Out << "\n"; } +void AssemblyWriter::writeAllAttributeGroups() { + std::vector > asVec; + asVec.resize(Machine.as_size()); + + for (SlotTracker::as_iterator I = Machine.as_begin(), E = Machine.as_end(); + I != E; ++I) + asVec[I->second] = *I; + + for (std::vector >::iterator + I = asVec.begin(), E = asVec.end(); I != E; ++I) + Out << "attributes #" << I->second << " = { " + << I->first.getAsString(AttributeSet::FunctionIndex, true) << " }\n"; +} + +} // namespace llvm + //===----------------------------------------------------------------------===// // External Interface declarations //===----------------------------------------------------------------------===// @@ -2074,18 +2180,39 @@ void Module::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const { 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 << ""; - 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(this), OS); @@ -2097,24 +2224,20 @@ void Type::print(raw_ostream &OS) const { } } -void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const { - if (this == 0) { - ROS << "printing a value\n"; - return; - } +void Value::print(raw_ostream &ROS) const { formatted_raw_ostream OS(ROS); if (const Instruction *I = dyn_cast(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(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(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(GV)) W.printGlobal(V); else if (const Function *F = dyn_cast(GV)) @@ -2124,26 +2247,43 @@ void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const { } else if (const MDNode *N = dyn_cast(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(this)) { TypePrinting TypePrinter; TypePrinter.print(C->getType(), OS); OS << ' '; - WriteConstantInternal(OS, C, TypePrinter, 0, 0); + WriteConstantInternal(OS, C, TypePrinter, nullptr, nullptr); } else if (isa(this) || isa(this) || isa(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(this) && !isa(this)) || + hasName() || isa(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. @@ -2153,7 +2293,10 @@ void Value::dump() const { print(dbgs()); dbgs() << '\n'; } void Type::dump() const { print(dbgs()); } // 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()); }