forked from OSchip/llvm-project
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:
parent
8536df7dbe
commit
0ad7f813d8
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue