-//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ------------------===//
+//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
//
// The LLVM Compiler Infrastructure
//
#define DEBUG_TYPE "asm-printer"
#include "MSP430.h"
+#include "InstPrinter/MSP430InstPrinter.h"
#include "MSP430InstrInfo.h"
+#include "MSP430MCInstLower.h"
#include "MSP430TargetMachine.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
+#include "llvm/Assembly/Writer.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/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Mangler.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Module.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
-
+#include "llvm/Target/Mangler.h"
using namespace llvm;
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
namespace {
- class VISIBILITY_HIDDEN MSP430AsmPrinter : public AsmPrinter {
+ class MSP430AsmPrinter : public AsmPrinter {
public:
- MSP430AsmPrinter(raw_ostream &O, MSP430TargetMachine &TM,
- const TargetAsmInfo *TAI, bool Fast, bool Verbose)
- : AsmPrinter(O, TM, TAI, Fast, Verbose) {}
+ MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
+ : AsmPrinter(TM, Streamer) {}
virtual const char *getPassName() const {
return "MSP430 Assembly Printer";
}
void printOperand(const MachineInstr *MI, int OpNum,
- const char* Modifier = 0);
+ raw_ostream &O, const char* Modifier = 0);
void printSrcMemOperand(const MachineInstr *MI, int OpNum,
- const char* Modifier = 0);
- void printCCOperand(const MachineInstr *MI, int OpNum);
- bool printInstruction(const MachineInstr *MI); // autogenerated.
- void printMachineInstruction(const MachineInstr * MI);
- bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
-
- void getAnalysisUsage(AnalysisUsage &AU) const {
- AsmPrinter::getAnalysisUsage(AU);
- AU.setPreservesAll();
- }
+ raw_ostream &O);
+ bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+ unsigned AsmVariant, const char *ExtraCode,
+ raw_ostream &O);
+ bool PrintAsmMemoryOperand(const MachineInstr *MI,
+ unsigned OpNo, unsigned AsmVariant,
+ const char *ExtraCode, raw_ostream &O);
+ void EmitInstruction(const MachineInstr *MI);
};
} // end of anonymous namespace
-#include "MSP430GenAsmWriter.inc"
-
-/// createMSP430CodePrinterPass - Returns a pass that prints the MSP430
-/// assembly code for a MachineFunction to the given output stream,
-/// using the given target machine description. This should work
-/// regardless of whether the function is in SSA form.
-///
-FunctionPass *llvm::createMSP430CodePrinterPass(raw_ostream &o,
- MSP430TargetMachine &tm,
- bool fast, bool verbose) {
- return new MSP430AsmPrinter(o, tm, tm.getTargetAsmInfo(), fast, verbose);
-}
-
-bool MSP430AsmPrinter::doInitialization(Module &M) {
- Mang = new Mangler(M, "", TAI->getPrivateGlobalPrefix());
- return false; // success
-}
-
-
-bool MSP430AsmPrinter::doFinalization(Module &M) {
- return AsmPrinter::doFinalization(M);
-}
-
-bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &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';
- }
-
- // We didn't modify anything
- return false;
-}
-
-void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
- ++EmittedInsts;
-
- // Call the autogenerated instruction printer routines.
- if (printInstruction(MI))
- return;
-
- assert(0 && "Should not happen");
-}
void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
- const char* Modifier) {
+ raw_ostream &O, const char *Modifier) {
const MachineOperand &MO = MI->getOperand(OpNum);
switch (MO.getType()) {
+ default: llvm_unreachable("Not implemented yet!");
case MachineOperand::MO_Register:
- assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
- "Virtual registers should be already mapped!");
- O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
+ O << MSP430InstPrinter::getRegisterName(MO.getReg());
return;
case MachineOperand::MO_Immediate:
if (!Modifier || strcmp(Modifier, "nohash"))
O << MO.getImm();
return;
case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
+ O << *MO.getMBB()->getSymbol();
return;
case MachineOperand::MO_GlobalAddress: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- bool isCallOp = Modifier && !strcmp(Modifier, "call");
- std::string Name = Mang->getValueName(MO.getGlobal());
- assert(MO.getOffset() == 0 && "No offsets allowed!");
+ uint64_t Offset = MO.getOffset();
+
+ // If the global address expression is a part of displacement field with a
+ // register base, we should not emit any prefix symbol here, e.g.
+ // mov.w &foo, r1
+ // vs
+ // mov.w glb(r1), r2
+ // Otherwise (!) msp430-as will silently miscompile the output :(
+ if (!Modifier || strcmp(Modifier, "nohash"))
+ O << (isMemOp ? '&' : '#');
+ if (Offset)
+ O << '(' << Offset << '+';
- if (isCallOp)
- O << '#';
- else if (isMemOp)
- O << '&';
+ O << *Mang->getSymbol(MO.getGlobal());
- O << Name;
+ if (Offset)
+ O << ')';
return;
}
case MachineOperand::MO_ExternalSymbol: {
- bool isCallOp = Modifier && !strcmp(Modifier, "call");
- std::string Name(TAI->getGlobalPrefix());
- Name += MO.getSymbolName();
- if (isCallOp)
- O << '#';
- O << Name;
+ bool isMemOp = Modifier && !strcmp(Modifier, "mem");
+ O << (isMemOp ? '&' : '#');
+ O << MAI->getGlobalPrefix() << MO.getSymbolName();
return;
}
- default:
- assert(0 && "Not implemented yet!");
}
}
void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
- const char* Modifier) {
+ raw_ostream &O) {
const MachineOperand &Base = MI->getOperand(OpNum);
const MachineOperand &Disp = MI->getOperand(OpNum+1);
- if (Base.isGlobal())
- printOperand(MI, OpNum, "mem");
- else if (Disp.isImm() && !Base.getReg())
- printOperand(MI, OpNum);
- else if (Base.getReg()) {
- if (Disp.getImm()) {
- printOperand(MI, OpNum + 1, "nohash");
- O << '(';
- printOperand(MI, OpNum);
- O << ')';
- } else {
- O << '@';
- printOperand(MI, OpNum);
- }
- } else
- assert(0 && "Unsupported memory operand");
+ // Print displacement first
+
+ // Imm here is in fact global address - print extra modifier.
+ if (Disp.isImm() && !Base.getReg())
+ O << '&';
+ printOperand(MI, OpNum+1, O, "nohash");
+
+ // Print register base field
+ if (Base.getReg()) {
+ O << '(';
+ printOperand(MI, OpNum, O);
+ O << ')';
+ }
+}
+
+/// PrintAsmOperand - Print out an operand for an inline asm expression.
+///
+bool MSP430AsmPrinter::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])
+ return true; // Unknown modifier.
+
+ printOperand(MI, OpNo, O);
+ return false;
}
-void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
- unsigned CC = MI->getOperand(OpNum).getImm();
-
- switch (CC) {
- default:
- assert(0 && "Unsupported CC code");
- break;
- case MSP430::COND_E:
- O << 'e';
- break;
- case MSP430::COND_NE:
- O << "ne";
- break;
- case MSP430::COND_HS:
- O << "hs";
- break;
- case MSP430::COND_LO:
- O << "lo";
- break;
- case MSP430::COND_GE:
- O << "ge";
- break;
- case MSP430::COND_L:
- O << 'l';
- break;
+bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
+ unsigned OpNo, unsigned AsmVariant,
+ const char *ExtraCode,
+ raw_ostream &O) {
+ if (ExtraCode && ExtraCode[0]) {
+ return true; // Unknown modifier.
}
+ printSrcMemOperand(MI, OpNo, O);
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) {
+ MSP430MCInstLower MCInstLowering(OutContext, *this);
+
+ MCInst TmpInst;
+ MCInstLowering.Lower(MI, TmpInst);
+ OutStreamer.EmitInstruction(TmpInst);
+}
+
+// Force static initialization.
+extern "C" void LLVMInitializeMSP430AsmPrinter() {
+ RegisterAsmPrinter<MSP430AsmPrinter> X(TheMSP430Target);
}