Home | History | Annotate | Download | only in SystemZ
      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 void 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.
    206 static MCSymbolRefExpr::VariantKind
    207 getModifierVariantKind(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 
    217 void SystemZAsmPrinter::
    218 EmitMachineConstantPoolValue(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 
    230 bool 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 
    247 bool 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 
    258 // Force static initialization.
    259 extern "C" void LLVMInitializeSystemZAsmPrinter() {
    260   RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
    261 }
    262