#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/CodeGen/MachineInstr.h"
-#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/ADT/Statistic.h"
+#include "llvm/Target/TargetLoweringObjectFile.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/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cctype>
using namespace llvm;
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional,
cl::desc("Maximum number of threads (for emulation thread-local storage)"),
cl::Hidden,
cl::init(8));
namespace {
- class VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter {
- DwarfWriter *DW;
+ class XCoreAsmPrinter : public AsmPrinter {
const XCoreSubtarget &Subtarget;
public:
- explicit XCoreAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
- const TargetAsmInfo *T, bool V)
- : AsmPrinter(O, TM, T, V), DW(0),
- 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 printOperand(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, raw_ostream &O) {
+ printInlineJT(MI, opNum, O, ".jmptable32");
+ }
+ 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 std::string &name);
- void emitExternDirective(const std::string &name);
-
- void emitArrayBound(const std::string &name, const GlobalVariable *GV);
- virtual void PrintGlobalVariable(const GlobalVariable *GV);
+ void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
+ virtual void EmitGlobalVariable(const GlobalVariable *GV);
- void emitFunctionStart(MachineFunction &MF);
- void emitFunctionEnd(MachineFunction &MF);
+ void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen'd.
+ static const char *getRegisterName(unsigned RegNo);
- bool printInstruction(const MachineInstr *MI); // autogenerated.
- void printMachineInstruction(const MachineInstr *MI);
- bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
-
- void getAnalysisUsage(AnalysisUsage &AU) const {
- AsmPrinter::getAnalysisUsage(AU);
- AU.setPreservesAll();
- AU.addRequired<MachineModuleInfo>();
- AU.addRequired<DwarfWriter>();
- }
+ void EmitFunctionEntryLabel();
+ void EmitInstruction(const MachineInstr *MI);
+ void EmitFunctionBodyEnd();
};
} // end of anonymous namespace
#include "XCoreGenAsmWriter.inc"
-void XCoreAsmPrinter::
-emitGlobalDirective(const std::string &name)
-{
- O << TAI->getGlobalDirective() << name;
- O << "\n";
-}
-
-void XCoreAsmPrinter::
-emitExternDirective(const std::string &name)
-{
- O << "\t.extern\t" << name;
- O << '\n';
-}
-
-void XCoreAsmPrinter::
-emitArrayBound(const std::string &name, 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 << TAI->getGlobalDirective() << name << ".globound" << "\n";
- O << TAI->getSetDirective() << name << ".globound" << ","
- << ATy->getNumElements() << "\n";
+ if (ArrayType *ATy = dyn_cast<ArrayType>(
+ cast<PointerType>(GV->getType())->getElementType())) {
+ 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 << TAI->getWeakDefDirective() << name << ".globound" << "\n";
+ OutStreamer.EmitRawText(MAI->getWeakDefDirective() +Twine(Sym->getName())+
+ ".globound");
}
}
}
-void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) {
+void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
// Check to see if this is a special global used by LLVM, if so, emit it.
if (!GV->hasInitializer() ||
EmitSpecialLLVMGlobal(GV))
return;
const TargetData *TD = TM.getTargetData();
+ OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM));
+
- SwitchToSection(TAI->SectionForGlobal(GV));
-
- std::string name = Mang->getMangledName(GV);
- Constant *C = GV->getInitializer();
+ MCSymbol *GVSym = Mang->getSymbol(GV);
+ const Constant *C = GV->getInitializer();
unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
// Mark the start of the global
- O << "\t.cc_top " << name << ".data," << name << "\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(name, GV);
- emitGlobalDirective(name);
+ emitArrayBound(GVSym, GV);
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
+
// TODO Use COMDAT groups for LinkOnceLinkage
- if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
- O << TAI->getWeakDefDirective() << name << "\n";
- }
+ if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
// FALL THROUGH
case GlobalValue::InternalLinkage:
case GlobalValue::PrivateLinkage:
- case GlobalValue::LinkerPrivateLinkage:
break;
- case GlobalValue::GhostLinkage:
- llvm_unreachable("Should not have any unmaterialized functions!");
case GlobalValue::DLLImportLinkage:
llvm_unreachable("DLLImport linkage is not supported by this target!");
case GlobalValue::DLLExportLinkage:
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 (TAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type " << name << ",@object\n";
- O << "\t.size " << name << "," << Size << "\n";
+ if (MAI->hasDotTypeDotSizeDirective()) {
+ OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
+ OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," +
+ Twine(Size));
}
- O << name << ":\n";
+ OutStreamer.EmitLabel(GVSym);
EmitGlobalConstant(C);
if (GV->isThreadLocal()) {
- for (unsigned i = 1; i < MaxThreads; ++i) {
+ for (unsigned i = 1; i < MaxThreads; ++i)
EmitGlobalConstant(C);
- }
- }
- if (Size < 4) {
- // The ABI requires that unsigned scalar types smaller than 32 bits
- // are are padded to 32 bits.
- EmitZeros(4 - Size);
}
+ // The ABI requires that unsigned scalar types smaller than 32 bits
+ // are padded to 32 bits.
+ if (Size < 4)
+ OutStreamer.EmitZeros(4 - Size, 0);
// Mark the end of the global
- O << "\t.cc_bottom " << name << ".data\n";
-}
-
-/// 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();
-
- SwitchToSection(TAI->SectionForGlobal(F));
-
- // Mark the start of the function
- O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\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(CurrentFnName);
- break;
- case Function::LinkOnceAnyLinkage:
- case Function::LinkOnceODRLinkage:
- case Function::WeakAnyLinkage:
- case Function::WeakODRLinkage:
- // TODO Use COMDAT groups for LinkOnceLinkage
- O << TAI->getGlobalDirective() << CurrentFnName << "\n";
- O << TAI->getWeakDefDirective() << CurrentFnName << "\n";
- break;
- }
- // (1 << 1) byte aligned
- EmitAlignment(MF.getAlignment(), F, 1);
- if (TAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type " << CurrentFnName << ",@function\n";
- }
- O << CurrentFnName << ":\n";
-}
-
-/// Emit the directives on the end of functions
-void XCoreAsmPrinter::
-emitFunctionEnd(MachineFunction &MF)
-{
- // Mark the end of the function
- O << "\t.cc_bottom " << CurrentFnName << ".function\n";
+ OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data");
}
-/// runOnMachineFunction - This uses the printMachineInstruction()
-/// method to print assembly for each instruction.
-///
-bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF)
-{
- this->MF = &MF;
-
- SetupMachineFunction(MF);
-
- // Print out constants referenced by the function
- EmitConstantPool(MF.getConstantPool());
-
- // Print out jump tables referenced by the function
- EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
-
- // Emit the function start directives
- emitFunctionStart(MF);
-
- // Emit pre-function debug information.
- DW->BeginFunction(&MF);
-
- // Print out code for the function.
- for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
- I != E; ++I) {
-
- // Print a label for the basic block.
- if (I != MF.begin()) {
- printBasicBlockLabel(I, true , true);
- O << '\n';
- }
-
- for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II) {
- // Print the assembly for the instruction.
- O << "\t";
- printMachineInstruction(II);
- }
-
- // Each Basic Block is separated by a newline
- O << '\n';
- }
-
+/// EmitFunctionBodyEnd - Targets can override this to emit stuff after
+/// the last basic block in the function.
+void XCoreAsmPrinter::EmitFunctionBodyEnd() {
// Emit function end directives
- emitFunctionEnd(MF);
-
- // Emit post-function debug information.
- DW->EndFunction(&MF);
+ OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) +
+ ".function");
+}
- // We didn't modify anything.
- 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, raw_ostream &O,
+ const std::string &directive) {
+ unsigned JTI = MI->getOperand(opNum).getIndex();
+ const MachineFunction *MF = MI->getParent()->getParent();
+ const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
+ const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
+ const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
+ O << "\t" << directive << " ";
+ for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
+ MachineBasicBlock *MBB = JTBBs[i];
+ if (i > 0)
+ O << ",";
+ 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:
- if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
- O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
- else
- llvm_unreachable("not implemented");
+ O << getRegisterName(MO.getReg());
break;
case MachineOperand::MO_Immediate:
O << MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
+ O << *MO.getMBB()->getSymbol();
break;
case MachineOperand::MO_GlobalAddress:
- O << Mang->getMangledName(MO.getGlobal());
+ O << *Mang->getSymbol(MO.getGlobal());
break;
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
break;
case MachineOperand::MO_ConstantPoolIndex:
- O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
+ O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
<< '_' << MO.getIndex();
break;
case MachineOperand::MO_JumpTableIndex:
- O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
+ O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << MO.getIndex();
break;
+ case MachineOperand::MO_BlockAddress:
+ O << *GetBlockAddressSymbol(MO.getBlockAddress());
+ break;
default:
llvm_unreachable("not implemented");
}
/// 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::printMachineInstruction(const MachineInstr *MI) {
- ++EmittedInsts;
+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 ";
- O << TM.getRegisterInfo()->get(dst).AsmName;
- O << ", ";
- O << TM.getRegisterInfo()->get(src).AsmName;
- O << "\n";
- return;
- }
- if (printInstruction(MI)) {
- return;
- }
- llvm_unreachable("Unhandled instruction in asm writer!");
-}
-
-bool XCoreAsmPrinter::doInitialization(Module &M) {
- bool Result = AsmPrinter::doInitialization(M);
- DW = getAnalysisIfAvailable<DwarfWriter>();
-
- return Result;
+ if (MI->getOpcode() == XCore::ADD_2rus && !MI->getOperand(2).getImm())
+ O << "\tmov " << getRegisterName(MI->getOperand(0).getReg()) << ", "
+ << getRegisterName(MI->getOperand(1).getReg());
+ else
+ printInstruction(MI, O);
+ OutStreamer.EmitRawText(O.str());
}
-
-
// Force static initialization.
-extern "C" void LLVMInitializeXCoreTarget() {
- RegisterTargetMachine<XCoreTargetMachine> X(TheXCoreTarget);
- RegisterAsmPrinter<XCoreAsmPrinter> Y(TheXCoreTarget);
+extern "C" void LLVMInitializeXCoreAsmPrinter() {
+ RegisterAsmPrinter<XCoreAsmPrinter> X(TheXCoreTarget);
}