SystemZAsmPrinter.cpp revision ebe69fe11e48d322045d5949c83283927a0d790b
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/IR/Mangler.h" 22#include "llvm/MC/MCExpr.h" 23#include "llvm/MC/MCInstBuilder.h" 24#include "llvm/MC/MCStreamer.h" 25#include "llvm/Support/TargetRegistry.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 if (MI->isCompare()) 33 return MCInstBuilder(Opcode) 34 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 35 .addImm(MI->getOperand(1).getImm()); 36 else 37 return MCInstBuilder(Opcode) 38 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 39 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) 40 .addImm(MI->getOperand(2).getImm()); 41} 42 43// Return an RI instruction like MI with opcode Opcode, but with the 44// GR64 register operands turned into GRH32s. 45static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) { 46 if (MI->isCompare()) 47 return MCInstBuilder(Opcode) 48 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 49 .addImm(MI->getOperand(1).getImm()); 50 else 51 return MCInstBuilder(Opcode) 52 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 53 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg())) 54 .addImm(MI->getOperand(2).getImm()); 55} 56 57// Return an RI instruction like MI with opcode Opcode, but with the 58// R2 register turned into a GR64. 59static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) { 60 return MCInstBuilder(Opcode) 61 .addReg(MI->getOperand(0).getReg()) 62 .addReg(MI->getOperand(1).getReg()) 63 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())) 64 .addImm(MI->getOperand(3).getImm()) 65 .addImm(MI->getOperand(4).getImm()) 66 .addImm(MI->getOperand(5).getImm()); 67} 68 69static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) { 70 StringRef Name = "__tls_get_offset"; 71 return MCSymbolRefExpr::Create(Context.GetOrCreateSymbol(Name), 72 MCSymbolRefExpr::VK_PLT, 73 Context); 74} 75 76static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) { 77 StringRef Name = "_GLOBAL_OFFSET_TABLE_"; 78 return MCSymbolRefExpr::Create(Context.GetOrCreateSymbol(Name), 79 MCSymbolRefExpr::VK_None, 80 Context); 81} 82 83void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { 84 SystemZMCInstLower Lower(MF->getContext(), *this); 85 MCInst LoweredMI; 86 switch (MI->getOpcode()) { 87 case SystemZ::Return: 88 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D); 89 break; 90 91 case SystemZ::CallBRASL: 92 LoweredMI = MCInstBuilder(SystemZ::BRASL) 93 .addReg(SystemZ::R14D) 94 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 95 break; 96 97 case SystemZ::CallBASR: 98 LoweredMI = MCInstBuilder(SystemZ::BASR) 99 .addReg(SystemZ::R14D) 100 .addReg(MI->getOperand(0).getReg()); 101 break; 102 103 case SystemZ::CallJG: 104 LoweredMI = MCInstBuilder(SystemZ::JG) 105 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 106 break; 107 108 case SystemZ::CallBR: 109 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D); 110 break; 111 112 case SystemZ::TLS_GDCALL: 113 LoweredMI = MCInstBuilder(SystemZ::BRASL) 114 .addReg(SystemZ::R14D) 115 .addExpr(getTLSGetOffset(MF->getContext())) 116 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 117 break; 118 119 case SystemZ::TLS_LDCALL: 120 LoweredMI = MCInstBuilder(SystemZ::BRASL) 121 .addReg(SystemZ::R14D) 122 .addExpr(getTLSGetOffset(MF->getContext())) 123 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 124 break; 125 126 case SystemZ::GOT: 127 LoweredMI = MCInstBuilder(SystemZ::LARL) 128 .addReg(MI->getOperand(0).getReg()) 129 .addExpr(getGlobalOffsetTable(MF->getContext())); 130 break; 131 132 case SystemZ::IILF64: 133 LoweredMI = MCInstBuilder(SystemZ::IILF) 134 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 135 .addImm(MI->getOperand(2).getImm()); 136 break; 137 138 case SystemZ::IIHF64: 139 LoweredMI = MCInstBuilder(SystemZ::IIHF) 140 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 141 .addImm(MI->getOperand(2).getImm()); 142 break; 143 144 case SystemZ::RISBHH: 145 case SystemZ::RISBHL: 146 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 147 break; 148 149 case SystemZ::RISBLH: 150 case SystemZ::RISBLL: 151 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 152 break; 153 154#define LOWER_LOW(NAME) \ 155 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 156 157 LOWER_LOW(IILL); 158 LOWER_LOW(IILH); 159 LOWER_LOW(TMLL); 160 LOWER_LOW(TMLH); 161 LOWER_LOW(NILL); 162 LOWER_LOW(NILH); 163 LOWER_LOW(NILF); 164 LOWER_LOW(OILL); 165 LOWER_LOW(OILH); 166 LOWER_LOW(OILF); 167 LOWER_LOW(XILF); 168 169#undef LOWER_LOW 170 171#define LOWER_HIGH(NAME) \ 172 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 173 174 LOWER_HIGH(IIHL); 175 LOWER_HIGH(IIHH); 176 LOWER_HIGH(TMHL); 177 LOWER_HIGH(TMHH); 178 LOWER_HIGH(NIHL); 179 LOWER_HIGH(NIHH); 180 LOWER_HIGH(NIHF); 181 LOWER_HIGH(OIHL); 182 LOWER_HIGH(OIHH); 183 LOWER_HIGH(OIHF); 184 LOWER_HIGH(XIHF); 185 186#undef LOWER_HIGH 187 188 case SystemZ::Serialize: 189 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 190 LoweredMI = MCInstBuilder(SystemZ::AsmBCR) 191 .addImm(14).addReg(SystemZ::R0D); 192 else 193 LoweredMI = MCInstBuilder(SystemZ::AsmBCR) 194 .addImm(15).addReg(SystemZ::R0D); 195 break; 196 197 default: 198 Lower.lower(MI, LoweredMI); 199 break; 200 } 201 EmitToStreamer(OutStreamer, LoweredMI); 202} 203 204// Convert a SystemZ-specific constant pool modifier into the associated 205// MCSymbolRefExpr variant kind. 206static MCSymbolRefExpr::VariantKind 207getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 208 switch (Modifier) { 209 case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 210 case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 211 case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 212 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 213 } 214 llvm_unreachable("Invalid SystemCPModifier!"); 215} 216 217void SystemZAsmPrinter:: 218EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 219 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 220 221 const MCExpr *Expr = 222 MCSymbolRefExpr::Create(getSymbol(ZCPV->getGlobalValue()), 223 getModifierVariantKind(ZCPV->getModifier()), 224 OutContext); 225 uint64_t Size = TM.getDataLayout()->getTypeAllocSize(ZCPV->getType()); 226 227 OutStreamer.EmitValue(Expr, Size); 228} 229 230bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, 231 unsigned OpNo, 232 unsigned AsmVariant, 233 const char *ExtraCode, 234 raw_ostream &OS) { 235 if (ExtraCode && *ExtraCode == 'n') { 236 if (!MI->getOperand(OpNo).isImm()) 237 return true; 238 OS << -int64_t(MI->getOperand(OpNo).getImm()); 239 } else { 240 SystemZMCInstLower Lower(MF->getContext(), *this); 241 MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo))); 242 SystemZInstPrinter::printOperand(MO, OS); 243 } 244 return false; 245} 246 247bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 248 unsigned OpNo, 249 unsigned AsmVariant, 250 const char *ExtraCode, 251 raw_ostream &OS) { 252 SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(), 253 MI->getOperand(OpNo + 1).getImm(), 254 MI->getOperand(OpNo + 2).getReg(), OS); 255 return false; 256} 257 258void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) { 259 if (Triple(TM.getTargetTriple()).isOSBinFormatELF()) { 260 auto &TLOFELF = 261 static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering()); 262 263 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>(); 264 265 // Output stubs for external and common global variables. 266 MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); 267 if (!Stubs.empty()) { 268 OutStreamer.SwitchSection(TLOFELF.getDataRelSection()); 269 const DataLayout *TD = TM.getDataLayout(); 270 271 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 272 OutStreamer.EmitLabel(Stubs[i].first); 273 OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), 274 TD->getPointerSize(0)); 275 } 276 Stubs.clear(); 277 } 278 } 279} 280 281// Force static initialization. 282extern "C" void LLVMInitializeSystemZAsmPrinter() { 283 RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget); 284} 285