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 void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { 70 SystemZMCInstLower Lower(MF->getContext(), *this); 71 MCInst LoweredMI; 72 switch (MI->getOpcode()) { 73 case SystemZ::Return: 74 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D); 75 break; 76 77 case SystemZ::CallBRASL: 78 LoweredMI = MCInstBuilder(SystemZ::BRASL) 79 .addReg(SystemZ::R14D) 80 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 81 break; 82 83 case SystemZ::CallBASR: 84 LoweredMI = MCInstBuilder(SystemZ::BASR) 85 .addReg(SystemZ::R14D) 86 .addReg(MI->getOperand(0).getReg()); 87 break; 88 89 case SystemZ::CallJG: 90 LoweredMI = MCInstBuilder(SystemZ::JG) 91 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 92 break; 93 94 case SystemZ::CallBR: 95 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R1D); 96 break; 97 98 case SystemZ::IILF64: 99 LoweredMI = MCInstBuilder(SystemZ::IILF) 100 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 101 .addImm(MI->getOperand(2).getImm()); 102 break; 103 104 case SystemZ::IIHF64: 105 LoweredMI = MCInstBuilder(SystemZ::IIHF) 106 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 107 .addImm(MI->getOperand(2).getImm()); 108 break; 109 110 case SystemZ::RISBHH: 111 case SystemZ::RISBHL: 112 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 113 break; 114 115 case SystemZ::RISBLH: 116 case SystemZ::RISBLL: 117 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 118 break; 119 120 #define LOWER_LOW(NAME) \ 121 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 122 123 LOWER_LOW(IILL); 124 LOWER_LOW(IILH); 125 LOWER_LOW(TMLL); 126 LOWER_LOW(TMLH); 127 LOWER_LOW(NILL); 128 LOWER_LOW(NILH); 129 LOWER_LOW(NILF); 130 LOWER_LOW(OILL); 131 LOWER_LOW(OILH); 132 LOWER_LOW(OILF); 133 LOWER_LOW(XILF); 134 135 #undef LOWER_LOW 136 137 #define LOWER_HIGH(NAME) \ 138 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 139 140 LOWER_HIGH(IIHL); 141 LOWER_HIGH(IIHH); 142 LOWER_HIGH(TMHL); 143 LOWER_HIGH(TMHH); 144 LOWER_HIGH(NIHL); 145 LOWER_HIGH(NIHH); 146 LOWER_HIGH(NIHF); 147 LOWER_HIGH(OIHL); 148 LOWER_HIGH(OIHH); 149 LOWER_HIGH(OIHF); 150 LOWER_HIGH(XIHF); 151 152 #undef LOWER_HIGH 153 154 case SystemZ::Serialize: 155 if (Subtarget->hasFastSerialization()) 156 LoweredMI = MCInstBuilder(SystemZ::AsmBCR) 157 .addImm(14).addReg(SystemZ::R0D); 158 else 159 LoweredMI = MCInstBuilder(SystemZ::AsmBCR) 160 .addImm(15).addReg(SystemZ::R0D); 161 break; 162 163 default: 164 Lower.lower(MI, LoweredMI); 165 break; 166 } 167 EmitToStreamer(OutStreamer, LoweredMI); 168 } 169 170 // Convert a SystemZ-specific constant pool modifier into the associated 171 // MCSymbolRefExpr variant kind. 172 static MCSymbolRefExpr::VariantKind 173 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 174 switch (Modifier) { 175 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 176 } 177 llvm_unreachable("Invalid SystemCPModifier!"); 178 } 179 180 void SystemZAsmPrinter:: 181 EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { 182 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 183 184 const MCExpr *Expr = 185 MCSymbolRefExpr::Create(getSymbol(ZCPV->getGlobalValue()), 186 getModifierVariantKind(ZCPV->getModifier()), 187 OutContext); 188 uint64_t Size = TM.getDataLayout()->getTypeAllocSize(ZCPV->getType()); 189 190 OutStreamer.EmitValue(Expr, Size); 191 } 192 193 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, 194 unsigned OpNo, 195 unsigned AsmVariant, 196 const char *ExtraCode, 197 raw_ostream &OS) { 198 if (ExtraCode && *ExtraCode == 'n') { 199 if (!MI->getOperand(OpNo).isImm()) 200 return true; 201 OS << -int64_t(MI->getOperand(OpNo).getImm()); 202 } else { 203 SystemZMCInstLower Lower(MF->getContext(), *this); 204 MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo))); 205 SystemZInstPrinter::printOperand(MO, OS); 206 } 207 return false; 208 } 209 210 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 211 unsigned OpNo, 212 unsigned AsmVariant, 213 const char *ExtraCode, 214 raw_ostream &OS) { 215 SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(), 216 MI->getOperand(OpNo + 1).getImm(), 217 MI->getOperand(OpNo + 2).getReg(), OS); 218 return false; 219 } 220 221 void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) { 222 if (Subtarget->isTargetELF()) { 223 auto &TLOFELF = 224 static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering()); 225 226 MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>(); 227 228 // Output stubs for external and common global variables. 229 MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); 230 if (!Stubs.empty()) { 231 OutStreamer.SwitchSection(TLOFELF.getDataRelSection()); 232 const DataLayout *TD = TM.getDataLayout(); 233 234 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) { 235 OutStreamer.EmitLabel(Stubs[i].first); 236 OutStreamer.EmitSymbolValue(Stubs[i].second.getPointer(), 237 TD->getPointerSize(0)); 238 } 239 Stubs.clear(); 240 } 241 } 242 } 243 244 // Force static initialization. 245 extern "C" void LLVMInitializeSystemZAsmPrinter() { 246 RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget); 247 } 248