#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
+#include "llvm/MDNode.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetAsmInfo.h"
const std::string bss_section(".bss");
- struct VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
+ class VISIBILITY_HIDDEN SPUAsmPrinter : public AsmPrinter {
std::set<std::string> FnStubs, GVStubs;
-
- SPUAsmPrinter(raw_ostream &O, TargetMachine &TM, const TargetAsmInfo *T) :
- AsmPrinter(O, TM, T)
- {
- }
+ public:
+ explicit SPUAsmPrinter(raw_ostream &O, TargetMachine &TM,
+ const TargetAsmInfo *T, bool V) :
+ AsmPrinter(O, TM, T, V) {}
virtual const char *getPassName() const {
return "STI CBEA SPU Assembly Printer";
printOp(MO);
}
}
-
+
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
printS7ImmOperand(const MachineInstr *MI, unsigned OpNo)
{
assert(value < (1 << 8) && "Invalid u7 argument");
O << value;
}
-
+
void
printShufAddr(const MachineInstr *MI, unsigned OpNo)
{
{
O << (unsigned)MI->getOperand(OpNo).getImm();
}
-
+
void
printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
// When used as the base register, r0 reads constant zero rather than
void
printDFormAddr(const MachineInstr *MI, unsigned OpNo)
{
- const MachineOperand &MO = MI->getOperand(OpNo);
- assert(MO.isImm() &&
- "printDFormAddr first operand is not immedate");
+ assert(MI->getOperand(OpNo).isImm() &&
+ "printDFormAddr first operand is not immediate");
int64_t value = int64_t(MI->getOperand(OpNo).getImm());
int16_t value16 = int16_t(value);
assert((value16 >= -(1 << (9+4)) && value16 <= (1 << (9+4)) - 1)
};
/// LinuxAsmPrinter - SPU assembly printer, customized for Linux
- struct VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
-
+ class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
DwarfWriter *DW;
- MachineModuleInfo *MMI;
-
- LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
- const TargetAsmInfo *T) :
- SPUAsmPrinter(O, TM, T),
- DW(0),
- MMI(0)
- { }
+ public:
+ explicit LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
+ const TargetAsmInfo *T, bool V)
+ : SPUAsmPrinter(O, TM, T, V), DW(0) {}
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<MachineModuleInfo>();
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:
}
}
O << Name;
-
- if (GV->hasExternalWeakLinkage())
- ExtWeakSymbols.insert(GV);
return;
}
/// PrintAsmOperand - Print out an operand for an inline asm expression.
///
bool SPUAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant,
+ unsigned AsmVariant,
const char *ExtraCode) {
// Does this asm operand have a single letter operand modifier?
if (ExtraCode && ExtraCode[0]) {
if (ExtraCode[1] != 0) return true; // Unknown modifier.
-
+
switch (ExtraCode[0]) {
default: return true; // Unknown modifier.
- case 'L': // Write second word of DImode reference.
+ case 'L': // Write second word of DImode reference.
// Verify that this operand has two consecutive registers.
if (!MI->getOperand(OpNo).isReg() ||
OpNo+1 == MI->getNumOperands() ||
break;
}
}
-
+
printOperand(MI, OpNo);
return false;
}
bool SPUAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
unsigned OpNo,
- unsigned AsmVariant,
+ unsigned AsmVariant,
const char *ExtraCode) {
if (ExtraCode && ExtraCode[0])
return true; // Unknown modifier.
bool
LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
{
+ this->MF = &MF;
+
SetupMachineFunction(MF);
O << "\n\n";
-
+
// Print out constants referenced by the function
EmitConstantPool(MF.getConstantPool());
const Function *F = MF.getFunction();
SwitchToSection(TAI->SectionForGlobal(F));
- EmitAlignment(3, F);
+ EmitAlignment(MF.getAlignment(), F);
switch (F->getLinkage()) {
default: assert(0 && "Unknown linkage type!");
+ case Function::PrivateLinkage:
case Function::InternalLinkage: // Symbols default to internal.
break;
case Function::ExternalLinkage:
O << "\t.global\t" << CurrentFnName << "\n"
<< "\t.type\t" << CurrentFnName << ", @function\n";
break;
- case Function::WeakLinkage:
- case Function::LinkOnceLinkage:
+ 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";
break;
// Print out jump tables referenced by the function.
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
-
+
// Emit post-function debug information.
DW->EndFunction(&MF);
-
+
// We didn't modify anything.
return false;
}
bool LinuxAsmPrinter::doInitialization(Module &M) {
bool Result = AsmPrinter::doInitialization(M);
+ DW = getAnalysisIfAvailable<DwarfWriter>();
SwitchToTextSection("\t.text");
- // Emit initial debug information.
- DW = getAnalysisToUpdate<DwarfWriter>();
- assert(DW && "Dwarf Writer is not available");
- MMI = getAnalysisToUpdate<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.
+/// 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)
/*!
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.
*/
printVisibility(name, GVar->getVisibility());
Constant *C = GVar->getInitializer();
+ if (isa<MDNode>(C) || isa<MDString>(C))
+ return;
const Type *Type = C->getType();
- unsigned Size = TD->getABITypeSize(Type);
+ unsigned Size = TD->getTypeAllocSize(Type);
unsigned Align = TD->getPreferredAlignmentLog(GVar);
SwitchToSection(TAI->SectionForGlobal(GVar));
if (C->isNullValue() && /* FIXME: Verify correct */
!GVar->hasSection() &&
- (GVar->hasInternalLinkage() || GVar->hasExternalLinkage() ||
- GVar->mayBeOverridden())) {
+ (GVar->hasLocalLinkage() || GVar->hasExternalLinkage() ||
+ GVar->isWeakForLinker())) {
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
if (GVar->hasExternalLinkage()) {
O << "\t.type " << name << ", @object\n";
O << name << ":\n";
O << "\t.zero " << Size << '\n';
- } else if (GVar->hasInternalLinkage()) {
+ } else if (GVar->hasLocalLinkage()) {
O << TAI->getLCOMMDirective() << name << ',' << Size;
} else {
O << ".comm " << name << ',' << Size;
switch (GVar->getLinkage()) {
// Should never be seen for the CellSPU platform...
- case GlobalValue::LinkOnceLinkage:
- case GlobalValue::WeakLinkage:
+ 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"
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();
+ llvm_report_error("Unknown linkage type!");
}
EmitAlignment(Align, GVar);
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';
}
I != E; ++I)
printModuleLevelGV(I);
- // TODO
-
- // Emit initial debug information.
- DW->EndModule();
-
return AsmPrinter::doFinalization(M);
}
/// that the Linux SPU assembler can deal with.
///
FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
- SPUTargetMachine &tm) {
- return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo());
+ SPUTargetMachine &tm,
+ bool verbose) {
+ return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
}
+// Force static initialization.
+extern "C" void LLVMInitializeCellSPUAsmPrinter() { }
+
+namespace {
+ static struct Register {
+ Register() {
+ SPUTargetMachine::registerAsmPrinter(createSPUAsmPrinterPass);
+ }
+ } Registrator;
+}