SystemZAsmPrinter.cpp revision 8eff5d998e88ba8763d72f4e94d7a32f2dbb9005
1//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// Streams SystemZ assembly language and associated data, in the form of 11// MCInsts and MCExprs respectively. 12// 13//===----------------------------------------------------------------------===// 14 15#include "SystemZAsmPrinter.h" 16#include "InstPrinter/SystemZInstPrinter.h" 17#include "SystemZConstantPoolValue.h" 18#include "SystemZMCInstLower.h" 19#include "llvm/CodeGen/MachineModuleInfoImpls.h" 20#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 21#include "llvm/MC/MCExpr.h" 22#include "llvm/MC/MCInstBuilder.h" 23#include "llvm/MC/MCStreamer.h" 24#include "llvm/Support/TargetRegistry.h" 25#include "llvm/Target/Mangler.h" 26 27using namespace llvm; 28 29// Return an RI instruction like MI with opcode Opcode, but with the 30// GR64 register operands turned into GR32s. 31static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) { 32 return MCInstBuilder(Opcode) 33 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 34 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) 35 .addImm(MI->getOperand(2).getImm()); 36} 37 38// Return an RI instruction like MI with opcode Opcode, but with the 39// GR64 register operands turned into GRH32s. 40static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) { 41 return MCInstBuilder(Opcode) 42 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 43 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg())) 44 .addImm(MI->getOperand(2).getImm()); 45} 46 47// Return an RI instruction like MI with opcode Opcode, but with the 48// R2 register turned into a GR64. 49static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) { 50 return MCInstBuilder(Opcode) 51 .addReg(MI->getOperand(0).getReg()) 52 .addReg(MI->getOperand(1).getReg()) 53 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())) 54 .addImm(MI->getOperand(3).getImm()) 55 .addImm(MI->getOperand(4).getImm()) 56 .addImm(MI->getOperand(5).getImm()); 57} 58 59void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { 60 SystemZMCInstLower Lower(MF->getContext(), *this); 61 MCInst LoweredMI; 62 switch (MI->getOpcode()) { 63 case SystemZ::Return: 64 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D); 65 break; 66 67 case SystemZ::CallBRASL: 68 LoweredMI = MCInstBuilder(SystemZ::BRASL) 69 .addReg(SystemZ::R14D) 70 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 71 break; 72 73 case SystemZ::CallBASR: 74 LoweredMI = MCInstBuilder(SystemZ::BASR) 75 .addReg(SystemZ::R14D) 76 .addReg(MI->getOperand(0).getReg()); 77 break; 78 79 case SystemZ::CallJG: 80 LoweredMI = MCInstBuilder(SystemZ::JG) 81 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 82 break; 83 84 case SystemZ::CallBR: 85 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D); 86 break; 87 88 case SystemZ::IILF64: 89 LoweredMI = MCInstBuilder(SystemZ::IILF) 90 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 91 .addImm(MI->getOperand(2).getImm()); 92 break; 93 94 case SystemZ::IIHF64: 95 LoweredMI = MCInstBuilder(SystemZ::IIHF) 96 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 97 .addImm(MI->getOperand(2).getImm()); 98 break; 99 100 case SystemZ::RISBHH: 101 case SystemZ::RISBHL: 102 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 103 break; 104 105 case SystemZ::RISBLH: 106 case SystemZ::RISBLL: 107 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 108 break; 109 110#define LOWER_LOW(NAME) \ 111 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 112 113 LOWER_LOW(IILL); 114 LOWER_LOW(IILH); 115 LOWER_LOW(NILL); 116 LOWER_LOW(NILH); 117 LOWER_LOW(NILF); 118 LOWER_LOW(OILL); 119 LOWER_LOW(OILH); 120 LOWER_LOW(OILF); 121 LOWER_LOW(XILF); 122 123#undef LOWER_LOW 124 125#define LOWER_HIGH(NAME) \ 126 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 127 128 LOWER_HIGH(IIHL); 129 LOWER_HIGH(IIHH); 130 LOWER_HIGH(NIHL); 131 LOWER_HIGH(NIHH); 132 LOWER_HIGH(NIHF); 133 LOWER_HIGH(OIHL); 134 LOWER_HIGH(OIHH); 135 LOWER_HIGH(OIHF); 136 LOWER_HIGH(XIHF); 137 138#undef LOWER_HIGH 139 140 default: 141 Lower.lower(MI, LoweredMI); 142 break; 143 } 144 OutStreamer.EmitInstruction(LoweredMI); 145} 146 147// Convert a SystemZ-specific constant pool modifier into the associated 148// MCSymbolRefExpr variant kind. 149static MCSymbolRefExpr::VariantKind 150getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 151 switch (Modifier) { 152 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 153 } 154 llvm_unreachable("Invalid SystemCPModifier!"); 155} 156 157void SystemZAsmPrinter:: 158EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 159 SystemZConstantPoolValue *ZCPV = 160 static_cast<SystemZConstantPoolValue*>(MCPV); 161 162 const MCExpr *Expr = 163 MCSymbolRefExpr::Create(Mang->getSymbol(ZCPV->getGlobalValue()), 164 getModifierVariantKind(ZCPV->getModifier()), 165 OutContext); 166 uint64_t Size = TM.getDataLayout()->getTypeAllocSize(ZCPV->getType()); 167 168 OutStreamer.EmitValue(Expr, Size); 169} 170 171bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, 172 unsigned OpNo, 173 unsigned AsmVariant, 174 const char *ExtraCode, 175 raw_ostream &OS) { 176 if (ExtraCode && *ExtraCode == 'n') { 177 if (!MI->getOperand(OpNo).isImm()) 178 return true; 179 OS << -int64_t(MI->getOperand(OpNo).getImm()); 180 } else { 181 SystemZMCInstLower Lower(MF->getContext(), *this); 182 MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo))); 183 SystemZInstPrinter::printOperand(MO, OS); 184 } 185 return false; 186} 187 188bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 189 unsigned OpNo, 190 unsigned AsmVariant, 191 const char *ExtraCode, 192 raw_ostream &OS) { 193 SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(), 194 MI->getOperand(OpNo + 1).getImm(), 195 MI->getOperand(OpNo + 2).getReg(), OS); 196 return false; 197} 198 199void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) { 200 if (Subtarget->isTargetELF()) { 201 const TargetLoweringObjectFileELF &TLOFELF = 202 static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering()); 203 204 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>(); 205 206 // Output stubs for external and common global variables. 207 MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); 208 if (!Stubs.empty()) { 209 OutStreamer.SwitchSection(TLOFELF.getDataRelSection()); 210 const DataLayout *TD = TM.getDataLayout(); 211 212 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 213 OutStreamer.EmitLabel(Stubs[i].first); 214 OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), 215 TD->getPointerSize(0)); 216 } 217 Stubs.clear(); 218 } 219 } 220} 221 222// Force static initialization. 223extern "C" void LLVMInitializeSystemZAsmPrinter() { 224 RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget); 225} 226