#include "llvm/InlineAsm.h"
#include "llvm/Instruction.h"
#include "llvm/Instructions.h"
+#include "llvm/MDNode.h"
#include "llvm/Module.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cctype>
+#include <map>
using namespace llvm;
// Make virtual table appear in this compilation unit.
case GlobalPrefix: OS << '@'; break;
case LabelPrefix: break;
case LocalPrefix: OS << '%'; break;
- }
+ }
// Scan the name to see if it needs quotes first.
bool NeedsQuotes = isdigit(NameStr[0]);
raw_ostream &OS, bool IgnoreTopLevelName) {
// Check to see if the type is named.
if (!IgnoreTopLevelName) {
- DenseMap<const Type*, std::string> &TM = getTypeNamesMap(TypeNames);
+ DenseMap<const Type *, std::string> &TM = getTypeNamesMap(TypeNames);
DenseMap<const Type *, std::string>::iterator I = TM.find(Ty);
if (I != TM.end()) {
OS << I->second;
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::IntegerTyID:
OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
break;
return;
// If this is a structure or opaque type, add a name for the type.
- if ((isa<StructType>(Ty) || isa<OpaqueType>(Ty))
- && !TP.hasTypeName(Ty)) {
+ if (((isa<StructType>(Ty) && cast<StructType>(Ty)->getNumElements())
+ || isa<OpaqueType>(Ty)) && !TP.hasTypeName(Ty)) {
TP.addTypeName(Ty, "%"+utostr(unsigned(NumberedTypes.size())));
NumberedTypes.push_back(Ty);
}
// Some form of long double. These appear as a magic letter identifying
// the type, then a fixed number of hex digits.
Out << "0x";
- if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended)
+ if (&CFP->getValueAPF().getSemantics() == &APFloat::x87DoubleExtended) {
Out << 'K';
- else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad)
+ // api needed to prevent premature destruction
+ APInt api = CFP->getValueAPF().bitcastToAPInt();
+ const uint64_t* p = api.getRawData();
+ uint64_t word = p[1];
+ int shiftcount=12;
+ int width = api.getBitWidth();
+ for (int j=0; j<width; j+=4, shiftcount-=4) {
+ unsigned int nibble = (word>>shiftcount) & 15;
+ if (nibble < 10)
+ Out << (unsigned char)(nibble + '0');
+ else
+ Out << (unsigned char)(nibble - 10 + 'A');
+ if (shiftcount == 0 && j+4 < width) {
+ word = *p;
+ shiftcount = 64;
+ if (width-j-4 < 64)
+ shiftcount = width-j-4;
+ }
+ }
+ return;
+ } else if (&CFP->getValueAPF().getSemantics() == &APFloat::IEEEquad)
Out << 'L';
else if (&CFP->getValueAPF().getSemantics() == &APFloat::PPCDoubleDouble)
Out << 'M';
Out << "undef";
return;
}
+
+ if (const MDString *S = dyn_cast<MDString>(CV)) {
+ Out << "!\"";
+ PrintEscapedString(S->begin(), S->size(), Out);
+ Out << '"';
+ return;
+ }
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
Out << CE->getOpcodeName();
TypePrinting TypePrinter;
AssemblyAnnotationWriter *AnnotationWriter;
std::vector<const Type*> NumberedTypes;
+
+ // Each MDNode is assigned unique MetadataIDNo.
+ std::map<const MDNode *, unsigned> MDNodes;
+ unsigned MetadataIDNo;
public:
inline AssemblyWriter(raw_ostream &o, SlotTracker &Mac, const Module *M,
AssemblyAnnotationWriter *AAW)
- : Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW) {
+ : Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW), MetadataIDNo(0) {
AddModuleTypesToPrinter(TypePrinter, NumberedTypes, M);
}
void writeOperand(const Value *Op, bool PrintType);
void writeParamOperand(const Value *Operand, Attributes Attrs);
+ void printMDNode(const MDNode *Node, bool StandAlone);
const Module* getModule() { return TheModule; }
switch (LT) {
case GlobalValue::PrivateLinkage: Out << "private "; break;
case GlobalValue::InternalLinkage: Out << "internal "; break;
+ case GlobalValue::AvailableExternallyLinkage:
+ Out << "available_externally ";
+ break;
case GlobalValue::LinkOnceAnyLinkage: Out << "linkonce "; break;
case GlobalValue::LinkOnceODRLinkage: Out << "linkonce_odr "; break;
case GlobalValue::WeakAnyLinkage: Out << "weak "; break;
}
void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
+ if (GV->hasInitializer())
+ // If GV is initialized using Metadata then separate out metadata
+ // operands used by the initializer. Note, MDNodes are not cyclic.
+ if (MDNode *N = dyn_cast<MDNode>(GV->getInitializer())) {
+ SmallVector<const MDNode *, 4> WorkList;
+ // Collect MDNodes used by the initializer.
+ for (MDNode::const_elem_iterator I = N->elem_begin(), E = N->elem_end();
+ I != E; ++I) {
+ const Value *TV = *I;
+ if (TV)
+ if (const MDNode *NN = dyn_cast<MDNode>(TV))
+ WorkList.push_back(NN);
+ }
+
+ // Print MDNodes used by the initializer.
+ while (!WorkList.empty()) {
+ const MDNode *N = WorkList.back(); WorkList.pop_back();
+ printMDNode(N, true);
+ Out << '\n';
+ }
+ }
+
if (GV->hasName()) {
PrintLLVMName(Out, GV);
Out << " = ";
if (GV->hasInitializer()) {
Out << ' ';
- writeOperand(GV->getInitializer(), false);
+ if (MDNode *N = dyn_cast<MDNode>(GV->getInitializer()))
+ printMDNode(N, false);
+ else
+ writeOperand(GV->getInitializer(), false);
}
if (GV->hasSection())
Out << '\n';
}
+void AssemblyWriter::printMDNode(const MDNode *Node,
+ bool StandAlone) {
+ std::map<const MDNode *, unsigned>::iterator MI = MDNodes.find(Node);
+ // If this node is already printed then just refer it using its Metadata
+ // id number.
+ if (MI != MDNodes.end()) {
+ if (!StandAlone)
+ Out << "!" << MI->second;
+ return;
+ }
+
+ if (StandAlone) {
+ // Print standalone MDNode.
+ // !42 = !{ ... }
+ Out << "!" << MetadataIDNo << " = ";
+ Out << "constant metadata ";
+ }
+
+ Out << "!{";
+ for (MDNode::const_elem_iterator I = Node->elem_begin(), E = Node->elem_end();
+ I != E;) {
+ const Value *TV = *I;
+ if (!TV)
+ Out << "null";
+ else if (const MDNode *N = dyn_cast<MDNode>(TV)) {
+ TypePrinter.print(N->getType(), Out);
+ Out << ' ';
+ printMDNode(N, StandAlone);
+ }
+ else if (!*I)
+ Out << "null";
+ else
+ writeOperand(*I, true);
+ if (++I != E)
+ Out << ", ";
+ }
+ Out << "}";
+
+ MDNodes[Node] = MetadataIDNo++;
+}
+
void AssemblyWriter::printAlias(const GlobalAlias *GA) {
// Don't crash when dumping partially built GA
if (!GA->hasName())
Out << ' ';
PrintLLVMName(Out, GA);
} else {
- const ConstantExpr *CE = 0;
- if ((CE = dyn_cast<ConstantExpr>(Aliasee)) &&
- (CE->getOpcode() == Instruction::BitCast)) {
- writeOperand(CE, false);
- } else
- assert(0 && "Unsupported aliasee");
+ const ConstantExpr *CE = cast<ConstantExpr>(Aliasee);
+ // The only valid GEP is an all zero GEP.
+ assert((CE->getOpcode() == Instruction::BitCast ||
+ CE->getOpcode() == Instruction::GetElementPtr) &&
+ "Unsupported aliasee");
+ writeOperand(CE, false);
}
printInfoComment(*GA);
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_FastCall: Out << "x86_fastcallcc "; 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;
default: Out << "cc" << F->getCallingConv() << " "; break;
}
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_FastCall: Out << " x86_fastcallcc"; 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;
default: Out << " cc" << CI->getCallingConv(); 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::ARM_APCS: Out << " arm_apcscc "; break;
+ case CallingConv::ARM_AAPCS: Out << " arm_aapcscc "; break;
+ case CallingConv::ARM_AAPCS_VFP:Out << " arm_aapcs_vfpcc "; break;
default: Out << " cc" << II->getCallingConv(); break;
}
W.write(BB);
} else if (const GlobalValue *GV = dyn_cast<GlobalValue>(this)) {
SlotTracker SlotTable(GV->getParent());
- AssemblyWriter W(OS, SlotTable, GV->getParent(), 0);
+ AssemblyWriter W(OS, SlotTable, GV->getParent(), AAW);
W.write(GV);
+ } else if (const MDNode *N = dyn_cast<MDNode>(this)) {
+ TypePrinting TypePrinter;
+ TypePrinter.print(N->getType(), OS);
+ OS << ' ';
+ // FIXME: Do we need a slot tracker for metadata ?
+ SlotTracker SlotTable((const Function *)NULL);
+ AssemblyWriter W(OS, SlotTable, NULL, AAW);
+ W.printMDNode(N, false);
} else if (const Constant *C = dyn_cast<Constant>(this)) {
TypePrinting TypePrinter;
TypePrinter.print(C->getType(), OS);
}
// Value::dump - allow easy printing of Values from the debugger.
-void Value::dump() const { print(errs()); errs() << '\n'; errs().flush(); }
+void Value::dump() const { print(errs()); errs() << '\n'; }
// Type::dump - allow easy printing of Types from the debugger.
// This one uses type names from the given context module
void Type::dump(const Module *Context) const {
WriteTypeSymbolic(errs(), this, Context);
errs() << '\n';
- errs().flush();
}
// Type::dump - allow easy printing of Types from the debugger.
void Type::dump() const { dump(0); }
// Module::dump() - Allow printing of Modules from the debugger.
-void Module::dump() const { print(errs(), 0); errs().flush(); }
+void Module::dump() const { print(errs(), 0); }