llvm-6502/lib/Target/MSP430/MSP430AsmPrinter.cpp
Chris Lattner f0144127b9 Rip all of the global variable lowering logic out of TargetAsmInfo. Since
it is highly specific to the object file that will be generated in the end,
this introduces a new TargetLoweringObjectFile interface that is implemented
for each of ELF/MachO/COFF/Alpha/PIC16 and XCore.

Though still is still a brutal and ugly refactoring, this is a major step
towards goodness.

This patch also:
1. fixes a bunch of dangling pointer problems in the PIC16 backend.
2. disables the TargetLowering copy ctor which PIC16 was accidentally using.
3. gets us closer to xcore having its own crazy target section flags and
   pic16 not having to shadow sections with its own objects.
4. fixes wierdness where ELF targets would set CStringSection but not
   CStringSection_.  Factor the code better.
5. fixes some bugs in string lowering on ELF targets.




git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77294 91177308-0d34-0410-b5e6-96231b3b80d8
2009-07-28 03:13:23 +00:00

255 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, 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';
O.flush();
// 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);
}