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 27 using namespace llvm; 28 29 // Return an RI instruction like MI with opcode Opcode, but with the 30 // GR64 register operands turned into GR32s. 31 static 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. 45 static 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. 59 static 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 69 static 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 76 static 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 83 // MI loads the high part of a vector from memory. Return an instruction 84 // that uses replicating vector load Opcode to do the same thing. 85 static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) { 86 return MCInstBuilder(Opcode) 87 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 88 .addReg(MI->getOperand(1).getReg()) 89 .addImm(MI->getOperand(2).getImm()) 90 .addReg(MI->getOperand(3).getReg()); 91 } 92 93 // MI stores the high part of a vector to memory. Return an instruction 94 // that uses elemental vector store Opcode to do the same thing. 95 static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) { 96 return MCInstBuilder(Opcode) 97 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 98 .addReg(MI->getOperand(1).getReg()) 99 .addImm(MI->getOperand(2).getImm()) 100 .addReg(MI->getOperand(3).getReg()) 101 .addImm(0); 102 } 103 104 void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { 105 SystemZMCInstLower Lower(MF->getContext(), *this); 106 MCInst LoweredMI; 107 switch (MI->getOpcode()) { 108 case SystemZ::Return: 109 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D); 110 break; 111 112 case SystemZ::CondReturn: 113 LoweredMI = MCInstBuilder(SystemZ::BCR) 114 .addImm(MI->getOperand(0).getImm()) 115 .addImm(MI->getOperand(1).getImm()) 116 .addReg(SystemZ::R14D); 117 break; 118 119 case SystemZ::CRBReturn: 120 LoweredMI = MCInstBuilder(SystemZ::CRB) 121 .addReg(MI->getOperand(0).getReg()) 122 .addReg(MI->getOperand(1).getReg()) 123 .addImm(MI->getOperand(2).getImm()) 124 .addReg(SystemZ::R14D) 125 .addImm(0); 126 break; 127 128 case SystemZ::CGRBReturn: 129 LoweredMI = MCInstBuilder(SystemZ::CGRB) 130 .addReg(MI->getOperand(0).getReg()) 131 .addReg(MI->getOperand(1).getReg()) 132 .addImm(MI->getOperand(2).getImm()) 133 .addReg(SystemZ::R14D) 134 .addImm(0); 135 break; 136 137 case SystemZ::CIBReturn: 138 LoweredMI = MCInstBuilder(SystemZ::CIB) 139 .addReg(MI->getOperand(0).getReg()) 140 .addImm(MI->getOperand(1).getImm()) 141 .addImm(MI->getOperand(2).getImm()) 142 .addReg(SystemZ::R14D) 143 .addImm(0); 144 break; 145 146 case SystemZ::CGIBReturn: 147 LoweredMI = MCInstBuilder(SystemZ::CGIB) 148 .addReg(MI->getOperand(0).getReg()) 149 .addImm(MI->getOperand(1).getImm()) 150 .addImm(MI->getOperand(2).getImm()) 151 .addReg(SystemZ::R14D) 152 .addImm(0); 153 break; 154 155 case SystemZ::CLRBReturn: 156 LoweredMI = MCInstBuilder(SystemZ::CLRB) 157 .addReg(MI->getOperand(0).getReg()) 158 .addReg(MI->getOperand(1).getReg()) 159 .addImm(MI->getOperand(2).getImm()) 160 .addReg(SystemZ::R14D) 161 .addImm(0); 162 break; 163 164 case SystemZ::CLGRBReturn: 165 LoweredMI = MCInstBuilder(SystemZ::CLGRB) 166 .addReg(MI->getOperand(0).getReg()) 167 .addReg(MI->getOperand(1).getReg()) 168 .addImm(MI->getOperand(2).getImm()) 169 .addReg(SystemZ::R14D) 170 .addImm(0); 171 break; 172 173 case SystemZ::CLIBReturn: 174 LoweredMI = MCInstBuilder(SystemZ::CLIB) 175 .addReg(MI->getOperand(0).getReg()) 176 .addImm(MI->getOperand(1).getImm()) 177 .addImm(MI->getOperand(2).getImm()) 178 .addReg(SystemZ::R14D) 179 .addImm(0); 180 break; 181 182 case SystemZ::CLGIBReturn: 183 LoweredMI = MCInstBuilder(SystemZ::CLGIB) 184 .addReg(MI->getOperand(0).getReg()) 185 .addImm(MI->getOperand(1).getImm()) 186 .addImm(MI->getOperand(2).getImm()) 187 .addReg(SystemZ::R14D) 188 .addImm(0); 189 break; 190 191 case SystemZ::CallBRASL: 192 LoweredMI = MCInstBuilder(SystemZ::BRASL) 193 .addReg(SystemZ::R14D) 194 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 195 break; 196 197 case SystemZ::CallBASR: 198 LoweredMI = MCInstBuilder(SystemZ::BASR) 199 .addReg(SystemZ::R14D) 200 .addReg(MI->getOperand(0).getReg()); 201 break; 202 203 case SystemZ::CallJG: 204 LoweredMI = MCInstBuilder(SystemZ::JG) 205 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 206 break; 207 208 case SystemZ::CallBRCL: 209 LoweredMI = MCInstBuilder(SystemZ::BRCL) 210 .addImm(MI->getOperand(0).getImm()) 211 .addImm(MI->getOperand(1).getImm()) 212 .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT)); 213 break; 214 215 case SystemZ::CallBR: 216 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D); 217 break; 218 219 case SystemZ::TLS_GDCALL: 220 LoweredMI = MCInstBuilder(SystemZ::BRASL) 221 .addReg(SystemZ::R14D) 222 .addExpr(getTLSGetOffset(MF->getContext())) 223 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 224 break; 225 226 case SystemZ::TLS_LDCALL: 227 LoweredMI = MCInstBuilder(SystemZ::BRASL) 228 .addReg(SystemZ::R14D) 229 .addExpr(getTLSGetOffset(MF->getContext())) 230 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 231 break; 232 233 case SystemZ::GOT: 234 LoweredMI = MCInstBuilder(SystemZ::LARL) 235 .addReg(MI->getOperand(0).getReg()) 236 .addExpr(getGlobalOffsetTable(MF->getContext())); 237 break; 238 239 case SystemZ::IILF64: 240 LoweredMI = MCInstBuilder(SystemZ::IILF) 241 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 242 .addImm(MI->getOperand(2).getImm()); 243 break; 244 245 case SystemZ::IIHF64: 246 LoweredMI = MCInstBuilder(SystemZ::IIHF) 247 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 248 .addImm(MI->getOperand(2).getImm()); 249 break; 250 251 case SystemZ::RISBHH: 252 case SystemZ::RISBHL: 253 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 254 break; 255 256 case SystemZ::RISBLH: 257 case SystemZ::RISBLL: 258 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 259 break; 260 261 case SystemZ::VLVGP32: 262 LoweredMI = MCInstBuilder(SystemZ::VLVGP) 263 .addReg(MI->getOperand(0).getReg()) 264 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) 265 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); 266 break; 267 268 case SystemZ::VLR32: 269 case SystemZ::VLR64: 270 LoweredMI = MCInstBuilder(SystemZ::VLR) 271 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 272 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); 273 break; 274 275 case SystemZ::VL32: 276 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); 277 break; 278 279 case SystemZ::VL64: 280 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); 281 break; 282 283 case SystemZ::VST32: 284 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); 285 break; 286 287 case SystemZ::VST64: 288 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); 289 break; 290 291 case SystemZ::LFER: 292 LoweredMI = MCInstBuilder(SystemZ::VLGVF) 293 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) 294 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) 295 .addReg(0).addImm(0); 296 break; 297 298 case SystemZ::LEFR: 299 LoweredMI = MCInstBuilder(SystemZ::VLVGF) 300 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 301 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 302 .addReg(MI->getOperand(1).getReg()) 303 .addReg(0).addImm(0); 304 break; 305 306 #define LOWER_LOW(NAME) \ 307 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 308 309 LOWER_LOW(IILL); 310 LOWER_LOW(IILH); 311 LOWER_LOW(TMLL); 312 LOWER_LOW(TMLH); 313 LOWER_LOW(NILL); 314 LOWER_LOW(NILH); 315 LOWER_LOW(NILF); 316 LOWER_LOW(OILL); 317 LOWER_LOW(OILH); 318 LOWER_LOW(OILF); 319 LOWER_LOW(XILF); 320 321 #undef LOWER_LOW 322 323 #define LOWER_HIGH(NAME) \ 324 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 325 326 LOWER_HIGH(IIHL); 327 LOWER_HIGH(IIHH); 328 LOWER_HIGH(TMHL); 329 LOWER_HIGH(TMHH); 330 LOWER_HIGH(NIHL); 331 LOWER_HIGH(NIHH); 332 LOWER_HIGH(NIHF); 333 LOWER_HIGH(OIHL); 334 LOWER_HIGH(OIHH); 335 LOWER_HIGH(OIHF); 336 LOWER_HIGH(XIHF); 337 338 #undef LOWER_HIGH 339 340 case SystemZ::Serialize: 341 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 342 LoweredMI = MCInstBuilder(SystemZ::AsmBCR) 343 .addImm(14).addReg(SystemZ::R0D); 344 else 345 LoweredMI = MCInstBuilder(SystemZ::AsmBCR) 346 .addImm(15).addReg(SystemZ::R0D); 347 break; 348 349 // Emit nothing here but a comment if we can. 350 case SystemZ::MemBarrier: 351 OutStreamer->emitRawComment("MEMBARRIER"); 352 return; 353 354 default: 355 Lower.lower(MI, LoweredMI); 356 break; 357 } 358 EmitToStreamer(*OutStreamer, LoweredMI); 359 } 360 361 // Convert a SystemZ-specific constant pool modifier into the associated 362 // MCSymbolRefExpr variant kind. 363 static MCSymbolRefExpr::VariantKind 364 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 365 switch (Modifier) { 366 case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 367 case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 368 case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 369 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 370 } 371 llvm_unreachable("Invalid SystemCPModifier!"); 372 } 373 374 void SystemZAsmPrinter:: 375 EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 376 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 377 378 const MCExpr *Expr = 379 MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 380 getModifierVariantKind(ZCPV->getModifier()), 381 OutContext); 382 uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 383 384 OutStreamer->EmitValue(Expr, Size); 385 } 386 387 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, 388 unsigned OpNo, 389 unsigned AsmVariant, 390 const char *ExtraCode, 391 raw_ostream &OS) { 392 if (ExtraCode && *ExtraCode == 'n') { 393 if (!MI->getOperand(OpNo).isImm()) 394 return true; 395 OS << -int64_t(MI->getOperand(OpNo).getImm()); 396 } else { 397 SystemZMCInstLower Lower(MF->getContext(), *this); 398 MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo))); 399 SystemZInstPrinter::printOperand(MO, MAI, OS); 400 } 401 return false; 402 } 403 404 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 405 unsigned OpNo, 406 unsigned AsmVariant, 407 const char *ExtraCode, 408 raw_ostream &OS) { 409 SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(), 410 MI->getOperand(OpNo + 1).getImm(), 411 MI->getOperand(OpNo + 2).getReg(), OS); 412 return false; 413 } 414 415 // Force static initialization. 416 extern "C" void LLVMInitializeSystemZAsmPrinter() { 417 RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget); 418 } 419