llvm-6502/lib/Target/SystemZ/SystemZAsmPrinter.cpp
Rafael Espindola 838c24a7c8 Refactor a lot of duplicated code for stub output.
This also moves it earlier so that it they are produced before we print
an end symbol for the data section.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@234315 91177308-0d34-0410-b5e6-96231b3b80d8
2015-04-07 13:42:44 +00:00

262 lines
8.6 KiB
C++

//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Streams SystemZ assembly language and associated data, in the form of
// MCInsts and MCExprs respectively.
//
//===----------------------------------------------------------------------===//
#include "SystemZAsmPrinter.h"
#include "InstPrinter/SystemZInstPrinter.h"
#include "SystemZConstantPoolValue.h"
#include "SystemZMCInstLower.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/IR/Mangler.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
// Return an RI instruction like MI with opcode Opcode, but with the
// GR64 register operands turned into GR32s.
static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
if (MI->isCompare())
return MCInstBuilder(Opcode)
.addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
.addImm(MI->getOperand(1).getImm());
else
return MCInstBuilder(Opcode)
.addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
.addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
.addImm(MI->getOperand(2).getImm());
}
// Return an RI instruction like MI with opcode Opcode, but with the
// GR64 register operands turned into GRH32s.
static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
if (MI->isCompare())
return MCInstBuilder(Opcode)
.addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
.addImm(MI->getOperand(1).getImm());
else
return MCInstBuilder(Opcode)
.addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
.addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
.addImm(MI->getOperand(2).getImm());
}
// Return an RI instruction like MI with opcode Opcode, but with the
// R2 register turned into a GR64.
static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
return MCInstBuilder(Opcode)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
.addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
.addImm(MI->getOperand(3).getImm())
.addImm(MI->getOperand(4).getImm())
.addImm(MI->getOperand(5).getImm());
}
static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
StringRef Name = "__tls_get_offset";
return MCSymbolRefExpr::Create(Context.GetOrCreateSymbol(Name),
MCSymbolRefExpr::VK_PLT,
Context);
}
static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
StringRef Name = "_GLOBAL_OFFSET_TABLE_";
return MCSymbolRefExpr::Create(Context.GetOrCreateSymbol(Name),
MCSymbolRefExpr::VK_None,
Context);
}
void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
SystemZMCInstLower Lower(MF->getContext(), *this);
MCInst LoweredMI;
switch (MI->getOpcode()) {
case SystemZ::Return:
LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
break;
case SystemZ::CallBRASL:
LoweredMI = MCInstBuilder(SystemZ::BRASL)
.addReg(SystemZ::R14D)
.addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
break;
case SystemZ::CallBASR:
LoweredMI = MCInstBuilder(SystemZ::BASR)
.addReg(SystemZ::R14D)
.addReg(MI->getOperand(0).getReg());
break;
case SystemZ::CallJG:
LoweredMI = MCInstBuilder(SystemZ::JG)
.addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
break;
case SystemZ::CallBR:
LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D);
break;
case SystemZ::TLS_GDCALL:
LoweredMI = MCInstBuilder(SystemZ::BRASL)
.addReg(SystemZ::R14D)
.addExpr(getTLSGetOffset(MF->getContext()))
.addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
break;
case SystemZ::TLS_LDCALL:
LoweredMI = MCInstBuilder(SystemZ::BRASL)
.addReg(SystemZ::R14D)
.addExpr(getTLSGetOffset(MF->getContext()))
.addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
break;
case SystemZ::GOT:
LoweredMI = MCInstBuilder(SystemZ::LARL)
.addReg(MI->getOperand(0).getReg())
.addExpr(getGlobalOffsetTable(MF->getContext()));
break;
case SystemZ::IILF64:
LoweredMI = MCInstBuilder(SystemZ::IILF)
.addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
.addImm(MI->getOperand(2).getImm());
break;
case SystemZ::IIHF64:
LoweredMI = MCInstBuilder(SystemZ::IIHF)
.addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
.addImm(MI->getOperand(2).getImm());
break;
case SystemZ::RISBHH:
case SystemZ::RISBHL:
LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
break;
case SystemZ::RISBLH:
case SystemZ::RISBLL:
LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
break;
#define LOWER_LOW(NAME) \
case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
LOWER_LOW(IILL);
LOWER_LOW(IILH);
LOWER_LOW(TMLL);
LOWER_LOW(TMLH);
LOWER_LOW(NILL);
LOWER_LOW(NILH);
LOWER_LOW(NILF);
LOWER_LOW(OILL);
LOWER_LOW(OILH);
LOWER_LOW(OILF);
LOWER_LOW(XILF);
#undef LOWER_LOW
#define LOWER_HIGH(NAME) \
case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
LOWER_HIGH(IIHL);
LOWER_HIGH(IIHH);
LOWER_HIGH(TMHL);
LOWER_HIGH(TMHH);
LOWER_HIGH(NIHL);
LOWER_HIGH(NIHH);
LOWER_HIGH(NIHF);
LOWER_HIGH(OIHL);
LOWER_HIGH(OIHH);
LOWER_HIGH(OIHF);
LOWER_HIGH(XIHF);
#undef LOWER_HIGH
case SystemZ::Serialize:
if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
LoweredMI = MCInstBuilder(SystemZ::AsmBCR)
.addImm(14).addReg(SystemZ::R0D);
else
LoweredMI = MCInstBuilder(SystemZ::AsmBCR)
.addImm(15).addReg(SystemZ::R0D);
break;
default:
Lower.lower(MI, LoweredMI);
break;
}
EmitToStreamer(OutStreamer, LoweredMI);
}
// Convert a SystemZ-specific constant pool modifier into the associated
// MCSymbolRefExpr variant kind.
static MCSymbolRefExpr::VariantKind
getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
switch (Modifier) {
case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
}
llvm_unreachable("Invalid SystemCPModifier!");
}
void SystemZAsmPrinter::
EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
const MCExpr *Expr =
MCSymbolRefExpr::Create(getSymbol(ZCPV->getGlobalValue()),
getModifierVariantKind(ZCPV->getModifier()),
OutContext);
uint64_t Size = TM.getDataLayout()->getTypeAllocSize(ZCPV->getType());
OutStreamer.EmitValue(Expr, Size);
}
bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI,
unsigned OpNo,
unsigned AsmVariant,
const char *ExtraCode,
raw_ostream &OS) {
if (ExtraCode && *ExtraCode == 'n') {
if (!MI->getOperand(OpNo).isImm())
return true;
OS << -int64_t(MI->getOperand(OpNo).getImm());
} else {
SystemZMCInstLower Lower(MF->getContext(), *this);
MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo)));
SystemZInstPrinter::printOperand(MO, OS);
}
return false;
}
bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
unsigned OpNo,
unsigned AsmVariant,
const char *ExtraCode,
raw_ostream &OS) {
SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(),
MI->getOperand(OpNo + 1).getImm(),
MI->getOperand(OpNo + 2).getReg(), OS);
return false;
}
// Force static initialization.
extern "C" void LLVMInitializeSystemZAsmPrinter() {
RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
}