mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-22 20:43:44 +02:00
377bd87849
doing global variable classification anymore) and hookized, sink almost all target targets global variable emission code into AsmPrinter and out of each target. Some notes: 1. PIC16 does completely custom and crazy stuff, so it is not changed. 2. XCore has some custom handling for extra directives. I'll look at it next. 3. This switches linux/ppc to use .globl instead of .global. If .globl is actually wrong, let me know and I'll fix it. 4. This makes linux/ppc get a lot of random cases right which were obviously wrong before, it is probably now a bit healthier. 5. Blackfin will probably start getting .comm and other things that it didn't before. If this is undesirable, it should explicitly opt out of these things by clearing the relevant fields of MCAsmInfo. This leads to a nice diffstat: 14 files changed, 127 insertions(+), 830 deletions(-) llvm-svn: 93858
300 lines
9.0 KiB
C++
300 lines
9.0 KiB
C++
//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly writer ---------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains a printer that converts from our internal representation
|
|
// of machine-dependent LLVM code to the SystemZ assembly language.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "asm-printer"
|
|
#include "SystemZ.h"
|
|
#include "SystemZInstrInfo.h"
|
|
#include "SystemZTargetMachine.h"
|
|
#include "llvm/Constants.h"
|
|
#include "llvm/DerivedTypes.h"
|
|
#include "llvm/Module.h"
|
|
#include "llvm/Assembly/Writer.h"
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
|
#include "llvm/CodeGen/DwarfWriter.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "llvm/MC/MCStreamer.h"
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
#include "llvm/MC/MCSymbol.h"
|
|
#include "llvm/Target/TargetData.h"
|
|
#include "llvm/Target/TargetLoweringObjectFile.h"
|
|
#include "llvm/Target/TargetRegistry.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/FormattedStream.h"
|
|
using namespace llvm;
|
|
|
|
STATISTIC(EmittedInsts, "Number of machine instrs printed");
|
|
|
|
namespace {
|
|
class SystemZAsmPrinter : public AsmPrinter {
|
|
public:
|
|
SystemZAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
|
|
const MCAsmInfo *MAI, bool V)
|
|
: AsmPrinter(O, TM, MAI, V) {}
|
|
|
|
virtual const char *getPassName() const {
|
|
return "SystemZ Assembly Printer";
|
|
}
|
|
|
|
void printOperand(const MachineInstr *MI, int OpNum,
|
|
const char* Modifier = 0);
|
|
void printPCRelImmOperand(const MachineInstr *MI, int OpNum);
|
|
void printRIAddrOperand(const MachineInstr *MI, int OpNum,
|
|
const char* Modifier = 0);
|
|
void printRRIAddrOperand(const MachineInstr *MI, int OpNum,
|
|
const char* Modifier = 0);
|
|
void printS16ImmOperand(const MachineInstr *MI, int OpNum) {
|
|
O << (int16_t)MI->getOperand(OpNum).getImm();
|
|
}
|
|
void printS32ImmOperand(const MachineInstr *MI, int OpNum) {
|
|
O << (int32_t)MI->getOperand(OpNum).getImm();
|
|
}
|
|
|
|
void printInstruction(const MachineInstr *MI); // autogenerated.
|
|
static const char *getRegisterName(unsigned RegNo);
|
|
|
|
void printMachineInstruction(const MachineInstr * MI);
|
|
|
|
void emitFunctionHeader(const MachineFunction &MF);
|
|
bool runOnMachineFunction(MachineFunction &F);
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AsmPrinter::getAnalysisUsage(AU);
|
|
AU.setPreservesAll();
|
|
}
|
|
};
|
|
} // end of anonymous namespace
|
|
|
|
#include "SystemZGenAsmWriter.inc"
|
|
|
|
void SystemZAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
|
|
unsigned FnAlign = MF.getAlignment();
|
|
const Function *F = MF.getFunction();
|
|
|
|
OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
|
|
|
|
EmitAlignment(FnAlign, F);
|
|
|
|
switch (F->getLinkage()) {
|
|
default: assert(0 && "Unknown linkage type!");
|
|
case Function::InternalLinkage: // Symbols default to internal.
|
|
case Function::PrivateLinkage:
|
|
case Function::LinkerPrivateLinkage:
|
|
break;
|
|
case Function::ExternalLinkage:
|
|
O << "\t.globl\t" << *CurrentFnSym << '\n';
|
|
break;
|
|
case Function::LinkOnceAnyLinkage:
|
|
case Function::LinkOnceODRLinkage:
|
|
case Function::WeakAnyLinkage:
|
|
case Function::WeakODRLinkage:
|
|
O << "\t.weak\t" << *CurrentFnSym << '\n';
|
|
break;
|
|
}
|
|
|
|
printVisibility(CurrentFnSym, F->getVisibility());
|
|
|
|
O << "\t.type\t" << *CurrentFnSym << ",@function\n";
|
|
O << *CurrentFnSym << ":\n";
|
|
}
|
|
|
|
bool SystemZAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
|
SetupMachineFunction(MF);
|
|
O << "\n\n";
|
|
|
|
// Print out constants referenced by the function
|
|
EmitConstantPool(MF.getConstantPool());
|
|
|
|
// Print the 'header' of function
|
|
emitFunctionHeader(MF);
|
|
|
|
// Print out code for the function.
|
|
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
|
|
I != E; ++I) {
|
|
// Print a label for the basic block.
|
|
EmitBasicBlockStart(I);
|
|
|
|
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
|
|
II != E; ++II)
|
|
// Print the assembly for the instruction.
|
|
printMachineInstruction(II);
|
|
}
|
|
|
|
if (MAI->hasDotTypeDotSizeDirective())
|
|
O << "\t.size\t" << *CurrentFnSym << ", .-" << *CurrentFnSym << '\n';
|
|
|
|
// Print out jump tables referenced by the function.
|
|
EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
|
|
|
|
// We didn't modify anything
|
|
return false;
|
|
}
|
|
|
|
void SystemZAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
|
++EmittedInsts;
|
|
|
|
processDebugLoc(MI, true);
|
|
|
|
// Call the autogenerated instruction printer routines.
|
|
printInstruction(MI);
|
|
|
|
if (VerboseAsm)
|
|
EmitComments(*MI);
|
|
O << '\n';
|
|
|
|
processDebugLoc(MI, false);
|
|
}
|
|
|
|
void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum){
|
|
const MachineOperand &MO = MI->getOperand(OpNum);
|
|
switch (MO.getType()) {
|
|
case MachineOperand::MO_Immediate:
|
|
O << MO.getImm();
|
|
return;
|
|
case MachineOperand::MO_MachineBasicBlock:
|
|
O << *GetMBBSymbol(MO.getMBB()->getNumber());
|
|
return;
|
|
case MachineOperand::MO_GlobalAddress: {
|
|
const GlobalValue *GV = MO.getGlobal();
|
|
O << *GetGlobalValueSymbol(GV);
|
|
|
|
// Assemble calls via PLT for externally visible symbols if PIC.
|
|
if (TM.getRelocationModel() == Reloc::PIC_ &&
|
|
!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
|
|
!GV->hasLocalLinkage())
|
|
O << "@PLT";
|
|
|
|
printOffset(MO.getOffset());
|
|
return;
|
|
}
|
|
case MachineOperand::MO_ExternalSymbol: {
|
|
std::string Name(MAI->getGlobalPrefix());
|
|
Name += MO.getSymbolName();
|
|
O << Name;
|
|
|
|
if (TM.getRelocationModel() == Reloc::PIC_)
|
|
O << "@PLT";
|
|
|
|
return;
|
|
}
|
|
default:
|
|
assert(0 && "Not implemented yet!");
|
|
}
|
|
}
|
|
|
|
|
|
void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
|
const char* Modifier) {
|
|
const MachineOperand &MO = MI->getOperand(OpNum);
|
|
switch (MO.getType()) {
|
|
case MachineOperand::MO_Register: {
|
|
assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
|
|
"Virtual registers should be already mapped!");
|
|
unsigned Reg = MO.getReg();
|
|
if (Modifier && strncmp(Modifier, "subreg", 6) == 0) {
|
|
if (strncmp(Modifier + 7, "even", 4) == 0)
|
|
Reg = TRI->getSubReg(Reg, SystemZ::SUBREG_EVEN);
|
|
else if (strncmp(Modifier + 7, "odd", 3) == 0)
|
|
Reg = TRI->getSubReg(Reg, SystemZ::SUBREG_ODD);
|
|
else
|
|
assert(0 && "Invalid subreg modifier");
|
|
}
|
|
|
|
O << '%' << getRegisterName(Reg);
|
|
return;
|
|
}
|
|
case MachineOperand::MO_Immediate:
|
|
O << MO.getImm();
|
|
return;
|
|
case MachineOperand::MO_MachineBasicBlock:
|
|
O << *GetMBBSymbol(MO.getMBB()->getNumber());
|
|
return;
|
|
case MachineOperand::MO_JumpTableIndex:
|
|
O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
|
|
<< MO.getIndex();
|
|
|
|
return;
|
|
case MachineOperand::MO_ConstantPoolIndex:
|
|
O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
|
|
<< MO.getIndex();
|
|
|
|
printOffset(MO.getOffset());
|
|
break;
|
|
case MachineOperand::MO_GlobalAddress:
|
|
O << *GetGlobalValueSymbol(MO.getGlobal());
|
|
break;
|
|
case MachineOperand::MO_ExternalSymbol: {
|
|
O << *GetExternalSymbolSymbol(MO.getSymbolName());
|
|
break;
|
|
}
|
|
default:
|
|
assert(0 && "Not implemented yet!");
|
|
}
|
|
|
|
switch (MO.getTargetFlags()) {
|
|
default:
|
|
llvm_unreachable("Unknown target flag on GV operand");
|
|
case SystemZII::MO_NO_FLAG:
|
|
break;
|
|
case SystemZII::MO_GOTENT: O << "@GOTENT"; break;
|
|
case SystemZII::MO_PLT: O << "@PLT"; break;
|
|
}
|
|
|
|
printOffset(MO.getOffset());
|
|
}
|
|
|
|
void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum,
|
|
const char* Modifier) {
|
|
const MachineOperand &Base = MI->getOperand(OpNum);
|
|
|
|
// Print displacement operand.
|
|
printOperand(MI, OpNum+1);
|
|
|
|
// Print base operand (if any)
|
|
if (Base.getReg()) {
|
|
O << '(';
|
|
printOperand(MI, OpNum);
|
|
O << ')';
|
|
}
|
|
}
|
|
|
|
void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum,
|
|
const char* Modifier) {
|
|
const MachineOperand &Base = MI->getOperand(OpNum);
|
|
const MachineOperand &Index = MI->getOperand(OpNum+2);
|
|
|
|
// Print displacement operand.
|
|
printOperand(MI, OpNum+1);
|
|
|
|
// Print base operand (if any)
|
|
if (Base.getReg()) {
|
|
O << '(';
|
|
printOperand(MI, OpNum);
|
|
if (Index.getReg()) {
|
|
O << ',';
|
|
printOperand(MI, OpNum+2);
|
|
}
|
|
O << ')';
|
|
} else
|
|
assert(!Index.getReg() && "Should allocate base register first!");
|
|
}
|
|
|
|
// Force static initialization.
|
|
extern "C" void LLVMInitializeSystemZAsmPrinter() {
|
|
RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
|
|
}
|