diff options
Diffstat (limited to 'lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp')
-rw-r--r-- | lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp new file mode 100644 index 0000000000..60744ddfff --- /dev/null +++ b/lib/Target/Blackfin/AsmPrinter/BlackfinAsmPrinter.cpp @@ -0,0 +1,237 @@ +//===-- 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/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/Mangler.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/FormattedStream.h" + +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +namespace { + class VISIBILITY_HIDDEN BlackfinAsmPrinter : public AsmPrinter { + public: + BlackfinAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const TargetAsmInfo *TAI, bool V) + : AsmPrinter(O, TM, TAI, V) {} + + virtual const char *getPassName() const { + return "Blackfin Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int opNum); + void printMemoryOperand(const MachineInstr *MI, int opNum); + bool printInstruction(const MachineInstr *MI); // autogenerated. + void emitLinkage(const std::string &n, 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 std::string &name, + 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 << TAI->getGlobalDirective() << name << "\n"; + break; + case GlobalValue::LinkOnceAnyLinkage: + case GlobalValue::LinkOnceODRLinkage: + case GlobalValue::WeakAnyLinkage: + case GlobalValue::WeakODRLinkage: + O << TAI->getGlobalDirective() << name << "\n"; + O << TAI->getWeakDefDirective() << name << "\n"; + break; + } +} + +void BlackfinAsmPrinter::PrintGlobalVariable(const GlobalVariable* GV) { + const TargetData *TD = TM.getTargetData(); + + if (!GV->hasInitializer() || EmitSpecialLLVMGlobal(GV)) + return; + + std::string name = Mang->getMangledName(GV); + Constant *C = GV->getInitializer(); + + SwitchToSection(getObjFileLowering().SectionForGlobal(GV, Mang, TM)); + emitLinkage(name, GV->getLinkage()); + EmitAlignment(TD->getPreferredAlignmentLog(GV), GV); + printVisibility(name, GV->getVisibility()); + + O << "\t.type " << name << ", STT_OBJECT\n"; + O << "\t.size " << name << ',' << TD->getTypeAllocSize(C->getType()) << '\n'; + O << name << ":\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(); + SwitchToSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + EmitAlignment(2, F); + emitLinkage(CurrentFnName, F->getLinkage()); + printVisibility(CurrentFnName, F->getVisibility()); + + O << "\t.type\t" << CurrentFnName << ", STT_FUNC\n" + << CurrentFnName << ":\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. + 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. + printInstruction(II); + ++EmittedInsts; + } + } + + O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n"; + + if (DW) + DW->EndFunction(&MF); + + return false; +} + +void BlackfinAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { + const MachineOperand &MO = MI->getOperand (opNum); + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + switch (MO.getType()) { + case MachineOperand::MO_Register: + assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && + "Virtual registers should be already mapped!"); + O << RI.get(MO.getReg()).AsmName; + break; + + case MachineOperand::MO_Immediate: + O << MO.getImm(); + break; + case MachineOperand::MO_MachineBasicBlock: + printBasicBlockLabel(MO.getMBB(), false, false, false); + return; + case MachineOperand::MO_GlobalAddress: + O << Mang->getMangledName(MO.getGlobal()); + printOffset(MO.getOffset()); + break; + case MachineOperand::MO_ExternalSymbol: + O << Mang->makeNameProper(MO.getSymbolName()); + break; + case MachineOperand::MO_ConstantPoolIndex: + O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" + << MO.getIndex(); + break; + case MachineOperand::MO_JumpTableIndex: + O << TAI->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; +} |