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::CallBCR: 220 LoweredMI = MCInstBuilder(SystemZ::BCR) 221 .addImm(MI->getOperand(0).getImm()) 222 .addImm(MI->getOperand(1).getImm()) 223 .addReg(SystemZ::R1D); 224 break; 225 226 case SystemZ::CRBCall: 227 LoweredMI = MCInstBuilder(SystemZ::CRB) 228 .addReg(MI->getOperand(0).getReg()) 229 .addReg(MI->getOperand(1).getReg()) 230 .addImm(MI->getOperand(2).getImm()) 231 .addReg(SystemZ::R1D) 232 .addImm(0); 233 break; 234 235 case SystemZ::CGRBCall: 236 LoweredMI = MCInstBuilder(SystemZ::CGRB) 237 .addReg(MI->getOperand(0).getReg()) 238 .addReg(MI->getOperand(1).getReg()) 239 .addImm(MI->getOperand(2).getImm()) 240 .addReg(SystemZ::R1D) 241 .addImm(0); 242 break; 243 244 case SystemZ::CIBCall: 245 LoweredMI = MCInstBuilder(SystemZ::CIB) 246 .addReg(MI->getOperand(0).getReg()) 247 .addImm(MI->getOperand(1).getImm()) 248 .addImm(MI->getOperand(2).getImm()) 249 .addReg(SystemZ::R1D) 250 .addImm(0); 251 break; 252 253 case SystemZ::CGIBCall: 254 LoweredMI = MCInstBuilder(SystemZ::CGIB) 255 .addReg(MI->getOperand(0).getReg()) 256 .addImm(MI->getOperand(1).getImm()) 257 .addImm(MI->getOperand(2).getImm()) 258 .addReg(SystemZ::R1D) 259 .addImm(0); 260 break; 261 262 case SystemZ::CLRBCall: 263 LoweredMI = MCInstBuilder(SystemZ::CLRB) 264 .addReg(MI->getOperand(0).getReg()) 265 .addReg(MI->getOperand(1).getReg()) 266 .addImm(MI->getOperand(2).getImm()) 267 .addReg(SystemZ::R1D) 268 .addImm(0); 269 break; 270 271 case SystemZ::CLGRBCall: 272 LoweredMI = MCInstBuilder(SystemZ::CLGRB) 273 .addReg(MI->getOperand(0).getReg()) 274 .addReg(MI->getOperand(1).getReg()) 275 .addImm(MI->getOperand(2).getImm()) 276 .addReg(SystemZ::R1D) 277 .addImm(0); 278 break; 279 280 case SystemZ::CLIBCall: 281 LoweredMI = MCInstBuilder(SystemZ::CLIB) 282 .addReg(MI->getOperand(0).getReg()) 283 .addImm(MI->getOperand(1).getImm()) 284 .addImm(MI->getOperand(2).getImm()) 285 .addReg(SystemZ::R1D) 286 .addImm(0); 287 break; 288 289 case SystemZ::CLGIBCall: 290 LoweredMI = MCInstBuilder(SystemZ::CLGIB) 291 .addReg(MI->getOperand(0).getReg()) 292 .addImm(MI->getOperand(1).getImm()) 293 .addImm(MI->getOperand(2).getImm()) 294 .addReg(SystemZ::R1D) 295 .addImm(0); 296 break; 297 298 case SystemZ::TLS_GDCALL: 299 LoweredMI = MCInstBuilder(SystemZ::BRASL) 300 .addReg(SystemZ::R14D) 301 .addExpr(getTLSGetOffset(MF->getContext())) 302 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 303 break; 304 305 case SystemZ::TLS_LDCALL: 306 LoweredMI = MCInstBuilder(SystemZ::BRASL) 307 .addReg(SystemZ::R14D) 308 .addExpr(getTLSGetOffset(MF->getContext())) 309 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 310 break; 311 312 case SystemZ::GOT: 313 LoweredMI = MCInstBuilder(SystemZ::LARL) 314 .addReg(MI->getOperand(0).getReg()) 315 .addExpr(getGlobalOffsetTable(MF->getContext())); 316 break; 317 318 case SystemZ::IILF64: 319 LoweredMI = MCInstBuilder(SystemZ::IILF) 320 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 321 .addImm(MI->getOperand(2).getImm()); 322 break; 323 324 case SystemZ::IIHF64: 325 LoweredMI = MCInstBuilder(SystemZ::IIHF) 326 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 327 .addImm(MI->getOperand(2).getImm()); 328 break; 329 330 case SystemZ::RISBHH: 331 case SystemZ::RISBHL: 332 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 333 break; 334 335 case SystemZ::RISBLH: 336 case SystemZ::RISBLL: 337 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 338 break; 339 340 case SystemZ::VLVGP32: 341 LoweredMI = MCInstBuilder(SystemZ::VLVGP) 342 .addReg(MI->getOperand(0).getReg()) 343 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) 344 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); 345 break; 346 347 case SystemZ::VLR32: 348 case SystemZ::VLR64: 349 LoweredMI = MCInstBuilder(SystemZ::VLR) 350 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 351 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); 352 break; 353 354 case SystemZ::VL32: 355 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); 356 break; 357 358 case SystemZ::VL64: 359 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); 360 break; 361 362 case SystemZ::VST32: 363 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); 364 break; 365 366 case SystemZ::VST64: 367 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); 368 break; 369 370 case SystemZ::LFER: 371 LoweredMI = MCInstBuilder(SystemZ::VLGVF) 372 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) 373 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) 374 .addReg(0).addImm(0); 375 break; 376 377 case SystemZ::LEFR: 378 LoweredMI = MCInstBuilder(SystemZ::VLVGF) 379 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 380 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 381 .addReg(MI->getOperand(1).getReg()) 382 .addReg(0).addImm(0); 383 break; 384 385 #define LOWER_LOW(NAME) \ 386 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 387 388 LOWER_LOW(IILL); 389 LOWER_LOW(IILH); 390 LOWER_LOW(TMLL); 391 LOWER_LOW(TMLH); 392 LOWER_LOW(NILL); 393 LOWER_LOW(NILH); 394 LOWER_LOW(NILF); 395 LOWER_LOW(OILL); 396 LOWER_LOW(OILH); 397 LOWER_LOW(OILF); 398 LOWER_LOW(XILF); 399 400 #undef LOWER_LOW 401 402 #define LOWER_HIGH(NAME) \ 403 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 404 405 LOWER_HIGH(IIHL); 406 LOWER_HIGH(IIHH); 407 LOWER_HIGH(TMHL); 408 LOWER_HIGH(TMHH); 409 LOWER_HIGH(NIHL); 410 LOWER_HIGH(NIHH); 411 LOWER_HIGH(NIHF); 412 LOWER_HIGH(OIHL); 413 LOWER_HIGH(OIHH); 414 LOWER_HIGH(OIHF); 415 LOWER_HIGH(XIHF); 416 417 #undef LOWER_HIGH 418 419 case SystemZ::Serialize: 420 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 421 LoweredMI = MCInstBuilder(SystemZ::AsmBCR) 422 .addImm(14).addReg(SystemZ::R0D); 423 else 424 LoweredMI = MCInstBuilder(SystemZ::AsmBCR) 425 .addImm(15).addReg(SystemZ::R0D); 426 break; 427 428 // Emit nothing here but a comment if we can. 429 case SystemZ::MemBarrier: 430 OutStreamer->emitRawComment("MEMBARRIER"); 431 return; 432 433 // We want to emit "j .+2" for traps, jumping to the relative immediate field 434 // of the jump instruction, which is an illegal instruction. We cannot emit a 435 // "." symbol, so create and emit a temp label before the instruction and use 436 // that instead. 437 case SystemZ::Trap: { 438 MCSymbol *DotSym = OutContext.createTempSymbol(); 439 OutStreamer->EmitLabel(DotSym); 440 441 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 442 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 443 LoweredMI = MCInstBuilder(SystemZ::J) 444 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 445 } 446 break; 447 448 // Conditional traps will create a branch on condition instruction that jumps 449 // to the relative immediate field of the jump instruction. (eg. "jo .+2") 450 case SystemZ::CondTrap: { 451 MCSymbol *DotSym = OutContext.createTempSymbol(); 452 OutStreamer->EmitLabel(DotSym); 453 454 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 455 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 456 LoweredMI = MCInstBuilder(SystemZ::BRC) 457 .addImm(MI->getOperand(0).getImm()) 458 .addImm(MI->getOperand(1).getImm()) 459 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 460 } 461 break; 462 463 default: 464 Lower.lower(MI, LoweredMI); 465 break; 466 } 467 EmitToStreamer(*OutStreamer, LoweredMI); 468 } 469 470 // Convert a SystemZ-specific constant pool modifier into the associated 471 // MCSymbolRefExpr variant kind. 472 static MCSymbolRefExpr::VariantKind 473 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 474 switch (Modifier) { 475 case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 476 case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 477 case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 478 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 479 } 480 llvm_unreachable("Invalid SystemCPModifier!"); 481 } 482 483 void SystemZAsmPrinter:: 484 EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 485 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 486 487 const MCExpr *Expr = 488 MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 489 getModifierVariantKind(ZCPV->getModifier()), 490 OutContext); 491 uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 492 493 OutStreamer->EmitValue(Expr, Size); 494 } 495 496 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, 497 unsigned OpNo, 498 unsigned AsmVariant, 499 const char *ExtraCode, 500 raw_ostream &OS) { 501 if (ExtraCode && *ExtraCode == 'n') { 502 if (!MI->getOperand(OpNo).isImm()) 503 return true; 504 OS << -int64_t(MI->getOperand(OpNo).getImm()); 505 } else { 506 SystemZMCInstLower Lower(MF->getContext(), *this); 507 MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo))); 508 SystemZInstPrinter::printOperand(MO, MAI, OS); 509 } 510 return false; 511 } 512 513 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 514 unsigned OpNo, 515 unsigned AsmVariant, 516 const char *ExtraCode, 517 raw_ostream &OS) { 518 SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(), 519 MI->getOperand(OpNo + 1).getImm(), 520 MI->getOperand(OpNo + 2).getReg(), OS); 521 return false; 522 } 523 524 // Force static initialization. 525 extern "C" void LLVMInitializeSystemZAsmPrinter() { 526 RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget); 527 } 528