mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-20 09:30:43 +00:00
1c55fab534
calls were originally put in place because errs() at one time was not unbuffered, and these print routines are commonly used with errs() for debugging. However, errs() is now properly unbuffered, so the flush calls are no longer needed. This significantly reduces the number of write(2) calls for regular asm printing when there are many small functions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78137 91177308-0d34-0410-b5e6-96231b3b80d8
253 lines
7.4 KiB
C++
253 lines
7.4 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 "MSP430InstrInfo.h"
|
|
#include "MSP430TargetMachine.h"
|
|
#include "llvm/Constants.h"
|
|
#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/Target/TargetData.h"
|
|
#include "llvm/Target/TargetLoweringObjectFile.h"
|
|
#include "llvm/Target/TargetRegistry.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
#include "llvm/Support/FormattedStream.h"
|
|
#include "llvm/Support/Mangler.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
using namespace llvm;
|
|
|
|
STATISTIC(EmittedInsts, "Number of machine instrs printed");
|
|
|
|
namespace {
|
|
class VISIBILITY_HIDDEN MSP430AsmPrinter : public AsmPrinter {
|
|
public:
|
|
MSP430AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
|
|
const TargetAsmInfo *TAI, bool V)
|
|
: AsmPrinter(O, TM, TAI, V) {}
|
|
|
|
virtual const char *getPassName() const {
|
|
return "MSP430 Assembly Printer";
|
|
}
|
|
|
|
void printOperand(const MachineInstr *MI, int OpNum,
|
|
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);
|
|
|
|
void emitFunctionHeader(const MachineFunction &MF);
|
|
bool runOnMachineFunction(MachineFunction &F);
|
|
|
|
virtual void PrintGlobalVariable(const GlobalVariable *GV) {
|
|
// FIXME: No support for global variables?
|
|
}
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AsmPrinter::getAnalysisUsage(AU);
|
|
AU.setPreservesAll();
|
|
}
|
|
};
|
|
} // end of anonymous namespace
|
|
|
|
#include "MSP430GenAsmWriter.inc"
|
|
|
|
|
|
void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
|
|
const Function *F = MF.getFunction();
|
|
|
|
SwitchToSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
|
|
|
|
unsigned FnAlign = MF.getAlignment();
|
|
EmitAlignment(FnAlign, F);
|
|
|
|
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:
|
|
O << "\t.globl\t" << CurrentFnName << '\n';
|
|
break;
|
|
case Function::LinkOnceAnyLinkage:
|
|
case Function::LinkOnceODRLinkage:
|
|
case Function::WeakAnyLinkage:
|
|
case Function::WeakODRLinkage:
|
|
O << "\t.weak\t" << CurrentFnName << '\n';
|
|
break;
|
|
}
|
|
|
|
printVisibility(CurrentFnName, F->getVisibility());
|
|
|
|
O << "\t.type\t" << CurrentFnName << ",@function\n"
|
|
<< CurrentFnName << ":\n";
|
|
}
|
|
|
|
bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
|
SetupMachineFunction(MF);
|
|
O << "\n\n";
|
|
|
|
// Print the 'header' of function
|
|
emitFunctionHeader(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 (!VerboseAsm && (I->pred_empty() || I->isOnlyReachableByFallthrough())) {
|
|
// This is an entry block or a block that's only reachable via a
|
|
// fallthrough edge. In non-VerboseAsm mode, don't print the label.
|
|
} else {
|
|
printBasicBlockLabel(I, true, true, VerboseAsm);
|
|
O << '\n';
|
|
}
|
|
|
|
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
|
|
II != E; ++II)
|
|
// Print the assembly for the instruction.
|
|
printMachineInstruction(II);
|
|
}
|
|
|
|
if (TAI->hasDotTypeDotSizeDirective())
|
|
O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\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;
|
|
|
|
llvm_unreachable("Should not happen");
|
|
}
|
|
|
|
void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
|
const char* Modifier) {
|
|
const MachineOperand &MO = MI->getOperand(OpNum);
|
|
switch (MO.getType()) {
|
|
case MachineOperand::MO_Register:
|
|
assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
|
|
"Virtual registers should be already mapped!");
|
|
O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
|
|
return;
|
|
case MachineOperand::MO_Immediate:
|
|
if (!Modifier || strcmp(Modifier, "nohash"))
|
|
O << '#';
|
|
O << MO.getImm();
|
|
return;
|
|
case MachineOperand::MO_MachineBasicBlock:
|
|
printBasicBlockLabel(MO.getMBB());
|
|
return;
|
|
case MachineOperand::MO_GlobalAddress: {
|
|
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
|
|
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
|
std::string Name = Mang->getMangledName(MO.getGlobal());
|
|
assert(MO.getOffset() == 0 && "No offsets allowed!");
|
|
|
|
if (isCallOp)
|
|
O << '#';
|
|
else if (isMemOp)
|
|
O << '&';
|
|
|
|
O << Name;
|
|
|
|
return;
|
|
}
|
|
case MachineOperand::MO_ExternalSymbol: {
|
|
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
|
std::string Name(TAI->getGlobalPrefix());
|
|
Name += MO.getSymbolName();
|
|
if (isCallOp)
|
|
O << '#';
|
|
O << Name;
|
|
return;
|
|
}
|
|
default:
|
|
llvm_unreachable("Not implemented yet!");
|
|
}
|
|
}
|
|
|
|
void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
|
|
const char* Modifier) {
|
|
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
|
|
llvm_unreachable("Unsupported memory operand");
|
|
}
|
|
|
|
void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
|
|
unsigned CC = MI->getOperand(OpNum).getImm();
|
|
|
|
switch (CC) {
|
|
default:
|
|
llvm_unreachable("Unsupported CC code");
|
|
break;
|
|
case MSP430::COND_E:
|
|
O << "eq";
|
|
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;
|
|
}
|
|
}
|
|
|
|
extern "C" void LLVMInitializeMSP430Target() {
|
|
// Register the target.
|
|
RegisterTargetMachine<MSP430TargetMachine> X(TheMSP430Target);
|
|
RegisterAsmPrinter<MSP430AsmPrinter> Y(TheMSP430Target);
|
|
}
|