1251607Sdim//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===// 2251607Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6251607Sdim// 7251607Sdim//===----------------------------------------------------------------------===// 8251607Sdim// 9251607Sdim// Streams SystemZ assembly language and associated data, in the form of 10251607Sdim// MCInsts and MCExprs respectively. 11251607Sdim// 12251607Sdim//===----------------------------------------------------------------------===// 13251607Sdim 14251607Sdim#include "SystemZAsmPrinter.h" 15353358Sdim#include "MCTargetDesc/SystemZInstPrinter.h" 16251607Sdim#include "SystemZConstantPoolValue.h" 17251607Sdim#include "SystemZMCInstLower.h" 18353358Sdim#include "TargetInfo/SystemZTargetInfo.h" 19360784Sdim#include "llvm/BinaryFormat/ELF.h" 20251607Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h" 21251607Sdim#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 22276479Sdim#include "llvm/IR/Mangler.h" 23251607Sdim#include "llvm/MC/MCExpr.h" 24261991Sdim#include "llvm/MC/MCInstBuilder.h" 25360784Sdim#include "llvm/MC/MCSectionELF.h" 26251607Sdim#include "llvm/MC/MCStreamer.h" 27251607Sdim#include "llvm/Support/TargetRegistry.h" 28251607Sdim 29251607Sdimusing namespace llvm; 30251607Sdim 31261991Sdim// Return an RI instruction like MI with opcode Opcode, but with the 32261991Sdim// GR64 register operands turned into GR32s. 33261991Sdimstatic MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) { 34261991Sdim if (MI->isCompare()) 35261991Sdim return MCInstBuilder(Opcode) 36261991Sdim .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 37261991Sdim .addImm(MI->getOperand(1).getImm()); 38261991Sdim else 39261991Sdim return MCInstBuilder(Opcode) 40261991Sdim .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 41261991Sdim .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) 42261991Sdim .addImm(MI->getOperand(2).getImm()); 43261991Sdim} 44261991Sdim 45261991Sdim// Return an RI instruction like MI with opcode Opcode, but with the 46261991Sdim// GR64 register operands turned into GRH32s. 47261991Sdimstatic MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) { 48261991Sdim if (MI->isCompare()) 49261991Sdim return MCInstBuilder(Opcode) 50261991Sdim .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 51261991Sdim .addImm(MI->getOperand(1).getImm()); 52261991Sdim else 53261991Sdim return MCInstBuilder(Opcode) 54261991Sdim .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 55261991Sdim .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg())) 56261991Sdim .addImm(MI->getOperand(2).getImm()); 57261991Sdim} 58261991Sdim 59261991Sdim// Return an RI instruction like MI with opcode Opcode, but with the 60261991Sdim// R2 register turned into a GR64. 61261991Sdimstatic MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) { 62261991Sdim return MCInstBuilder(Opcode) 63261991Sdim .addReg(MI->getOperand(0).getReg()) 64261991Sdim .addReg(MI->getOperand(1).getReg()) 65261991Sdim .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())) 66261991Sdim .addImm(MI->getOperand(3).getImm()) 67261991Sdim .addImm(MI->getOperand(4).getImm()) 68261991Sdim .addImm(MI->getOperand(5).getImm()); 69261991Sdim} 70261991Sdim 71288943Sdimstatic const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) { 72288943Sdim StringRef Name = "__tls_get_offset"; 73288943Sdim return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 74288943Sdim MCSymbolRefExpr::VK_PLT, 75288943Sdim Context); 76288943Sdim} 77288943Sdim 78288943Sdimstatic const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) { 79288943Sdim StringRef Name = "_GLOBAL_OFFSET_TABLE_"; 80288943Sdim return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 81288943Sdim MCSymbolRefExpr::VK_None, 82288943Sdim Context); 83288943Sdim} 84288943Sdim 85353358Sdim// MI is an instruction that accepts an optional alignment hint, 86353358Sdim// and which was already lowered to LoweredMI. If the alignment 87353358Sdim// of the original memory operand is known, update LoweredMI to 88353358Sdim// an instruction with the corresponding hint set. 89353358Sdimstatic void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI, 90353358Sdim unsigned Opcode) { 91353358Sdim if (!MI->hasOneMemOperand()) 92353358Sdim return; 93353358Sdim const MachineMemOperand *MMO = *MI->memoperands_begin(); 94353358Sdim unsigned AlignmentHint = 0; 95353358Sdim if (MMO->getAlignment() >= 16) 96353358Sdim AlignmentHint = 4; 97353358Sdim else if (MMO->getAlignment() >= 8) 98353358Sdim AlignmentHint = 3; 99353358Sdim if (AlignmentHint == 0) 100353358Sdim return; 101353358Sdim 102353358Sdim LoweredMI.setOpcode(Opcode); 103353358Sdim LoweredMI.addOperand(MCOperand::createImm(AlignmentHint)); 104353358Sdim} 105353358Sdim 106288943Sdim// MI loads the high part of a vector from memory. Return an instruction 107288943Sdim// that uses replicating vector load Opcode to do the same thing. 108288943Sdimstatic MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) { 109288943Sdim return MCInstBuilder(Opcode) 110288943Sdim .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 111288943Sdim .addReg(MI->getOperand(1).getReg()) 112288943Sdim .addImm(MI->getOperand(2).getImm()) 113288943Sdim .addReg(MI->getOperand(3).getReg()); 114288943Sdim} 115288943Sdim 116288943Sdim// MI stores the high part of a vector to memory. Return an instruction 117288943Sdim// that uses elemental vector store Opcode to do the same thing. 118288943Sdimstatic MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) { 119288943Sdim return MCInstBuilder(Opcode) 120288943Sdim .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 121288943Sdim .addReg(MI->getOperand(1).getReg()) 122288943Sdim .addImm(MI->getOperand(2).getImm()) 123288943Sdim .addReg(MI->getOperand(3).getReg()) 124288943Sdim .addImm(0); 125288943Sdim} 126288943Sdim 127251607Sdimvoid SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { 128261991Sdim SystemZMCInstLower Lower(MF->getContext(), *this); 129251607Sdim MCInst LoweredMI; 130261991Sdim switch (MI->getOpcode()) { 131261991Sdim case SystemZ::Return: 132261991Sdim LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D); 133261991Sdim break; 134261991Sdim 135309124Sdim case SystemZ::CondReturn: 136309124Sdim LoweredMI = MCInstBuilder(SystemZ::BCR) 137309124Sdim .addImm(MI->getOperand(0).getImm()) 138309124Sdim .addImm(MI->getOperand(1).getImm()) 139309124Sdim .addReg(SystemZ::R14D); 140309124Sdim break; 141309124Sdim 142309124Sdim case SystemZ::CRBReturn: 143309124Sdim LoweredMI = MCInstBuilder(SystemZ::CRB) 144309124Sdim .addReg(MI->getOperand(0).getReg()) 145309124Sdim .addReg(MI->getOperand(1).getReg()) 146309124Sdim .addImm(MI->getOperand(2).getImm()) 147309124Sdim .addReg(SystemZ::R14D) 148309124Sdim .addImm(0); 149309124Sdim break; 150309124Sdim 151309124Sdim case SystemZ::CGRBReturn: 152309124Sdim LoweredMI = MCInstBuilder(SystemZ::CGRB) 153309124Sdim .addReg(MI->getOperand(0).getReg()) 154309124Sdim .addReg(MI->getOperand(1).getReg()) 155309124Sdim .addImm(MI->getOperand(2).getImm()) 156309124Sdim .addReg(SystemZ::R14D) 157309124Sdim .addImm(0); 158309124Sdim break; 159309124Sdim 160309124Sdim case SystemZ::CIBReturn: 161309124Sdim LoweredMI = MCInstBuilder(SystemZ::CIB) 162309124Sdim .addReg(MI->getOperand(0).getReg()) 163309124Sdim .addImm(MI->getOperand(1).getImm()) 164309124Sdim .addImm(MI->getOperand(2).getImm()) 165309124Sdim .addReg(SystemZ::R14D) 166309124Sdim .addImm(0); 167309124Sdim break; 168309124Sdim 169309124Sdim case SystemZ::CGIBReturn: 170309124Sdim LoweredMI = MCInstBuilder(SystemZ::CGIB) 171309124Sdim .addReg(MI->getOperand(0).getReg()) 172309124Sdim .addImm(MI->getOperand(1).getImm()) 173309124Sdim .addImm(MI->getOperand(2).getImm()) 174309124Sdim .addReg(SystemZ::R14D) 175309124Sdim .addImm(0); 176309124Sdim break; 177309124Sdim 178309124Sdim case SystemZ::CLRBReturn: 179309124Sdim LoweredMI = MCInstBuilder(SystemZ::CLRB) 180309124Sdim .addReg(MI->getOperand(0).getReg()) 181309124Sdim .addReg(MI->getOperand(1).getReg()) 182309124Sdim .addImm(MI->getOperand(2).getImm()) 183309124Sdim .addReg(SystemZ::R14D) 184309124Sdim .addImm(0); 185309124Sdim break; 186309124Sdim 187309124Sdim case SystemZ::CLGRBReturn: 188309124Sdim LoweredMI = MCInstBuilder(SystemZ::CLGRB) 189309124Sdim .addReg(MI->getOperand(0).getReg()) 190309124Sdim .addReg(MI->getOperand(1).getReg()) 191309124Sdim .addImm(MI->getOperand(2).getImm()) 192309124Sdim .addReg(SystemZ::R14D) 193309124Sdim .addImm(0); 194309124Sdim break; 195309124Sdim 196309124Sdim case SystemZ::CLIBReturn: 197309124Sdim LoweredMI = MCInstBuilder(SystemZ::CLIB) 198309124Sdim .addReg(MI->getOperand(0).getReg()) 199309124Sdim .addImm(MI->getOperand(1).getImm()) 200309124Sdim .addImm(MI->getOperand(2).getImm()) 201309124Sdim .addReg(SystemZ::R14D) 202309124Sdim .addImm(0); 203309124Sdim break; 204309124Sdim 205309124Sdim case SystemZ::CLGIBReturn: 206309124Sdim LoweredMI = MCInstBuilder(SystemZ::CLGIB) 207309124Sdim .addReg(MI->getOperand(0).getReg()) 208309124Sdim .addImm(MI->getOperand(1).getImm()) 209309124Sdim .addImm(MI->getOperand(2).getImm()) 210309124Sdim .addReg(SystemZ::R14D) 211309124Sdim .addImm(0); 212309124Sdim break; 213309124Sdim 214261991Sdim case SystemZ::CallBRASL: 215261991Sdim LoweredMI = MCInstBuilder(SystemZ::BRASL) 216261991Sdim .addReg(SystemZ::R14D) 217261991Sdim .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 218261991Sdim break; 219261991Sdim 220261991Sdim case SystemZ::CallBASR: 221261991Sdim LoweredMI = MCInstBuilder(SystemZ::BASR) 222261991Sdim .addReg(SystemZ::R14D) 223261991Sdim .addReg(MI->getOperand(0).getReg()); 224261991Sdim break; 225261991Sdim 226261991Sdim case SystemZ::CallJG: 227261991Sdim LoweredMI = MCInstBuilder(SystemZ::JG) 228261991Sdim .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 229261991Sdim break; 230261991Sdim 231309124Sdim case SystemZ::CallBRCL: 232309124Sdim LoweredMI = MCInstBuilder(SystemZ::BRCL) 233309124Sdim .addImm(MI->getOperand(0).getImm()) 234309124Sdim .addImm(MI->getOperand(1).getImm()) 235309124Sdim .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT)); 236309124Sdim break; 237309124Sdim 238261991Sdim case SystemZ::CallBR: 239261991Sdim LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D); 240261991Sdim break; 241261991Sdim 242309124Sdim case SystemZ::CallBCR: 243309124Sdim LoweredMI = MCInstBuilder(SystemZ::BCR) 244309124Sdim .addImm(MI->getOperand(0).getImm()) 245309124Sdim .addImm(MI->getOperand(1).getImm()) 246309124Sdim .addReg(SystemZ::R1D); 247309124Sdim break; 248309124Sdim 249309124Sdim case SystemZ::CRBCall: 250309124Sdim LoweredMI = MCInstBuilder(SystemZ::CRB) 251309124Sdim .addReg(MI->getOperand(0).getReg()) 252309124Sdim .addReg(MI->getOperand(1).getReg()) 253309124Sdim .addImm(MI->getOperand(2).getImm()) 254309124Sdim .addReg(SystemZ::R1D) 255309124Sdim .addImm(0); 256309124Sdim break; 257309124Sdim 258309124Sdim case SystemZ::CGRBCall: 259309124Sdim LoweredMI = MCInstBuilder(SystemZ::CGRB) 260309124Sdim .addReg(MI->getOperand(0).getReg()) 261309124Sdim .addReg(MI->getOperand(1).getReg()) 262309124Sdim .addImm(MI->getOperand(2).getImm()) 263309124Sdim .addReg(SystemZ::R1D) 264309124Sdim .addImm(0); 265309124Sdim break; 266309124Sdim 267309124Sdim case SystemZ::CIBCall: 268309124Sdim LoweredMI = MCInstBuilder(SystemZ::CIB) 269309124Sdim .addReg(MI->getOperand(0).getReg()) 270309124Sdim .addImm(MI->getOperand(1).getImm()) 271309124Sdim .addImm(MI->getOperand(2).getImm()) 272309124Sdim .addReg(SystemZ::R1D) 273309124Sdim .addImm(0); 274309124Sdim break; 275309124Sdim 276309124Sdim case SystemZ::CGIBCall: 277309124Sdim LoweredMI = MCInstBuilder(SystemZ::CGIB) 278309124Sdim .addReg(MI->getOperand(0).getReg()) 279309124Sdim .addImm(MI->getOperand(1).getImm()) 280309124Sdim .addImm(MI->getOperand(2).getImm()) 281309124Sdim .addReg(SystemZ::R1D) 282309124Sdim .addImm(0); 283309124Sdim break; 284309124Sdim 285309124Sdim case SystemZ::CLRBCall: 286309124Sdim LoweredMI = MCInstBuilder(SystemZ::CLRB) 287309124Sdim .addReg(MI->getOperand(0).getReg()) 288309124Sdim .addReg(MI->getOperand(1).getReg()) 289309124Sdim .addImm(MI->getOperand(2).getImm()) 290309124Sdim .addReg(SystemZ::R1D) 291309124Sdim .addImm(0); 292309124Sdim break; 293309124Sdim 294309124Sdim case SystemZ::CLGRBCall: 295309124Sdim LoweredMI = MCInstBuilder(SystemZ::CLGRB) 296309124Sdim .addReg(MI->getOperand(0).getReg()) 297309124Sdim .addReg(MI->getOperand(1).getReg()) 298309124Sdim .addImm(MI->getOperand(2).getImm()) 299309124Sdim .addReg(SystemZ::R1D) 300309124Sdim .addImm(0); 301309124Sdim break; 302309124Sdim 303309124Sdim case SystemZ::CLIBCall: 304309124Sdim LoweredMI = MCInstBuilder(SystemZ::CLIB) 305309124Sdim .addReg(MI->getOperand(0).getReg()) 306309124Sdim .addImm(MI->getOperand(1).getImm()) 307309124Sdim .addImm(MI->getOperand(2).getImm()) 308309124Sdim .addReg(SystemZ::R1D) 309309124Sdim .addImm(0); 310309124Sdim break; 311309124Sdim 312309124Sdim case SystemZ::CLGIBCall: 313309124Sdim LoweredMI = MCInstBuilder(SystemZ::CLGIB) 314309124Sdim .addReg(MI->getOperand(0).getReg()) 315309124Sdim .addImm(MI->getOperand(1).getImm()) 316309124Sdim .addImm(MI->getOperand(2).getImm()) 317309124Sdim .addReg(SystemZ::R1D) 318309124Sdim .addImm(0); 319309124Sdim break; 320309124Sdim 321288943Sdim case SystemZ::TLS_GDCALL: 322288943Sdim LoweredMI = MCInstBuilder(SystemZ::BRASL) 323288943Sdim .addReg(SystemZ::R14D) 324288943Sdim .addExpr(getTLSGetOffset(MF->getContext())) 325288943Sdim .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 326288943Sdim break; 327288943Sdim 328288943Sdim case SystemZ::TLS_LDCALL: 329288943Sdim LoweredMI = MCInstBuilder(SystemZ::BRASL) 330288943Sdim .addReg(SystemZ::R14D) 331288943Sdim .addExpr(getTLSGetOffset(MF->getContext())) 332288943Sdim .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 333288943Sdim break; 334288943Sdim 335288943Sdim case SystemZ::GOT: 336288943Sdim LoweredMI = MCInstBuilder(SystemZ::LARL) 337288943Sdim .addReg(MI->getOperand(0).getReg()) 338288943Sdim .addExpr(getGlobalOffsetTable(MF->getContext())); 339288943Sdim break; 340288943Sdim 341261991Sdim case SystemZ::IILF64: 342261991Sdim LoweredMI = MCInstBuilder(SystemZ::IILF) 343261991Sdim .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 344261991Sdim .addImm(MI->getOperand(2).getImm()); 345261991Sdim break; 346261991Sdim 347261991Sdim case SystemZ::IIHF64: 348261991Sdim LoweredMI = MCInstBuilder(SystemZ::IIHF) 349261991Sdim .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 350261991Sdim .addImm(MI->getOperand(2).getImm()); 351261991Sdim break; 352261991Sdim 353261991Sdim case SystemZ::RISBHH: 354261991Sdim case SystemZ::RISBHL: 355261991Sdim LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 356261991Sdim break; 357261991Sdim 358261991Sdim case SystemZ::RISBLH: 359261991Sdim case SystemZ::RISBLL: 360261991Sdim LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 361261991Sdim break; 362261991Sdim 363288943Sdim case SystemZ::VLVGP32: 364288943Sdim LoweredMI = MCInstBuilder(SystemZ::VLVGP) 365288943Sdim .addReg(MI->getOperand(0).getReg()) 366288943Sdim .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) 367288943Sdim .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); 368288943Sdim break; 369288943Sdim 370288943Sdim case SystemZ::VLR32: 371288943Sdim case SystemZ::VLR64: 372288943Sdim LoweredMI = MCInstBuilder(SystemZ::VLR) 373288943Sdim .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 374288943Sdim .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); 375288943Sdim break; 376288943Sdim 377353358Sdim case SystemZ::VL: 378353358Sdim Lower.lower(MI, LoweredMI); 379353358Sdim lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign); 380353358Sdim break; 381353358Sdim 382353358Sdim case SystemZ::VST: 383353358Sdim Lower.lower(MI, LoweredMI); 384353358Sdim lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign); 385353358Sdim break; 386353358Sdim 387353358Sdim case SystemZ::VLM: 388353358Sdim Lower.lower(MI, LoweredMI); 389353358Sdim lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign); 390353358Sdim break; 391353358Sdim 392353358Sdim case SystemZ::VSTM: 393353358Sdim Lower.lower(MI, LoweredMI); 394353358Sdim lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign); 395353358Sdim break; 396353358Sdim 397288943Sdim case SystemZ::VL32: 398288943Sdim LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); 399288943Sdim break; 400288943Sdim 401288943Sdim case SystemZ::VL64: 402288943Sdim LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); 403288943Sdim break; 404288943Sdim 405288943Sdim case SystemZ::VST32: 406288943Sdim LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); 407288943Sdim break; 408288943Sdim 409288943Sdim case SystemZ::VST64: 410288943Sdim LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); 411288943Sdim break; 412288943Sdim 413288943Sdim case SystemZ::LFER: 414288943Sdim LoweredMI = MCInstBuilder(SystemZ::VLGVF) 415288943Sdim .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) 416288943Sdim .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) 417288943Sdim .addReg(0).addImm(0); 418288943Sdim break; 419288943Sdim 420288943Sdim case SystemZ::LEFR: 421288943Sdim LoweredMI = MCInstBuilder(SystemZ::VLVGF) 422288943Sdim .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 423288943Sdim .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 424288943Sdim .addReg(MI->getOperand(1).getReg()) 425288943Sdim .addReg(0).addImm(0); 426288943Sdim break; 427288943Sdim 428261991Sdim#define LOWER_LOW(NAME) \ 429261991Sdim case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 430261991Sdim 431261991Sdim LOWER_LOW(IILL); 432261991Sdim LOWER_LOW(IILH); 433261991Sdim LOWER_LOW(TMLL); 434261991Sdim LOWER_LOW(TMLH); 435261991Sdim LOWER_LOW(NILL); 436261991Sdim LOWER_LOW(NILH); 437261991Sdim LOWER_LOW(NILF); 438261991Sdim LOWER_LOW(OILL); 439261991Sdim LOWER_LOW(OILH); 440261991Sdim LOWER_LOW(OILF); 441261991Sdim LOWER_LOW(XILF); 442261991Sdim 443261991Sdim#undef LOWER_LOW 444261991Sdim 445261991Sdim#define LOWER_HIGH(NAME) \ 446261991Sdim case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 447261991Sdim 448261991Sdim LOWER_HIGH(IIHL); 449261991Sdim LOWER_HIGH(IIHH); 450261991Sdim LOWER_HIGH(TMHL); 451261991Sdim LOWER_HIGH(TMHH); 452261991Sdim LOWER_HIGH(NIHL); 453261991Sdim LOWER_HIGH(NIHH); 454261991Sdim LOWER_HIGH(NIHF); 455261991Sdim LOWER_HIGH(OIHL); 456261991Sdim LOWER_HIGH(OIHH); 457261991Sdim LOWER_HIGH(OIHF); 458261991Sdim LOWER_HIGH(XIHF); 459261991Sdim 460261991Sdim#undef LOWER_HIGH 461261991Sdim 462276479Sdim case SystemZ::Serialize: 463288943Sdim if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 464314564Sdim LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 465276479Sdim .addImm(14).addReg(SystemZ::R0D); 466276479Sdim else 467314564Sdim LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 468276479Sdim .addImm(15).addReg(SystemZ::R0D); 469276479Sdim break; 470276479Sdim 471309124Sdim // Emit nothing here but a comment if we can. 472309124Sdim case SystemZ::MemBarrier: 473309124Sdim OutStreamer->emitRawComment("MEMBARRIER"); 474309124Sdim return; 475309124Sdim 476309124Sdim // We want to emit "j .+2" for traps, jumping to the relative immediate field 477309124Sdim // of the jump instruction, which is an illegal instruction. We cannot emit a 478309124Sdim // "." symbol, so create and emit a temp label before the instruction and use 479309124Sdim // that instead. 480309124Sdim case SystemZ::Trap: { 481309124Sdim MCSymbol *DotSym = OutContext.createTempSymbol(); 482309124Sdim OutStreamer->EmitLabel(DotSym); 483309124Sdim 484309124Sdim const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 485309124Sdim const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 486309124Sdim LoweredMI = MCInstBuilder(SystemZ::J) 487309124Sdim .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 488309124Sdim } 489309124Sdim break; 490309124Sdim 491309124Sdim // Conditional traps will create a branch on condition instruction that jumps 492309124Sdim // to the relative immediate field of the jump instruction. (eg. "jo .+2") 493309124Sdim case SystemZ::CondTrap: { 494309124Sdim MCSymbol *DotSym = OutContext.createTempSymbol(); 495309124Sdim OutStreamer->EmitLabel(DotSym); 496309124Sdim 497309124Sdim const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 498309124Sdim const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 499309124Sdim LoweredMI = MCInstBuilder(SystemZ::BRC) 500309124Sdim .addImm(MI->getOperand(0).getImm()) 501309124Sdim .addImm(MI->getOperand(1).getImm()) 502309124Sdim .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 503309124Sdim } 504309124Sdim break; 505309124Sdim 506360784Sdim case TargetOpcode::FENTRY_CALL: 507360784Sdim LowerFENTRY_CALL(*MI, Lower); 508360784Sdim return; 509360784Sdim 510341825Sdim case TargetOpcode::STACKMAP: 511341825Sdim LowerSTACKMAP(*MI); 512341825Sdim return; 513341825Sdim 514341825Sdim case TargetOpcode::PATCHPOINT: 515341825Sdim LowerPATCHPOINT(*MI, Lower); 516341825Sdim return; 517341825Sdim 518261991Sdim default: 519261991Sdim Lower.lower(MI, LoweredMI); 520261991Sdim break; 521261991Sdim } 522288943Sdim EmitToStreamer(*OutStreamer, LoweredMI); 523251607Sdim} 524251607Sdim 525341825Sdim 526341825Sdim// Emit the largest nop instruction smaller than or equal to NumBytes 527341825Sdim// bytes. Return the size of nop emitted. 528341825Sdimstatic unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, 529341825Sdim unsigned NumBytes, const MCSubtargetInfo &STI) { 530341825Sdim if (NumBytes < 2) { 531341825Sdim llvm_unreachable("Zero nops?"); 532341825Sdim return 0; 533341825Sdim } 534341825Sdim else if (NumBytes < 4) { 535341825Sdim OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BCRAsm) 536341825Sdim .addImm(0).addReg(SystemZ::R0D), STI); 537341825Sdim return 2; 538341825Sdim } 539341825Sdim else if (NumBytes < 6) { 540341825Sdim OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BCAsm) 541341825Sdim .addImm(0).addReg(0).addImm(0).addReg(0), 542341825Sdim STI); 543341825Sdim return 4; 544341825Sdim } 545341825Sdim else { 546341825Sdim MCSymbol *DotSym = OutContext.createTempSymbol(); 547341825Sdim const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 548360784Sdim OutStreamer.EmitLabel(DotSym); 549341825Sdim OutStreamer.EmitInstruction(MCInstBuilder(SystemZ::BRCLAsm) 550341825Sdim .addImm(0).addExpr(Dot), STI); 551341825Sdim return 6; 552341825Sdim } 553341825Sdim} 554341825Sdim 555360784Sdimvoid SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, 556360784Sdim SystemZMCInstLower &Lower) { 557360784Sdim MCContext &Ctx = MF->getContext(); 558360784Sdim if (MF->getFunction().hasFnAttribute("mrecord-mcount")) { 559360784Sdim MCSymbol *DotSym = OutContext.createTempSymbol(); 560360784Sdim OutStreamer->PushSection(); 561360784Sdim OutStreamer->SwitchSection( 562360784Sdim Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); 563360784Sdim OutStreamer->EmitSymbolValue(DotSym, 8); 564360784Sdim OutStreamer->PopSection(); 565360784Sdim OutStreamer->EmitLabel(DotSym); 566360784Sdim } 567360784Sdim 568360784Sdim if (MF->getFunction().hasFnAttribute("mnop-mcount")) { 569360784Sdim EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo()); 570360784Sdim return; 571360784Sdim } 572360784Sdim 573360784Sdim MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__"); 574360784Sdim const MCSymbolRefExpr *Op = 575360784Sdim MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx); 576360784Sdim OutStreamer->EmitInstruction(MCInstBuilder(SystemZ::BRASL) 577360784Sdim .addReg(SystemZ::R0D).addExpr(Op), getSubtargetInfo()); 578360784Sdim} 579360784Sdim 580341825Sdimvoid SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { 581341825Sdim const SystemZInstrInfo *TII = 582341825Sdim static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo()); 583341825Sdim 584341825Sdim unsigned NumNOPBytes = MI.getOperand(1).getImm(); 585341825Sdim 586360784Sdim auto &Ctx = OutStreamer->getContext(); 587360784Sdim MCSymbol *MILabel = Ctx.createTempSymbol(); 588360784Sdim OutStreamer->EmitLabel(MILabel); 589360784Sdim 590360784Sdim SM.recordStackMap(*MILabel, MI); 591341825Sdim assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); 592341825Sdim 593341825Sdim // Scan ahead to trim the shadow. 594341825Sdim unsigned ShadowBytes = 0; 595341825Sdim const MachineBasicBlock &MBB = *MI.getParent(); 596341825Sdim MachineBasicBlock::const_iterator MII(MI); 597341825Sdim ++MII; 598341825Sdim while (ShadowBytes < NumNOPBytes) { 599341825Sdim if (MII == MBB.end() || 600341825Sdim MII->getOpcode() == TargetOpcode::PATCHPOINT || 601341825Sdim MII->getOpcode() == TargetOpcode::STACKMAP) 602341825Sdim break; 603341825Sdim ShadowBytes += TII->getInstSizeInBytes(*MII); 604341825Sdim if (MII->isCall()) 605341825Sdim break; 606341825Sdim ++MII; 607341825Sdim } 608341825Sdim 609341825Sdim // Emit nops. 610341825Sdim while (ShadowBytes < NumNOPBytes) 611341825Sdim ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, 612341825Sdim getSubtargetInfo()); 613341825Sdim} 614341825Sdim 615341825Sdim// Lower a patchpoint of the form: 616341825Sdim// [<def>], <id>, <numBytes>, <target>, <numArgs> 617341825Sdimvoid SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, 618341825Sdim SystemZMCInstLower &Lower) { 619360784Sdim auto &Ctx = OutStreamer->getContext(); 620360784Sdim MCSymbol *MILabel = Ctx.createTempSymbol(); 621360784Sdim OutStreamer->EmitLabel(MILabel); 622360784Sdim 623360784Sdim SM.recordPatchPoint(*MILabel, MI); 624341825Sdim PatchPointOpers Opers(&MI); 625341825Sdim 626341825Sdim unsigned EncodedBytes = 0; 627341825Sdim const MachineOperand &CalleeMO = Opers.getCallTarget(); 628341825Sdim 629341825Sdim if (CalleeMO.isImm()) { 630341825Sdim uint64_t CallTarget = CalleeMO.getImm(); 631341825Sdim if (CallTarget) { 632341825Sdim unsigned ScratchIdx = -1; 633341825Sdim unsigned ScratchReg = 0; 634341825Sdim do { 635341825Sdim ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); 636341825Sdim ScratchReg = MI.getOperand(ScratchIdx).getReg(); 637341825Sdim } while (ScratchReg == SystemZ::R0D); 638341825Sdim 639341825Sdim // Materialize the call target address 640341825Sdim EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) 641341825Sdim .addReg(ScratchReg) 642341825Sdim .addImm(CallTarget & 0xFFFFFFFF)); 643341825Sdim EncodedBytes += 6; 644341825Sdim if (CallTarget >> 32) { 645341825Sdim EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) 646341825Sdim .addReg(ScratchReg) 647341825Sdim .addImm(CallTarget >> 32)); 648341825Sdim EncodedBytes += 6; 649341825Sdim } 650341825Sdim 651341825Sdim EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 652341825Sdim .addReg(SystemZ::R14D) 653341825Sdim .addReg(ScratchReg)); 654341825Sdim EncodedBytes += 2; 655341825Sdim } 656341825Sdim } else if (CalleeMO.isGlobal()) { 657341825Sdim const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); 658341825Sdim EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) 659341825Sdim .addReg(SystemZ::R14D) 660341825Sdim .addExpr(Expr)); 661341825Sdim EncodedBytes += 6; 662341825Sdim } 663341825Sdim 664341825Sdim // Emit padding. 665341825Sdim unsigned NumBytes = Opers.getNumPatchBytes(); 666341825Sdim assert(NumBytes >= EncodedBytes && 667341825Sdim "Patchpoint can't request size less than the length of a call."); 668341825Sdim assert((NumBytes - EncodedBytes) % 2 == 0 && 669341825Sdim "Invalid number of NOP bytes requested!"); 670341825Sdim while (EncodedBytes < NumBytes) 671341825Sdim EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, 672341825Sdim getSubtargetInfo()); 673341825Sdim} 674341825Sdim 675251607Sdim// Convert a SystemZ-specific constant pool modifier into the associated 676251607Sdim// MCSymbolRefExpr variant kind. 677251607Sdimstatic MCSymbolRefExpr::VariantKind 678251607SdimgetModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 679251607Sdim switch (Modifier) { 680288943Sdim case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 681288943Sdim case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 682288943Sdim case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 683251607Sdim case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 684251607Sdim } 685251607Sdim llvm_unreachable("Invalid SystemCPModifier!"); 686251607Sdim} 687251607Sdim 688251607Sdimvoid SystemZAsmPrinter:: 689251607SdimEmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 690276479Sdim auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 691251607Sdim 692251607Sdim const MCExpr *Expr = 693288943Sdim MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 694251607Sdim getModifierVariantKind(ZCPV->getModifier()), 695251607Sdim OutContext); 696296417Sdim uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 697251607Sdim 698288943Sdim OutStreamer->EmitValue(Expr, Size); 699251607Sdim} 700251607Sdim 701353358Sdimbool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 702251607Sdim const char *ExtraCode, 703251607Sdim raw_ostream &OS) { 704353358Sdim if (ExtraCode) 705353358Sdim return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); 706353358Sdim SystemZMCInstLower Lower(MF->getContext(), *this); 707353358Sdim MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo))); 708353358Sdim SystemZInstPrinter::printOperand(MO, MAI, OS); 709251607Sdim return false; 710251607Sdim} 711251607Sdim 712251607Sdimbool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 713251607Sdim unsigned OpNo, 714251607Sdim const char *ExtraCode, 715251607Sdim raw_ostream &OS) { 716251607Sdim SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(), 717251607Sdim MI->getOperand(OpNo + 1).getImm(), 718251607Sdim MI->getOperand(OpNo + 2).getReg(), OS); 719251607Sdim return false; 720251607Sdim} 721251607Sdim 722341825Sdimvoid SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) { 723344779Sdim emitStackMaps(SM); 724341825Sdim} 725341825Sdim 726251607Sdim// Force static initialization. 727360784Sdimextern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() { 728314564Sdim RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); 729251607Sdim} 730