1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00
llvm-mirror/lib/Target/SystemZ/SystemZAsmPrinter.cpp
Richard Sandiford c2e496f7ba [SystemZ] Use upper words of GR64s for codegen
This just adds the basics necessary for allocating the upper words to
virtual registers (move, load and store).  The move support is parameterised
in a way that makes it easy to handle zero extensions, but the associated
zero-extend patterns are added by a later patch.

The easiest way of testing this seemed to be add a new "h" register
constraint for high words.  I don't expect the constraint to be useful
in real inline asms, but it should work, so I didn't try to hide it
behind an option.

llvm-svn: 191739
2013-10-01 11:26:28 +00:00

196 lines
6.5 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/MC/MCExpr.h"
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/Mangler.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) {
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
// 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());
}
void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
SystemZMCInstLower Lower(Mang, 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::IILF64:
LoweredMI = MCInstBuilder(SystemZ::IILF)
.addReg(SystemZMC::getRegAsGR32(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(NILL);
LOWER_LOW(NILH);
LOWER_LOW(NILF);
LOWER_LOW(OILL);
LOWER_LOW(OILH);
LOWER_LOW(OILF);
LOWER_LOW(XILF);
#undef LOWER_LOW
default:
Lower.lower(MI, LoweredMI);
break;
}
OutStreamer.EmitInstruction(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::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
}
llvm_unreachable("Invalid SystemCPModifier!");
}
void SystemZAsmPrinter::
EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
SystemZConstantPoolValue *ZCPV =
static_cast<SystemZConstantPoolValue*>(MCPV);
const MCExpr *Expr =
MCSymbolRefExpr::Create(Mang->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(Mang, 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;
}
void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) {
if (Subtarget->isTargetELF()) {
const TargetLoweringObjectFileELF &TLOFELF =
static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
// Output stubs for external and common global variables.
MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
if (!Stubs.empty()) {
OutStreamer.SwitchSection(TLOFELF.getDataRelSection());
const DataLayout *TD = TM.getDataLayout();
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
OutStreamer.EmitLabel(Stubs[i].first);
OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(),
TD->getPointerSize(0));
}
Stubs.clear();
}
}
}
// Force static initialization.
extern "C" void LLVMInitializeSystemZAsmPrinter() {
RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
}