Add initial support for using the generated asm writer. Also, fix FP constant printing to always print 8 byte intializers. Move printing of LinkOnce stubs.

llvm-svn: 15741
This commit is contained in:
Nate Begeman 2004-08-14 22:09:10 +00:00
parent 8536df7dbe
commit 0ad7f813d8
1 changed files with 73 additions and 61 deletions

View File

@ -19,7 +19,7 @@
#define DEBUG_TYPE "asmprinter" #define DEBUG_TYPE "asmprinter"
#include "PowerPC.h" #include "PowerPC.h"
#include "PowerPCInstrInfo.h" #include "PowerPCInstrInfo.h"
#include "PPC32TargetMachine.h" #include "PowerPCTargetMachine.h"
#include "llvm/Constants.h" #include "llvm/Constants.h"
#include "llvm/DerivedTypes.h" #include "llvm/DerivedTypes.h"
#include "llvm/Module.h" #include "llvm/Module.h"
@ -40,7 +40,7 @@ namespace llvm {
namespace { namespace {
Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
struct Printer : public MachineFunctionPass { struct PowerPCAsmPrinter : public MachineFunctionPass {
/// Output stream on which we're printing assembly code. /// Output stream on which we're printing assembly code.
/// ///
std::ostream &O; std::ostream &O;
@ -48,7 +48,7 @@ namespace {
/// Target machine description which we query for reg. names, data /// Target machine description which we query for reg. names, data
/// layout, etc. /// layout, etc.
/// ///
PPC32TargetMachine &TM; PowerPCTargetMachine &TM;
/// Name-mangler for global names. /// Name-mangler for global names.
/// ///
@ -56,8 +56,8 @@ namespace {
std::set<std::string> FnStubs, GVStubs, LinkOnceStubs; std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
std::set<std::string> Strings; std::set<std::string> Strings;
Printer(std::ostream &o, TargetMachine &tm) : O(o), PowerPCAsmPrinter(std::ostream &o, TargetMachine &tm) : O(o),
TM(reinterpret_cast<PPC32TargetMachine&>(tm)), LabelNumber(0) {} TM(reinterpret_cast<PowerPCTargetMachine&>(tm)), LabelNumber(0) {}
/// Cache of mangled name for current function. This is /// Cache of mangled name for current function. This is
/// recalculated at the beginning of each call to /// recalculated at the beginning of each call to
@ -70,9 +70,15 @@ namespace {
unsigned LabelNumber; unsigned LabelNumber;
virtual const char *getPassName() const { virtual const char *getPassName() const {
return "PPC32 Assembly Printer"; return "PowerPC 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);
void printMachineInstruction(const MachineInstr *MI); void printMachineInstruction(const MachineInstr *MI);
void printOp(const MachineOperand &MO, bool LoadAddrOp = false); void printOp(const MachineOperand &MO, bool LoadAddrOp = false);
void printImmOp(const MachineOperand &MO, unsigned ArgType); void printImmOp(const MachineOperand &MO, unsigned ArgType);
@ -90,10 +96,13 @@ namespace {
/// using the given target machine description. This should work /// using the given target machine description. This should work
/// regardless of whether the function is in SSA form or not. /// regardless of whether the function is in SSA form or not.
/// ///
FunctionPass *createPPC32AsmPrinter(std::ostream &o,TargetMachine &tm) { FunctionPass *createPPCAsmPrinter(std::ostream &o,TargetMachine &tm) {
return new Printer(o, tm); return new PowerPCAsmPrinter(o, tm);
} }
// Include the auto-generated portion of the assembly writer
#include "PowerPCGenAsmWriter.inc"
/// isStringCompatible - Can we treat the specified array as a string? /// isStringCompatible - Can we treat the specified array as a string?
/// Only if it is an array of ubytes or non-negative sbytes. /// Only if it is an array of ubytes or non-negative sbytes.
/// ///
@ -152,7 +161,7 @@ static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
// Print out the specified constant, without a storage class. Only the // Print out the specified constant, without a storage class. Only the
// constants valid in constant expressions can occur here. // constants valid in constant expressions can occur here.
void Printer::emitConstantValueOnly(const Constant *CV) { void PowerPCAsmPrinter::emitConstantValueOnly(const Constant *CV) {
if (CV->isNullValue()) if (CV->isNullValue())
O << "0"; O << "0";
else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) { else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
@ -222,7 +231,7 @@ void Printer::emitConstantValueOnly(const Constant *CV) {
// Print a constant value or values, with the appropriate storage class as a // Print a constant value or values, with the appropriate storage class as a
// prefix. // prefix.
void Printer::emitGlobalConstant(const Constant *CV) { void PowerPCAsmPrinter::emitGlobalConstant(const Constant *CV) {
const TargetData &TD = TM.getTargetData(); const TargetData &TD = TM.getTargetData();
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) { if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
@ -263,35 +272,21 @@ void Printer::emitGlobalConstant(const Constant *CV) {
// FP Constants are printed as integer constants to avoid losing // FP Constants are printed as integer constants to avoid losing
// precision... // precision...
double Val = CFP->getValue(); double Val = CFP->getValue();
switch (CFP->getType()->getTypeID()) { union DU { // Abide by C TBAA rules
default: assert(0 && "Unknown floating point type!"); double FVal;
case Type::FloatTyID: { uint64_t UVal;
union FU { // Abide by C TBAA rules struct {
float FVal; uint32_t MSWord;
unsigned UVal; uint32_t LSWord;
} U; } T;
U.FVal = Val; } U;
O << ".long\t" << U.UVal << "\t; float " << Val << "\n"; U.FVal = Val;
return;
} O << ".long\t" << U.T.MSWord << "\t; double most significant word "
case Type::DoubleTyID: { << Val << "\n";
union DU { // Abide by C TBAA rules O << ".long\t" << U.T.LSWord << "\t; double least significant word "
double FVal; << Val << "\n";
uint64_t UVal; return;
struct {
uint32_t MSWord;
uint32_t LSWord;
} T;
} U;
U.FVal = Val;
O << ".long\t" << U.T.MSWord << "\t; double most significant word "
<< Val << "\n";
O << ".long\t" << U.T.LSWord << "\t; double least significant word "
<< Val << "\n";
return;
}
}
} else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) { } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
union DU { // Abide by C TBAA rules union DU { // Abide by C TBAA rules
@ -348,7 +343,7 @@ void Printer::emitGlobalConstant(const Constant *CV) {
/// used to print out constants which have been "spilled to memory" by /// used to print out constants which have been "spilled to memory" by
/// the code generator. /// the code generator.
/// ///
void Printer::printConstantPool(MachineConstantPool *MCP) { void PowerPCAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
const std::vector<Constant*> &CP = MCP->getConstants(); const std::vector<Constant*> &CP = MCP->getConstants();
const TargetData &TD = TM.getTargetData(); const TargetData &TD = TM.getTargetData();
@ -367,7 +362,7 @@ void Printer::printConstantPool(MachineConstantPool *MCP) {
/// runOnMachineFunction - This uses the printMachineInstruction() /// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction. /// method to print assembly for each instruction.
/// ///
bool Printer::runOnMachineFunction(MachineFunction &MF) { bool PowerPCAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
O << "\n\n"; O << "\n\n";
// What's my mangled name? // What's my mangled name?
CurrentFnName = Mang->getValueName(MF.getFunction()); CurrentFnName = Mang->getValueName(MF.getFunction());
@ -400,7 +395,7 @@ bool Printer::runOnMachineFunction(MachineFunction &MF) {
return false; return false;
} }
void Printer::printOp(const MachineOperand &MO, void PowerPCAsmPrinter::printOp(const MachineOperand &MO,
bool LoadAddrOp /* = false */) { bool LoadAddrOp /* = false */) {
const MRegisterInfo &RI = *TM.getRegisterInfo(); const MRegisterInfo &RI = *TM.getRegisterInfo();
int new_symbol; int new_symbol;
@ -458,14 +453,19 @@ void Printer::printOp(const MachineOperand &MO,
O << "L" << Name << "$stub"; O << "L" << Name << "$stub";
return; return;
} }
// External global variables need a non-lazily-resolved stub // External global variables need a non-lazily-resolved stub
if (!GV->hasInternalLinkage() && if (GV->isExternal() && TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
GVStubs.insert(Name); GVStubs.insert(Name);
O << "L" << Name << "$non_lazy_ptr"; O << "L" << Name << "$non_lazy_ptr";
return; return;
} }
if (F && LoadAddrOp && TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
LinkOnceStubs.insert(Name);
O << "L" << Name << "$non_lazy_ptr";
return;
}
O << Mang->getValueName(GV); O << Mang->getValueName(GV);
return; return;
@ -477,7 +477,7 @@ void Printer::printOp(const MachineOperand &MO,
} }
} }
void Printer::printImmOp(const MachineOperand &MO, unsigned ArgType) { void PowerPCAsmPrinter::printImmOp(const MachineOperand &MO, unsigned ArgType) {
int Imm = MO.getImmedValue(); int Imm = MO.getImmedValue();
if (ArgType == PPCII::Simm16 || ArgType == PPCII::Disimm16) { if (ArgType == PPCII::Simm16 || ArgType == PPCII::Disimm16) {
O << (short)Imm; O << (short)Imm;
@ -488,10 +488,14 @@ void Printer::printImmOp(const MachineOperand &MO, unsigned ArgType) {
} }
} }
/// printMachineInstruction -- Print out a single PPC LLVM instruction /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to
/// MI in Darwin syntax to the current output stream. /// the current output stream.
/// ///
void Printer::printMachineInstruction(const MachineInstr *MI) { void PowerPCAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
++EmittedInsts;
if (printInstruction(MI))
return; // Printer was automatically generated
unsigned Opcode = MI->getOpcode(); unsigned Opcode = MI->getOpcode();
const TargetInstrInfo &TII = *TM.getInstrInfo(); const TargetInstrInfo &TII = *TM.getInstrInfo();
const TargetInstrDescriptor &Desc = TII.get(Opcode); const TargetInstrDescriptor &Desc = TII.get(Opcode);
@ -509,7 +513,6 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
"Instruction requires VMX support"); "Instruction requires VMX support");
assert(((Desc.TSFlags & PPCII::PPC64) == 0) && assert(((Desc.TSFlags & PPCII::PPC64) == 0) &&
"Instruction requires 64 bit support"); "Instruction requires 64 bit support");
++EmittedInsts;
// CALLpcrel and CALLindirect are handled specially here to print only the // CALLpcrel and CALLindirect are handled specially here to print only the
// appropriate number of args that the assembler expects. This is because // appropriate number of args that the assembler expects. This is because
@ -603,9 +606,18 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
O << ", "; O << ", ";
} }
} }
return;
// Call the autogenerated instruction printer routines.
bool Handled = printInstruction(MI);
if (!Handled) {
MI->dump();
assert(0 && "Do not know how to print this instruction!");
abort();
}
} }
bool Printer::doInitialization(Module &M) { bool PowerPCAsmPrinter::doInitialization(Module &M) {
Mang = new Mangler(M, true); Mang = new Mangler(M, true);
return false; // success return false; // success
} }
@ -622,7 +634,7 @@ static void SwitchSection(std::ostream &OS, std::string &CurSection,
} }
} }
bool Printer::doFinalization(Module &M) { bool PowerPCAsmPrinter::doFinalization(Module &M) {
const TargetData &TD = TM.getTargetData(); const TargetData &TD = TM.getTargetData();
std::string CurSection; std::string CurSection;
@ -683,15 +695,6 @@ bool Printer::doFinalization(Module &M) {
} }
} }
// Output stubs for link-once variables
if (LinkOnceStubs.begin() != LinkOnceStubs.end())
O << ".data\n.align 2\n";
for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
e = LinkOnceStubs.end(); i != e; ++i) {
O << *i << "$non_lazy_ptr:\n"
<< "\t.long\t" << *i << '\n';
}
// Output stubs for dynamically-linked functions // Output stubs for dynamically-linked functions
for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end(); for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
i != e; ++i) i != e; ++i)
@ -729,6 +732,15 @@ bool Printer::doFinalization(Module &M) {
O << "\t.long\t0\n"; O << "\t.long\t0\n";
} }
// Output stubs for link-once variables
if (LinkOnceStubs.begin() != LinkOnceStubs.end())
O << ".data\n.align 2\n";
for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
e = LinkOnceStubs.end(); i != e; ++i) {
O << "L" << *i << "$non_lazy_ptr:\n"
<< "\t.long\t" << *i << '\n';
}
delete Mang; delete Mang;
return false; // success return false; // success
} }