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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15741 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nate Begeman 2004-08-14 22:09:10 +00:00
parent 14d89d6810
commit e59bf59ba5
2 changed files with 146 additions and 122 deletions

View File

@ -19,7 +19,7 @@
#define DEBUG_TYPE "asmprinter"
#include "PowerPC.h"
#include "PowerPCInstrInfo.h"
#include "PPC32TargetMachine.h"
#include "PowerPCTargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
@ -40,7 +40,7 @@ namespace llvm {
namespace {
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.
///
std::ostream &O;
@ -48,7 +48,7 @@ namespace {
/// Target machine description which we query for reg. names, data
/// layout, etc.
///
PPC32TargetMachine &TM;
PowerPCTargetMachine &TM;
/// Name-mangler for global names.
///
@ -56,8 +56,8 @@ namespace {
std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
std::set<std::string> Strings;
Printer(std::ostream &o, TargetMachine &tm) : O(o),
TM(reinterpret_cast<PPC32TargetMachine&>(tm)), LabelNumber(0) {}
PowerPCAsmPrinter(std::ostream &o, TargetMachine &tm) : O(o),
TM(reinterpret_cast<PowerPCTargetMachine&>(tm)), LabelNumber(0) {}
/// Cache of mangled name for current function. This is
/// recalculated at the beginning of each call to
@ -70,9 +70,15 @@ namespace {
unsigned LabelNumber;
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 printOp(const MachineOperand &MO, bool LoadAddrOp = false);
void printImmOp(const MachineOperand &MO, unsigned ArgType);
@ -90,10 +96,13 @@ namespace {
/// using the given target machine description. This should work
/// regardless of whether the function is in SSA form or not.
///
FunctionPass *createPPC32AsmPrinter(std::ostream &o,TargetMachine &tm) {
return new Printer(o, tm);
FunctionPass *createPPCAsmPrinter(std::ostream &o,TargetMachine &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?
/// 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
// constants valid in constant expressions can occur here.
void Printer::emitConstantValueOnly(const Constant *CV) {
void PowerPCAsmPrinter::emitConstantValueOnly(const Constant *CV) {
if (CV->isNullValue())
O << "0";
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
// prefix.
void Printer::emitGlobalConstant(const Constant *CV) {
void PowerPCAsmPrinter::emitGlobalConstant(const Constant *CV) {
const TargetData &TD = TM.getTargetData();
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
// precision...
double Val = CFP->getValue();
switch (CFP->getType()->getTypeID()) {
default: assert(0 && "Unknown floating point type!");
case Type::FloatTyID: {
union FU { // Abide by C TBAA rules
float FVal;
unsigned UVal;
} U;
U.FVal = Val;
O << ".long\t" << U.UVal << "\t; float " << Val << "\n";
return;
}
case Type::DoubleTyID: {
union DU { // Abide by C TBAA rules
double FVal;
uint64_t UVal;
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;
}
}
union DU { // Abide by C TBAA rules
double FVal;
uint64_t UVal;
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) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
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
/// the code generator.
///
void Printer::printConstantPool(MachineConstantPool *MCP) {
void PowerPCAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
const std::vector<Constant*> &CP = MCP->getConstants();
const TargetData &TD = TM.getTargetData();
@ -367,7 +362,7 @@ void Printer::printConstantPool(MachineConstantPool *MCP) {
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
bool Printer::runOnMachineFunction(MachineFunction &MF) {
bool PowerPCAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
O << "\n\n";
// What's my mangled name?
CurrentFnName = Mang->getValueName(MF.getFunction());
@ -400,7 +395,7 @@ bool Printer::runOnMachineFunction(MachineFunction &MF) {
return false;
}
void Printer::printOp(const MachineOperand &MO,
void PowerPCAsmPrinter::printOp(const MachineOperand &MO,
bool LoadAddrOp /* = false */) {
const MRegisterInfo &RI = *TM.getRegisterInfo();
int new_symbol;
@ -458,14 +453,19 @@ void Printer::printOp(const MachineOperand &MO,
O << "L" << Name << "$stub";
return;
}
// External global variables need a non-lazily-resolved stub
if (!GV->hasInternalLinkage() &&
TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
if (GV->isExternal() && TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
GVStubs.insert(Name);
O << "L" << Name << "$non_lazy_ptr";
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);
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();
if (ArgType == PPCII::Simm16 || ArgType == PPCII::Disimm16) {
O << (short)Imm;
@ -488,10 +488,14 @@ void Printer::printImmOp(const MachineOperand &MO, unsigned ArgType) {
}
}
/// printMachineInstruction -- Print out a single PPC LLVM instruction
/// MI in Darwin syntax to the current output stream.
/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to
/// 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();
const TargetInstrInfo &TII = *TM.getInstrInfo();
const TargetInstrDescriptor &Desc = TII.get(Opcode);
@ -509,7 +513,6 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
"Instruction requires VMX support");
assert(((Desc.TSFlags & PPCII::PPC64) == 0) &&
"Instruction requires 64 bit support");
++EmittedInsts;
// CALLpcrel and CALLindirect are handled specially here to print only the
// appropriate number of args that the assembler expects. This is because
@ -603,9 +606,18 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
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);
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();
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
for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
i != e; ++i)
@ -729,6 +732,15 @@ bool Printer::doFinalization(Module &M) {
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;
return false; // success
}

View File

@ -19,7 +19,7 @@
#define DEBUG_TYPE "asmprinter"
#include "PowerPC.h"
#include "PowerPCInstrInfo.h"
#include "PPC32TargetMachine.h"
#include "PowerPCTargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
@ -40,7 +40,7 @@ namespace llvm {
namespace {
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.
///
std::ostream &O;
@ -48,7 +48,7 @@ namespace {
/// Target machine description which we query for reg. names, data
/// layout, etc.
///
PPC32TargetMachine &TM;
PowerPCTargetMachine &TM;
/// Name-mangler for global names.
///
@ -56,8 +56,8 @@ namespace {
std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
std::set<std::string> Strings;
Printer(std::ostream &o, TargetMachine &tm) : O(o),
TM(reinterpret_cast<PPC32TargetMachine&>(tm)), LabelNumber(0) {}
PowerPCAsmPrinter(std::ostream &o, TargetMachine &tm) : O(o),
TM(reinterpret_cast<PowerPCTargetMachine&>(tm)), LabelNumber(0) {}
/// Cache of mangled name for current function. This is
/// recalculated at the beginning of each call to
@ -70,9 +70,15 @@ namespace {
unsigned LabelNumber;
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 printOp(const MachineOperand &MO, bool LoadAddrOp = false);
void printImmOp(const MachineOperand &MO, unsigned ArgType);
@ -90,10 +96,13 @@ namespace {
/// using the given target machine description. This should work
/// regardless of whether the function is in SSA form or not.
///
FunctionPass *createPPC32AsmPrinter(std::ostream &o,TargetMachine &tm) {
return new Printer(o, tm);
FunctionPass *createPPCAsmPrinter(std::ostream &o,TargetMachine &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?
/// 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
// constants valid in constant expressions can occur here.
void Printer::emitConstantValueOnly(const Constant *CV) {
void PowerPCAsmPrinter::emitConstantValueOnly(const Constant *CV) {
if (CV->isNullValue())
O << "0";
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
// prefix.
void Printer::emitGlobalConstant(const Constant *CV) {
void PowerPCAsmPrinter::emitGlobalConstant(const Constant *CV) {
const TargetData &TD = TM.getTargetData();
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
// precision...
double Val = CFP->getValue();
switch (CFP->getType()->getTypeID()) {
default: assert(0 && "Unknown floating point type!");
case Type::FloatTyID: {
union FU { // Abide by C TBAA rules
float FVal;
unsigned UVal;
} U;
U.FVal = Val;
O << ".long\t" << U.UVal << "\t; float " << Val << "\n";
return;
}
case Type::DoubleTyID: {
union DU { // Abide by C TBAA rules
double FVal;
uint64_t UVal;
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;
}
}
union DU { // Abide by C TBAA rules
double FVal;
uint64_t UVal;
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) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
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
/// the code generator.
///
void Printer::printConstantPool(MachineConstantPool *MCP) {
void PowerPCAsmPrinter::printConstantPool(MachineConstantPool *MCP) {
const std::vector<Constant*> &CP = MCP->getConstants();
const TargetData &TD = TM.getTargetData();
@ -367,7 +362,7 @@ void Printer::printConstantPool(MachineConstantPool *MCP) {
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
bool Printer::runOnMachineFunction(MachineFunction &MF) {
bool PowerPCAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
O << "\n\n";
// What's my mangled name?
CurrentFnName = Mang->getValueName(MF.getFunction());
@ -400,7 +395,7 @@ bool Printer::runOnMachineFunction(MachineFunction &MF) {
return false;
}
void Printer::printOp(const MachineOperand &MO,
void PowerPCAsmPrinter::printOp(const MachineOperand &MO,
bool LoadAddrOp /* = false */) {
const MRegisterInfo &RI = *TM.getRegisterInfo();
int new_symbol;
@ -458,14 +453,19 @@ void Printer::printOp(const MachineOperand &MO,
O << "L" << Name << "$stub";
return;
}
// External global variables need a non-lazily-resolved stub
if (!GV->hasInternalLinkage() &&
TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
if (GV->isExternal() && TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
GVStubs.insert(Name);
O << "L" << Name << "$non_lazy_ptr";
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);
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();
if (ArgType == PPCII::Simm16 || ArgType == PPCII::Disimm16) {
O << (short)Imm;
@ -488,10 +488,14 @@ void Printer::printImmOp(const MachineOperand &MO, unsigned ArgType) {
}
}
/// printMachineInstruction -- Print out a single PPC LLVM instruction
/// MI in Darwin syntax to the current output stream.
/// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to
/// 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();
const TargetInstrInfo &TII = *TM.getInstrInfo();
const TargetInstrDescriptor &Desc = TII.get(Opcode);
@ -509,7 +513,6 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
"Instruction requires VMX support");
assert(((Desc.TSFlags & PPCII::PPC64) == 0) &&
"Instruction requires 64 bit support");
++EmittedInsts;
// CALLpcrel and CALLindirect are handled specially here to print only the
// appropriate number of args that the assembler expects. This is because
@ -603,9 +606,18 @@ void Printer::printMachineInstruction(const MachineInstr *MI) {
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);
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();
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
for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
i != e; ++i)
@ -729,6 +732,15 @@ bool Printer::doFinalization(Module &M) {
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;
return false; // success
}