#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cctype>
using namespace llvm;
class XCoreAsmPrinter : public AsmPrinter {
const XCoreSubtarget &Subtarget;
public:
- explicit XCoreAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
- MCContext &Ctx, MCStreamer &Streamer,
- const MCAsmInfo *T)
- : AsmPrinter(O, TM, Ctx, Streamer, T),
- Subtarget(TM.getSubtarget<XCoreSubtarget>()) {}
+ explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
+ : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<XCoreSubtarget>()){}
virtual const char *getPassName() const {
return "XCore Assembly Printer";
}
- void printMemOperand(const MachineInstr *MI, int opNum);
- void printInlineJT(const MachineInstr *MI, int opNum,
+ void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
+ void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
const std::string &directive = ".jmptable");
- void printInlineJT32(const MachineInstr *MI, int opNum) {
- printInlineJT(MI, opNum, ".jmptable32");
+ void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {
+ printInlineJT(MI, opNum, O, ".jmptable32");
}
- void printOperand(const MachineInstr *MI, int opNum);
+ void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant, const char *ExtraCode);
+ unsigned AsmVariant, const char *ExtraCode,
+ raw_ostream &O);
- void emitGlobalDirective(const MCSymbol *Sym);
-
- void emitArrayBound(const MCSymbol *Sym, const GlobalVariable *GV);
+ void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
virtual void EmitGlobalVariable(const GlobalVariable *GV);
- void emitFunctionStart(MachineFunction &MF);
-
- void printInstruction(const MachineInstr *MI); // autogenerated.
+ void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen'd.
static const char *getRegisterName(unsigned RegNo);
- bool runOnMachineFunction(MachineFunction &MF);
+ void EmitFunctionEntryLabel();
void EmitInstruction(const MachineInstr *MI);
void EmitFunctionBodyEnd();
-
- void getAnalysisUsage(AnalysisUsage &AU) const {
- AsmPrinter::getAnalysisUsage(AU);
- AU.setPreservesAll();
- AU.addRequired<MachineModuleInfo>();
- AU.addRequired<DwarfWriter>();
- }
};
} // end of anonymous namespace
#include "XCoreGenAsmWriter.inc"
-void XCoreAsmPrinter::emitGlobalDirective(const MCSymbol *Sym) {
- O << MAI->getGlobalDirective() << *Sym << "\n";
-}
-
-void XCoreAsmPrinter::emitArrayBound(const MCSymbol *Sym,
- const GlobalVariable *GV) {
+void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
assert(((GV->hasExternalLinkage() ||
GV->hasWeakLinkage()) ||
GV->hasLinkOnceLinkage()) && "Unexpected linkage");
if (const ArrayType *ATy = dyn_cast<ArrayType>(
cast<PointerType>(GV->getType())->getElementType())) {
- O << MAI->getGlobalDirective() << *Sym;
- O << ".globound" << "\n";
- O << "\t.set\t" << *Sym;
- O << ".globound" << "," << ATy->getNumElements() << "\n";
+ OutStreamer.EmitSymbolAttribute(Sym, MCSA_Global);
+ // FIXME: MCStreamerize.
+ OutStreamer.EmitRawText(StringRef(".globound"));
+ OutStreamer.EmitRawText("\t.set\t" + Twine(Sym->getName()));
+ OutStreamer.EmitRawText(".globound," + Twine(ATy->getNumElements()));
if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
// TODO Use COMDAT groups for LinkOnceLinkage
- O << MAI->getWeakDefDirective() << *Sym << ".globound" << "\n";
+ OutStreamer.EmitRawText(MAI->getWeakDefDirective() +Twine(Sym->getName())+
+ ".globound");
}
}
}
unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
// Mark the start of the global
- O << "\t.cc_top " << *GVSym << ".data," << *GVSym << "\n";
+ OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," +
+ GVSym->getName());
switch (GV->getLinkage()) {
case GlobalValue::AppendingLinkage:
- llvm_report_error("AppendingLinkage is not supported by this target!");
+ report_fatal_error("AppendingLinkage is not supported by this target!");
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
case GlobalValue::ExternalLinkage:
emitArrayBound(GVSym, GV);
- emitGlobalDirective(GVSym);
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
+
// TODO Use COMDAT groups for LinkOnceLinkage
if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())
- O << MAI->getWeakDefDirective() << *GVSym << "\n";
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
// FALL THROUGH
case GlobalValue::InternalLinkage:
case GlobalValue::PrivateLinkage:
llvm_unreachable("Unknown linkage type!");
}
- EmitAlignment(Align, GV, 2);
+ EmitAlignment(Align > 2 ? Align : 2, GV);
unsigned Size = TD->getTypeAllocSize(C->getType());
if (GV->isThreadLocal()) {
Size *= MaxThreads;
}
if (MAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type " << *GVSym << ",@object\n";
- O << "\t.size " << *GVSym << "," << Size << "\n";
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
+ OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," +
+ Twine(Size));
}
- O << *GVSym << ":\n";
+ OutStreamer.EmitLabel(GVSym);
EmitGlobalConstant(C);
if (GV->isThreadLocal()) {
OutStreamer.EmitZeros(4 - Size, 0);
// Mark the end of the global
- O << "\t.cc_bottom " << *GVSym << ".data\n";
+ OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data");
}
-/// Emit the directives on the start of functions
-void XCoreAsmPrinter::emitFunctionStart(MachineFunction &MF) {
- // Print out the label for the function.
- const Function *F = MF.getFunction();
-
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
-
- // Mark the start of the function
- O << "\t.cc_top " << *CurrentFnSym << ".function," << *CurrentFnSym << "\n";
-
- switch (F->getLinkage()) {
- default: llvm_unreachable("Unknown linkage type!");
- case Function::InternalLinkage: // Symbols default to internal.
- case Function::PrivateLinkage:
- case Function::LinkerPrivateLinkage:
- break;
- case Function::ExternalLinkage:
- emitGlobalDirective(CurrentFnSym);
- break;
- case Function::LinkOnceAnyLinkage:
- case Function::LinkOnceODRLinkage:
- case Function::WeakAnyLinkage:
- case Function::WeakODRLinkage:
- // TODO Use COMDAT groups for LinkOnceLinkage
- O << MAI->getGlobalDirective() << *CurrentFnSym << "\n";
- O << MAI->getWeakDefDirective() << *CurrentFnSym << "\n";
- break;
- }
- // (1 << 1) byte aligned
- EmitAlignment(MF.getAlignment(), F, 1);
- if (MAI->hasDotTypeDotSizeDirective())
- O << "\t.type " << *CurrentFnSym << ",@function\n";
-
- O << *CurrentFnSym << ":\n";
-}
-
-
/// EmitFunctionBodyEnd - Targets can override this to emit stuff after
/// the last basic block in the function.
void XCoreAsmPrinter::EmitFunctionBodyEnd() {
// Emit function end directives
- O << "\t.cc_bottom " << *CurrentFnSym << ".function\n";
+ OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) +
+ ".function");
}
-/// runOnMachineFunction - This uses the printMachineInstruction()
-/// method to print assembly for each instruction.
-///
-bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- SetupMachineFunction(MF);
-
- // Print out constants referenced by the function
- EmitConstantPool();
-
- // Emit the function start directives
- emitFunctionStart(MF);
-
- // Emit pre-function debug information.
- DW->BeginFunction(&MF);
-
- EmitFunctionBody();
- return false;
+void XCoreAsmPrinter::EmitFunctionEntryLabel() {
+ // Mark the start of the function
+ OutStreamer.EmitRawText("\t.cc_top " + Twine(CurrentFnSym->getName()) +
+ ".function," + CurrentFnSym->getName());
+ OutStreamer.EmitLabel(CurrentFnSym);
}
-void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum)
-{
- printOperand(MI, opNum);
+void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
+ raw_ostream &O) {
+ printOperand(MI, opNum, O);
- if (MI->getOperand(opNum+1).isImm()
- && MI->getOperand(opNum+1).getImm() == 0)
+ if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0)
return;
O << "+";
- printOperand(MI, opNum+1);
+ printOperand(MI, opNum+1, O);
}
void XCoreAsmPrinter::
-printInlineJT(const MachineInstr *MI, int opNum, const std::string &directive)
-{
+printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
+ const std::string &directive) {
unsigned JTI = MI->getOperand(opNum).getIndex();
const MachineFunction *MF = MI->getParent()->getParent();
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
MachineBasicBlock *MBB = JTBBs[i];
if (i > 0)
O << ",";
- O << *MBB->getSymbol(OutContext);
+ O << *MBB->getSymbol();
}
}
-void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
+void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
+ raw_ostream &O) {
const MachineOperand &MO = MI->getOperand(opNum);
switch (MO.getType()) {
case MachineOperand::MO_Register:
O << MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
- O << *MO.getMBB()->getSymbol(OutContext);
+ O << *MO.getMBB()->getSymbol();
break;
case MachineOperand::MO_GlobalAddress:
O << *Mang->getSymbol(MO.getGlobal());
/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant,
- const char *ExtraCode) {
- printOperand(MI, OpNo);
+ unsigned AsmVariant,const char *ExtraCode,
+ raw_ostream &O) {
+ printOperand(MI, OpNo, O);
return false;
}
void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) {
+ SmallString<128> Str;
+ raw_svector_ostream O(Str);
+
// Check for mov mnemonic
unsigned src, dst, srcSR, dstSR;
if (TM.getInstrInfo()->isMoveInstr(*MI, src, dst, srcSR, dstSR)) {
O << "\tmov " << getRegisterName(dst) << ", ";
O << getRegisterName(src);
- OutStreamer.AddBlankLine();
- return;
+ } else {
+ printInstruction(MI, O);
}
- printInstruction(MI);
- OutStreamer.AddBlankLine();
+ OutStreamer.EmitRawText(O.str());
}
// Force static initialization.