-//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly writer ---------------===//
+//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
//
// The LLVM Compiler Infrastructure
//
//
//===----------------------------------------------------------------------===//
//
-// This file contains a printer that converts from our internal representation
-// of machine-dependent LLVM code to the SystemZ assembly language.
+// Streams SystemZ assembly language and associated data, in the form of
+// MCInsts and MCExprs respectively.
//
//===----------------------------------------------------------------------===//
-#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/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
+#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/MC/MCAsmInfo.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/Target/Mangler.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-namespace {
- class SystemZAsmPrinter : public AsmPrinter {
- public:
- SystemZAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
- : AsmPrinter(TM, Streamer) {}
-
- virtual const char *getPassName() const {
- return "SystemZ Assembly Printer";
- }
- void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
- const char* Modifier = 0);
- void printPCRelImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
- void printRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
- const char* Modifier = 0);
- void printRRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
- const char* Modifier = 0);
- void printS16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
- O << (int16_t)MI->getOperand(OpNum).getImm();
- }
- void printU16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
- O << (uint16_t)MI->getOperand(OpNum).getImm();
- }
- void printS32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
- O << (int32_t)MI->getOperand(OpNum).getImm();
- }
- void printU32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
- O << (uint32_t)MI->getOperand(OpNum).getImm();
- }
+using namespace llvm;
- void printInstruction(const MachineInstr *MI, raw_ostream &O);
- static const char *getRegisterName(unsigned RegNo);
+// 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());
+}
- void EmitInstruction(const MachineInstr *MI);
- };
-} // end of anonymous namespace
+// 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());
+}
-#include "SystemZGenAsmWriter.inc"
+// 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) {
- SmallString<128> Str;
- raw_svector_ostream OS(Str);
- printInstruction(MI, OS);
- OutStreamer.EmitRawText(OS.str());
-}
+ SystemZMCInstLower Lower(MF->getContext(), *this);
+ MCInst LoweredMI;
+ switch (MI->getOpcode()) {
+ case SystemZ::Return:
+ LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
+ break;
-void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum,
- raw_ostream &O) {
- const MachineOperand &MO = MI->getOperand(OpNum);
- switch (MO.getType()) {
- case MachineOperand::MO_Immediate:
- O << MO.getImm();
- return;
- case MachineOperand::MO_MachineBasicBlock:
- O << *MO.getMBB()->getSymbol();
- return;
- case MachineOperand::MO_GlobalAddress: {
- const GlobalValue *GV = MO.getGlobal();
- O << *Mang->getSymbol(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(), O);
- return;
- }
- case MachineOperand::MO_ExternalSymbol: {
- std::string Name(MAI->getGlobalPrefix());
- Name += MO.getSymbolName();
- O << Name;
+ case SystemZ::CallBRASL:
+ LoweredMI = MCInstBuilder(SystemZ::BRASL)
+ .addReg(SystemZ::R14D)
+ .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
+ break;
- if (TM.getRelocationModel() == Reloc::PIC_)
- O << "@PLT";
+ case SystemZ::CallBASR:
+ LoweredMI = MCInstBuilder(SystemZ::BASR)
+ .addReg(SystemZ::R14D)
+ .addReg(MI->getOperand(0).getReg());
+ break;
- return;
- }
- default:
- assert(0 && "Not implemented yet!");
- }
-}
+ 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;
-void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
- raw_ostream &O, 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 = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_32bit);
- else if (strncmp(Modifier + 7, "odd", 3) == 0)
- Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_odd32);
- else
- assert(0 && "Invalid subreg modifier");
- }
+ case SystemZ::IILF64:
+ LoweredMI = MCInstBuilder(SystemZ::IILF)
+ .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
+ .addImm(MI->getOperand(2).getImm());
+ break;
- O << '%' << getRegisterName(Reg);
- return;
- }
- case MachineOperand::MO_Immediate:
- O << MO.getImm();
- return;
- case MachineOperand::MO_MachineBasicBlock:
- O << *MO.getMBB()->getSymbol();
- 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(), O);
+ case SystemZ::IIHF64:
+ LoweredMI = MCInstBuilder(SystemZ::IIHF)
+ .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
+ .addImm(MI->getOperand(2).getImm());
break;
- case MachineOperand::MO_GlobalAddress:
- O << *Mang->getSymbol(MO.getGlobal());
+
+ case SystemZ::RISBHH:
+ case SystemZ::RISBHL:
+ LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
break;
- case MachineOperand::MO_ExternalSymbol: {
- O << *GetExternalSymbolSymbol(MO.getSymbolName());
+
+ case SystemZ::RISBLH:
+ case SystemZ::RISBLL:
+ LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
break;
- }
- default:
- assert(0 && "Not implemented yet!");
- }
- switch (MO.getTargetFlags()) {
- default: assert(0 && "Unknown target flag on GV operand");
- case SystemZII::MO_NO_FLAG:
+#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 (Subtarget->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;
- case SystemZII::MO_GOTENT: O << "@GOTENT"; break;
- case SystemZII::MO_PLT: O << "@PLT"; break;
}
+ EmitToStreamer(OutStreamer, LoweredMI);
+}
- printOffset(MO.getOffset(), O);
+// 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::printRIAddrOperand(const MachineInstr *MI, int OpNum,
- raw_ostream &O,
- const char *Modifier) {
- const MachineOperand &Base = MI->getOperand(OpNum);
+void SystemZAsmPrinter::
+EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
+ auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
- // Print displacement operand.
- printOperand(MI, OpNum+1, O);
+ const MCExpr *Expr =
+ MCSymbolRefExpr::Create(getSymbol(ZCPV->getGlobalValue()),
+ getModifierVariantKind(ZCPV->getModifier()),
+ OutContext);
+ uint64_t Size =
+ TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(ZCPV->getType());
- // Print base operand (if any)
- if (Base.getReg()) {
- O << '(';
- printOperand(MI, OpNum, O);
- O << ')';
+ 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;
}
-void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum,
- raw_ostream &O,
- const char *Modifier) {
- const MachineOperand &Base = MI->getOperand(OpNum);
- const MachineOperand &Index = MI->getOperand(OpNum+2);
-
- // Print displacement operand.
- printOperand(MI, OpNum+1, O);
-
- // Print base operand (if any)
- if (Base.getReg()) {
- O << '(';
- printOperand(MI, OpNum, O);
- if (Index.getReg()) {
- O << ',';
- printOperand(MI, OpNum+2, O);
+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()) {
+ auto &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.getSubtargetImpl()->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();
}
- O << ')';
- } else
- assert(!Index.getReg() && "Should allocate base register first!");
+ }
}
// Force static initialization.