mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-15 06:18:50 +00:00
bc65a8d518
are part of the core IR library in order to support dumping and other basic functionality. Rename the 'Assembly' include directory to 'AsmParser' to match the library name and the only functionality left their -- printing has been in the core IR library for quite some time. Update all of the #includes to match. All of this started because I wanted to have the layering in good shape before I started adding support for printing LLVM IR using the new pass infrastructure, and commandline support for the new pass infrastructure. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198688 91177308-0d34-0410-b5e6-96231b3b80d8
162 lines
5.3 KiB
C++
162 lines
5.3 KiB
C++
//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ----------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains a printer that converts from our internal representation
|
|
// of machine-dependent LLVM code to the MSP430 assembly language.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "asm-printer"
|
|
#include "MSP430.h"
|
|
#include "InstPrinter/MSP430InstPrinter.h"
|
|
#include "MSP430InstrInfo.h"
|
|
#include "MSP430MCInstLower.h"
|
|
#include "MSP430TargetMachine.h"
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/IR/Constants.h"
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/Writer.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;
|
|
|
|
namespace {
|
|
class MSP430AsmPrinter : public AsmPrinter {
|
|
public:
|
|
MSP430AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
|
|
: AsmPrinter(TM, Streamer) {}
|
|
|
|
virtual const char *getPassName() const {
|
|
return "MSP430 Assembly Printer";
|
|
}
|
|
|
|
void printOperand(const MachineInstr *MI, int OpNum,
|
|
raw_ostream &O, const char* Modifier = 0);
|
|
void printSrcMemOperand(const MachineInstr *MI, int OpNum,
|
|
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
|
|
|
|
|
|
void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
|
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:
|
|
O << MSP430InstPrinter::getRegisterName(MO.getReg());
|
|
return;
|
|
case MachineOperand::MO_Immediate:
|
|
if (!Modifier || strcmp(Modifier, "nohash"))
|
|
O << '#';
|
|
O << MO.getImm();
|
|
return;
|
|
case MachineOperand::MO_MachineBasicBlock:
|
|
O << *MO.getMBB()->getSymbol();
|
|
return;
|
|
case MachineOperand::MO_GlobalAddress: {
|
|
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
|
|
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 << '+';
|
|
|
|
O << *getSymbol(MO.getGlobal());
|
|
|
|
if (Offset)
|
|
O << ')';
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
|
|
raw_ostream &O) {
|
|
const MachineOperand &Base = MI->getOperand(OpNum);
|
|
const MachineOperand &Disp = MI->getOperand(OpNum+1);
|
|
|
|
// 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;
|
|
}
|
|
|
|
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);
|
|
}
|