Files
llvm-6502/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp
Chris Lattner d1947ed2f8 supplement CurrentFnName with CurrentFnSym, which will eventually
replace it.  Upgrade Alpha, Blackfin, and part of CellSPU to not
use mangler anymore.  CellSPU needs more invasive surgery.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93589 91177308-0d34-0410-b5e6-96231b3b80d8
2010-01-15 23:55:16 +00:00

263 lines
8.0 KiB
C++

//===-- BlackfinAsmPrinter.cpp - Blackfin 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 GAS-format BLACKFIN assembly language.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "Blackfin.h"
#include "BlackfinInstrInfo.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/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
namespace {
class BlackfinAsmPrinter : public AsmPrinter {
public:
BlackfinAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
const MCAsmInfo *MAI, bool V)
: AsmPrinter(O, TM, MAI, V) {}
virtual const char *getPassName() const {
return "Blackfin Assembly Printer";
}
void printOperand(const MachineInstr *MI, int opNum);
void printMemoryOperand(const MachineInstr *MI, int opNum);
void printInstruction(const MachineInstr *MI); // autogenerated.
static const char *getRegisterName(unsigned RegNo);
void emitLinkage(const MCSymbol *GVSym, GlobalValue::LinkageTypes l);
bool runOnMachineFunction(MachineFunction &F);
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode);
void PrintGlobalVariable(const GlobalVariable* GVar);
};
} // end of anonymous namespace
#include "BlackfinGenAsmWriter.inc"
extern "C" void LLVMInitializeBlackfinAsmPrinter() {
RegisterAsmPrinter<BlackfinAsmPrinter> X(TheBlackfinTarget);
}
void BlackfinAsmPrinter::emitLinkage(const MCSymbol *GVSym,
GlobalValue::LinkageTypes L) {
switch (L) {
default: llvm_unreachable("Unknown linkage type!");
case GlobalValue::InternalLinkage: // Symbols default to internal.
case GlobalValue::PrivateLinkage:
case GlobalValue::LinkerPrivateLinkage:
break;
case GlobalValue::ExternalLinkage:
O << MAI->getGlobalDirective();
GVSym->print(O, MAI);
O << "\n";
break;
case GlobalValue::LinkOnceAnyLinkage:
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
O << MAI->getGlobalDirective();
GVSym->print(O, MAI);
O << "\n";
O << MAI->getWeakDefDirective();
GVSym->print(O, MAI);
O << "\n";
break;
}
}
void BlackfinAsmPrinter::PrintGlobalVariable(const GlobalVariable* GV) {
const TargetData *TD = TM.getTargetData();
if (!GV->hasInitializer() || EmitSpecialLLVMGlobal(GV))
return;
MCSymbol *GVSym = GetGlobalValueSymbol(GV);
Constant *C = GV->getInitializer();
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,
TM));
emitLinkage(GVSym, GV->getLinkage());
EmitAlignment(TD->getPreferredAlignmentLog(GV), GV);
printVisibility(GVSym, GV->getVisibility());
O << "\t.type ";
GVSym->print(O, MAI);
O << ", STT_OBJECT\n";
O << "\t.size ";
GVSym->print(O, MAI);
O << "\n";
O << ',' << TD->getTypeAllocSize(C->getType()) << '\n';
GVSym->print(O, MAI);
O << ":\n";
EmitGlobalConstant(C);
}
/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
bool BlackfinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
SetupMachineFunction(MF);
EmitConstantPool(MF.getConstantPool());
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
const Function *F = MF.getFunction();
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
EmitAlignment(2, F);
emitLinkage(CurrentFnSym, F->getLinkage());
printVisibility(CurrentFnSym, F->getVisibility());
O << "\t.type\t";
CurrentFnSym->print(O, MAI);
O << ", STT_FUNC\n";
CurrentFnSym->print(O, MAI);
O << ":\n";
if (DW)
DW->BeginFunction(&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.
EmitBasicBlockStart(I);
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
processDebugLoc(II, true);
printInstruction(II);
if (VerboseAsm)
EmitComments(*II);
O << '\n';
processDebugLoc(II, false);
++EmittedInsts;
}
}
O << "\t.size ";
CurrentFnSym->print(O, MAI);
O << ", .-";
CurrentFnSym->print(O, MAI);
O << "\n";
if (DW)
DW->EndFunction(&MF);
return false;
}
void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
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 << getRegisterName(MO.getReg());
break;
case MachineOperand::MO_Immediate:
O << MO.getImm();
break;
case MachineOperand::MO_MachineBasicBlock:
GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI);
return;
case MachineOperand::MO_GlobalAddress:
GetGlobalValueSymbol(MO.getGlobal())->print(O, MAI);
printOffset(MO.getOffset());
break;
case MachineOperand::MO_ExternalSymbol:
GetExternalSymbolSymbol(MO.getSymbolName())->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();
break;
default:
llvm_unreachable("<unknown operand type>");
break;
}
}
void BlackfinAsmPrinter::printMemoryOperand(const MachineInstr *MI, int opNum) {
printOperand(MI, opNum);
if (MI->getOperand(opNum+1).isImm() && MI->getOperand(opNum+1).getImm() == 0)
return;
O << " + ";
printOperand(MI, opNum+1);
}
/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool BlackfinAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
unsigned OpNo,
unsigned AsmVariant,
const char *ExtraCode) {
if (ExtraCode && ExtraCode[0]) {
if (ExtraCode[1] != 0) return true; // Unknown modifier.
switch (ExtraCode[0]) {
default: return true; // Unknown modifier.
case 'r':
break;
}
}
printOperand(MI, OpNo);
return false;
}
bool BlackfinAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
unsigned OpNo,
unsigned AsmVariant,
const char *ExtraCode) {
if (ExtraCode && ExtraCode[0])
return true; // Unknown modifier
O << '[';
printOperand(MI, OpNo);
O << ']';
return false;
}