//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "asm-printer"
#include "XCore.h"
#include "InstPrinter/XCoreInstPrinter.h"
#include "XCoreInstrInfo.h"
#include "XCoreMCInstLower.h"
#include "XCoreSubtarget.h"
#include "XCoreTargetMachine.h"
+#include "XCoreTargetStreamer.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/DebugInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/CommandLine.h"
+#include "llvm/MC/MCSymbolELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include <algorithm>
#include <cctype>
using namespace llvm;
-static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional,
- cl::desc("Maximum number of threads (for emulation thread-local storage)"),
- cl::Hidden,
- cl::value_desc("number"),
- cl::init(8));
+#define DEBUG_TYPE "asm-printer"
namespace {
class XCoreAsmPrinter : public AsmPrinter {
- const XCoreSubtarget &Subtarget;
XCoreMCInstLower MCInstLowering;
- void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
+ XCoreTargetStreamer &getTargetStreamer();
+
public:
- explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
- : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<XCoreSubtarget>()),
- MCInstLowering(*this) {}
+ explicit XCoreAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> Streamer)
+ : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(*this) {}
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "XCore Assembly Printer";
}
void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode,
- raw_ostream &O);
+ raw_ostream &O) override;
+ bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
+ unsigned AsmVariant, const char *ExtraCode,
+ raw_ostream &O) override;
void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
- virtual void EmitGlobalVariable(const GlobalVariable *GV);
+ void EmitGlobalVariable(const GlobalVariable *GV) override;
- void EmitFunctionEntryLabel();
- void EmitInstruction(const MachineInstr *MI);
- void EmitFunctionBodyStart();
- void EmitFunctionBodyEnd();
- virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const;
+ void EmitFunctionEntryLabel() override;
+ void EmitInstruction(const MachineInstr *MI) override;
+ void EmitFunctionBodyStart() override;
+ void EmitFunctionBodyEnd() override;
};
} // end of anonymous namespace
+XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() {
+ return static_cast<XCoreTargetStreamer&>(*OutStreamer->getTargetStreamer());
+}
+
void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
- assert(((GV->hasExternalLinkage() ||
- GV->hasWeakLinkage()) ||
- GV->hasLinkOnceLinkage()) && "Unexpected linkage");
+ assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() ||
+ GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) &&
+ "Unexpected linkage");
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
- OutStreamer.EmitRawText(MAI->getWeakDefDirective() +Twine(Sym->getName())+
- ".globound");
+ cast<PointerType>(GV->getType())->getElementType())) {
+
+ MCSymbol *SymGlob = OutContext.getOrCreateSymbol(
+ Twine(Sym->getName() + StringRef(".globound")));
+ OutStreamer->EmitSymbolAttribute(SymGlob, MCSA_Global);
+ OutStreamer->EmitAssignment(SymGlob,
+ MCConstantExpr::create(ATy->getNumElements(),
+ OutContext));
+ if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
+ GV->hasCommonLinkage()) {
+ OutStreamer->EmitSymbolAttribute(SymGlob, MCSA_Weak);
}
}
}
EmitSpecialLLVMGlobal(GV))
return;
- const DataLayout *TD = TM.getDataLayout();
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM));
+ const DataLayout &DL = getDataLayout();
+ OutStreamer->SwitchSection(
+ getObjFileLowering().SectionForGlobal(GV, *Mang, TM));
-
- MCSymbol *GVSym = Mang->getSymbol(GV);
+ MCSymbol *GVSym = getSymbol(GV);
const Constant *C = GV->getInitializer();
- unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
-
+ unsigned Align = (unsigned)DL.getPreferredTypeAlignmentShift(C->getType());
+
// Mark the start of the global
- OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," +
- GVSym->getName());
+ getTargetStreamer().emitCCTopData(GVSym->getName());
switch (GV->getLinkage()) {
case GlobalValue::AppendingLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
case GlobalValue::ExternalLinkage:
+ case GlobalValue::CommonLinkage:
emitArrayBound(GVSym, GV);
- OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global);
- // TODO Use COMDAT groups for LinkOnceLinkage
- if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())
- OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
+ if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
+ GV->hasCommonLinkage())
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Weak);
// FALL THROUGH
case GlobalValue::InternalLinkage:
case GlobalValue::PrivateLinkage:
break;
- case GlobalValue::DLLImportLinkage:
- llvm_unreachable("DLLImport linkage is not supported by this target!");
- case GlobalValue::DLLExportLinkage:
- llvm_unreachable("DLLExport linkage is not supported by this target!");
default:
llvm_unreachable("Unknown linkage type!");
}
EmitAlignment(Align > 2 ? Align : 2, GV);
- unsigned Size = TD->getTypeAllocSize(C->getType());
if (GV->isThreadLocal()) {
- Size *= MaxThreads;
+ report_fatal_error("TLS is not supported by this target!");
}
+ unsigned Size = DL.getTypeAllocSize(C->getType());
if (MAI->hasDotTypeDotSizeDirective()) {
- OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
- OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," +
- Twine(Size));
- }
- OutStreamer.EmitLabel(GVSym);
-
- EmitGlobalConstant(C);
- if (GV->isThreadLocal()) {
- for (unsigned i = 1; i < MaxThreads; ++i)
- EmitGlobalConstant(C);
+ OutStreamer->EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
+ OutStreamer->emitELFSize(cast<MCSymbolELF>(GVSym),
+ MCConstantExpr::create(Size, OutContext));
}
+ OutStreamer->EmitLabel(GVSym);
+
+ EmitGlobalConstant(DL, C);
// The ABI requires that unsigned scalar types smaller than 32 bits
// are padded to 32 bits.
if (Size < 4)
- OutStreamer.EmitZeros(4 - Size, 0);
+ OutStreamer->EmitZeros(4 - Size);
// Mark the end of the global
- OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data");
+ getTargetStreamer().emitCCBottomData(GVSym->getName());
}
void XCoreAsmPrinter::EmitFunctionBodyStart() {
/// the last basic block in the function.
void XCoreAsmPrinter::EmitFunctionBodyEnd() {
// Emit function end directives
- OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) +
- ".function");
+ getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName());
}
void XCoreAsmPrinter::EmitFunctionEntryLabel() {
// Mark the start of the function
- OutStreamer.EmitRawText("\t.cc_top " + Twine(CurrentFnSym->getName()) +
- ".function," + CurrentFnSym->getName());
- OutStreamer.EmitLabel(CurrentFnSym);
+ getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName());
+ OutStreamer->EmitLabel(CurrentFnSym);
}
void XCoreAsmPrinter::
MachineBasicBlock *MBB = JTBBs[i];
if (i > 0)
O << ",";
- O << *MBB->getSymbol();
+ MBB->getSymbol()->print(O, MAI);
}
}
void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
raw_ostream &O) {
+ const DataLayout &DL = getDataLayout();
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();
+ MO.getMBB()->getSymbol()->print(O, MAI);
break;
case MachineOperand::MO_GlobalAddress:
- O << *Mang->getSymbol(MO.getGlobal());
- break;
- case MachineOperand::MO_ExternalSymbol:
- O << MO.getSymbolName();
+ getSymbol(MO.getGlobal())->print(O, MAI);
break;
case MachineOperand::MO_ConstantPoolIndex:
- O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
- << '_' << MO.getIndex();
- break;
- case MachineOperand::MO_JumpTableIndex:
- O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << MO.getIndex();
+ O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
+ << MO.getIndex();
break;
case MachineOperand::MO_BlockAddress:
- O << *GetBlockAddressSymbol(MO.getBlockAddress());
+ GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
break;
default:
llvm_unreachable("not implemented");
bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant,const char *ExtraCode,
raw_ostream &O) {
- // Does this asm operand have a single letter operand modifier?
- if (ExtraCode && ExtraCode[0])
- if (ExtraCode[1] != 0) return true; // Unknown modifier.
-
- switch (ExtraCode[0]) {
- default:
- // See if this is a generic print operand
- return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
- }
-
- printOperand(MI, OpNo, O);
- return false;
-}
+ // Print the operand if there is no operand modifier.
+ if (!ExtraCode || !ExtraCode[0]) {
+ printOperand(MI, OpNo, O);
+ return false;
+ }
-void XCoreAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
- raw_ostream &OS) {
- unsigned NOps = MI->getNumOperands();
- assert(NOps == 4);
- OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
- // cast away const; DIetc do not take const operands for some reason.
- DIVariable V(const_cast<MDNode *>(MI->getOperand(NOps-1).getMetadata()));
- OS << V.getName();
- OS << " <- ";
- // Frame address. Currently handles register +- offset only.
- assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
- OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS);
- OS << ']';
- OS << "+";
- printOperand(MI, NOps-2, OS);
+ // Otherwise fallback on the default implementation.
+ return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
}
-MachineLocation XCoreAsmPrinter::
-getDebugValueLocation(const MachineInstr *MI) const {
- // Handles frame addresses emitted in XCoreInstrInfo::emitFrameIndexDebugValue.
- assert(MI->getNumOperands() == 4 && "Invalid no. of machine operands!");
- assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm() &&
- "Unexpected MachineOperand types");
- return MachineLocation(MI->getOperand(0).getReg(),
- MI->getOperand(1).getImm());
+bool XCoreAsmPrinter::
+PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
+ unsigned AsmVariant, const char *ExtraCode,
+ raw_ostream &O) {
+ if (ExtraCode && ExtraCode[0]) {
+ return true; // Unknown modifier.
+ }
+ printOperand(MI, OpNum, O);
+ O << '[';
+ printOperand(MI, OpNum + 1, O);
+ O << ']';
+ return false;
}
void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) {
raw_svector_ostream O(Str);
switch (MI->getOpcode()) {
- case XCore::DBG_VALUE: {
- if (isVerbose() && OutStreamer.hasRawTextSupport()) {
- SmallString<128> TmpStr;
- raw_svector_ostream OS(TmpStr);
- PrintDebugValueComment(MI, OS);
- OutStreamer.EmitRawText(StringRef(OS.str()));
- }
- return;
- }
+ case XCore::DBG_VALUE:
+ llvm_unreachable("Should be handled target independently");
case XCore::ADD_2rus:
if (MI->getOperand(2).getImm() == 0) {
O << "\tmov "
<< XCoreInstPrinter::getRegisterName(MI->getOperand(0).getReg()) << ", "
<< XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());
- OutStreamer.EmitRawText(O.str());
+ OutStreamer->EmitRawText(O.str());
return;
}
break;
else
printInlineJT32(MI, 0, O);
O << '\n';
- OutStreamer.EmitRawText(O.str());
+ OutStreamer->EmitRawText(O.str());
return;
}
MCInst TmpInst;
MCInstLowering.Lower(MI, TmpInst);
- OutStreamer.EmitInstruction(TmpInst);
+ EmitToStreamer(*OutStreamer, TmpInst);
}
// Force static initialization.