#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetOptions.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetRegistry.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
-#include <set>
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/MathExtras.h"
using namespace llvm;
namespace {
const std::string bss_section(".bss");
- class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
- std::set<std::string> FnStubs, GVStubs;
+ class SPUAsmPrinter : public AsmPrinter {
public:
- explicit SPUAsmPrinter(raw_ostream &O, TargetMachine &TM,
- const TargetAsmInfo *T, unsigned OL, bool V) :
- AsmPrinter(O, TM, T, OL, V) {}
+ explicit SPUAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
+ const MCAsmInfo *T, bool V) :
+ AsmPrinter(O, TM, T, V) {}
virtual const char *getPassName() const {
return "STI CBEA SPU Assembly Printer";
}
/// printInstruction - This method is automatically generated by tablegen
- /// from the instruction set description. This method returns true if the
- /// machine instruction was sufficiently described to print it, otherwise it
- /// returns false.
- bool printInstruction(const MachineInstr *MI);
+ /// from the instruction set description.
+ void printInstruction(const MachineInstr *MI);
+ static const char *getRegisterName(unsigned RegNo);
+
void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO);
unsigned RegNo = MO.getReg();
assert(TargetRegisterInfo::isPhysicalRegister(RegNo) &&
"Not physreg??");
- O << TM.getRegisterInfo()->get(RegNo).AsmName;
+ O << getRegisterName(RegNo);
}
void printOperand(const MachineInstr *MI, unsigned OpNo) {
const MachineOperand &MO = MI->getOperand(OpNo);
if (MO.isReg()) {
- assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
- O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
+ O << getRegisterName(MO.getReg());
} else if (MO.isImm()) {
O << MO.getImm();
} else {
// the value contained in the register. For this reason, the darwin
// assembler requires that we print r0 as 0 (no r) when used as the base.
const MachineOperand &MO = MI->getOperand(OpNo);
- O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
- O << ", ";
+ O << getRegisterName(MO.getReg()) << ", ";
printOperand(MI, OpNo+1);
}
&& "Invalid negated immediate rotate 7-bit argument");
O << -value;
} else {
- assert(0 &&"Invalid/non-immediate rotate amount in printRotateNeg7Imm");
+ llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
}
}
&& "Invalid negated immediate rotate 7-bit argument");
O << -value;
} else {
- assert(0 &&"Invalid/non-immediate rotate amount in printRotateNeg7Imm");
+ llvm_unreachable("Invalid/non-immediate rotate amount in printRotateNeg7Imm");
}
}
virtual bool runOnMachineFunction(MachineFunction &F) = 0;
- //! Assembly printer cleanup after function has been emitted
- virtual bool doFinalization(Module &M) = 0;
};
/// LinuxAsmPrinter - SPU assembly printer, customized for Linux
- class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
- DwarfWriter *DW;
- MachineModuleInfo *MMI;
+ class LinuxAsmPrinter : public SPUAsmPrinter {
public:
- LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
- const TargetAsmInfo *T, bool F, bool V)
- : SPUAsmPrinter(O, TM, T, F, V), DW(0), MMI(0) {}
+ explicit LinuxAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
+ const MCAsmInfo *T, bool V)
+ : SPUAsmPrinter(O, TM, T, V) {}
virtual const char *getPassName() const {
return "STI CBEA SPU Assembly Printer";
}
bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- //! Dump globals, perform cleanup after function emission
- bool doFinalization(Module &M);
void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<DwarfWriter>();
SPUAsmPrinter::getAnalysisUsage(AU);
}
-
- //! Emit a global variable according to its section and type
- void printModuleLevelGV(const GlobalVariable* GVar);
};
} // end of anonymous namespace
void SPUAsmPrinter::printOp(const MachineOperand &MO) {
switch (MO.getType()) {
case MachineOperand::MO_Immediate:
- cerr << "printOp() does not handle immediate values\n";
- abort();
+ llvm_report_error("printOp() does not handle immediate values");
return;
case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
+ O << *MO.getMBB()->getSymbol(OutContext);
return;
case MachineOperand::MO_JumpTableIndex:
- O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
+ O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << MO.getIndex();
return;
case MachineOperand::MO_ConstantPoolIndex:
- O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
+ O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
<< '_' << MO.getIndex();
return;
case MachineOperand::MO_ExternalSymbol:
// Computing the address of an external symbol, not calling it.
if (TM.getRelocationModel() != Reloc::Static) {
- std::string Name(TAI->getGlobalPrefix()); Name += MO.getSymbolName();
- GVStubs.insert(Name);
- O << "L" << Name << "$non_lazy_ptr";
+ O << "L" << MAI->getGlobalPrefix() << MO.getSymbolName()
+ << "$non_lazy_ptr";
return;
}
- O << TAI->getGlobalPrefix() << MO.getSymbolName();
+ O << *GetExternalSymbolSymbol(MO.getSymbolName());
return;
- case MachineOperand::MO_GlobalAddress: {
- // Computing the address of a global symbol, not calling it.
- GlobalValue *GV = MO.getGlobal();
- std::string Name = Mang->getValueName(GV);
-
+ case MachineOperand::MO_GlobalAddress:
// External or weakly linked global variables need non-lazily-resolved
// stubs
if (TM.getRelocationModel() != Reloc::Static) {
+ GlobalValue *GV = MO.getGlobal();
if (((GV->isDeclaration() || GV->hasWeakLinkage() ||
GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()))) {
- GVStubs.insert(Name);
- O << "L" << Name << "$non_lazy_ptr";
+ O << *GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
return;
}
}
- O << Name;
-
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
+ O << *GetGlobalValueSymbol(MO.getGlobal());
return;
- }
-
default:
O << "<unknown operand type: " << MO.getType() << ">";
return;
///
void SPUAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
+ processDebugLoc(MI, true);
printInstruction(MI);
+ if (VerboseAsm)
+ EmitComments(*MI);
+ processDebugLoc(MI, false);
+ O << '\n';
}
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
-bool
-LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
-{
- this->MF = &MF;
-
+bool LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
SetupMachineFunction(MF);
O << "\n\n";
// Print out labels for the function.
const Function *F = MF.getFunction();
- SwitchToSection(TAI->SectionForGlobal(F));
- EmitAlignment(3, F);
+ OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
+ EmitAlignment(MF.getAlignment(), F);
switch (F->getLinkage()) {
- default: assert(0 && "Unknown linkage type!");
+ default: llvm_unreachable("Unknown linkage type!");
case Function::PrivateLinkage:
+ case Function::LinkerPrivateLinkage:
case Function::InternalLinkage: // Symbols default to internal.
break;
case Function::ExternalLinkage:
- O << "\t.global\t" << CurrentFnName << "\n"
- << "\t.type\t" << CurrentFnName << ", @function\n";
+ O << "\t.global\t" << *CurrentFnSym << "\n" << "\t.type\t";
+ O << *CurrentFnSym << ", @function\n";
break;
case Function::WeakAnyLinkage:
case Function::WeakODRLinkage:
case Function::LinkOnceAnyLinkage:
case Function::LinkOnceODRLinkage:
- O << "\t.global\t" << CurrentFnName << "\n";
- O << "\t.weak_definition\t" << CurrentFnName << "\n";
+ O << "\t.global\t" << *CurrentFnSym << "\n";
+ O << "\t.weak_definition\t" << *CurrentFnSym << "\n";
break;
}
- O << CurrentFnName << ":\n";
+
+ O << *CurrentFnSym << ":\n";
// Emit pre-function debug information.
DW->BeginFunction(&MF);
I != E; ++I) {
// Print a label for the basic block.
if (I != MF.begin()) {
- printBasicBlockLabel(I, true, true);
- O << '\n';
+ EmitBasicBlockStart(I);
}
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
}
}
- O << "\t.size\t" << CurrentFnName << ",.-" << CurrentFnName << "\n";
+ O << "\t.size\t" << *CurrentFnSym << ",.-" << *CurrentFnSym << "\n";
// Print out jump tables referenced by the function.
- EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
+ EmitJumpTableInfo(MF);
// Emit post-function debug information.
DW->EndFunction(&MF);
return false;
}
-
-bool LinuxAsmPrinter::doInitialization(Module &M) {
- bool Result = AsmPrinter::doInitialization(M);
- SwitchToTextSection("\t.text");
- // Emit initial debug information.
- DW = getAnalysisIfAvailable<DwarfWriter>();
- assert(DW && "Dwarf Writer is not available");
- MMI = getAnalysisIfAvailable<MachineModuleInfo>();
- DW->BeginModule(&M, MMI, O, this, TAI);
- return Result;
-}
-
-/// PrintUnmangledNameSafely - Print out the printable characters in the name.
-/// Don't print things like \\n or \\0.
-static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
- for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
- Name != E; ++Name)
- if (isprint(*Name))
- OS << *Name;
-}
-
-/*!
- Emit a global variable according to its section, alignment, etc.
-
- \note This code was shamelessly copied from the PowerPC's assembly printer,
- which sort of screams for some kind of refactorization of common code.
- */
-void LinuxAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer())
- return;
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar))
- return;
-
- std::string name = Mang->getValueName(GVar);
-
- printVisibility(name, GVar->getVisibility());
-
- Constant *C = GVar->getInitializer();
- const Type *Type = C->getType();
- unsigned Size = TD->getTypePaddedSize(Type);
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
-
- SwitchToSection(TAI->SectionForGlobal(GVar));
-
- if (C->isNullValue() && /* FIXME: Verify correct */
- !GVar->hasSection() &&
- (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
- GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasExternalLinkage()) {
- O << "\t.global " << name << '\n';
- O << "\t.type " << name << ", @object\n";
- O << name << ":\n";
- O << "\t.zero " << Size << '\n';
- } else if (GVar->hasLocalLinkage()) {
- O << TAI->getLCOMMDirective() << name << ',' << Size;
- } else {
- O << ".comm " << name << ',' << Size;
- }
- O << "\t\t" << TAI->getCommentString() << " '";
- PrintUnmangledNameSafely(GVar, O);
- O << "'\n";
- return;
- }
-
- switch (GVar->getLinkage()) {
- // Should never be seen for the CellSPU platform...
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::CommonLinkage:
- O << "\t.global " << name << '\n'
- << "\t.type " << name << ", @object\n"
- << "\t.weak " << name << '\n';
- break;
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << "\t.global " << name << '\n'
- << "\t.type " << name << ", @object\n";
- // FALL THROUGH
- case GlobalValue::PrivateLinkage:
- case GlobalValue::InternalLinkage:
- break;
- default:
- cerr << "Unknown linkage type!";
- abort();
- }
-
- EmitAlignment(Align, GVar);
- O << name << ":\t\t\t\t" << TAI->getCommentString() << " '";
- PrintUnmangledNameSafely(GVar, O);
- O << "'\n";
-
- // If the initializer is a extern weak symbol, remember to emit the weak
- // reference!
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
-
- EmitGlobalConstant(C);
- O << '\n';
-}
-
-bool LinuxAsmPrinter::doFinalization(Module &M) {
- // Print out module-level global variables here.
- for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I)
- printModuleLevelGV(I);
-
- // Emit initial debug information.
- DW->EndModule();
-
- return AsmPrinter::doFinalization(M);
-}
-
-/// createSPUCodePrinterPass - Returns a pass that prints the Cell SPU
-/// assembly code for a MachineFunction to the given output stream, in a format
-/// that the Linux SPU assembler can deal with.
-///
-FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
- SPUTargetMachine &tm,
- unsigned OptLevel, bool verbose) {
- return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
+// Force static initialization.
+extern "C" void LLVMInitializeCellSPUAsmPrinter() {
+ RegisterAsmPrinter<LinuxAsmPrinter> X(TheCellSPUTarget);
}