Home | History | Annotate | Download | only in SystemZ
      1 //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly writer ---------------===//
      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 // This file contains a printer that converts from our internal representation
     11 // of machine-dependent LLVM code to the SystemZ assembly language.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #define DEBUG_TYPE "asm-printer"
     16 #include "SystemZ.h"
     17 #include "SystemZInstrInfo.h"
     18 #include "SystemZTargetMachine.h"
     19 #include "llvm/Constants.h"
     20 #include "llvm/DerivedTypes.h"
     21 #include "llvm/Module.h"
     22 #include "llvm/Assembly/Writer.h"
     23 #include "llvm/CodeGen/AsmPrinter.h"
     24 #include "llvm/CodeGen/MachineModuleInfo.h"
     25 #include "llvm/CodeGen/MachineFunctionPass.h"
     26 #include "llvm/CodeGen/MachineConstantPool.h"
     27 #include "llvm/MC/MCStreamer.h"
     28 #include "llvm/MC/MCAsmInfo.h"
     29 #include "llvm/MC/MCSymbol.h"
     30 #include "llvm/Target/Mangler.h"
     31 #include "llvm/ADT/SmallString.h"
     32 #include "llvm/Support/TargetRegistry.h"
     33 #include "llvm/Support/raw_ostream.h"
     34 using namespace llvm;
     35 
     36 namespace {
     37   class SystemZAsmPrinter : public AsmPrinter {
     38   public:
     39     SystemZAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
     40       : AsmPrinter(TM, Streamer) {}
     41 
     42     virtual const char *getPassName() const {
     43       return "SystemZ Assembly Printer";
     44     }
     45 
     46     void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
     47                       const char* Modifier = 0);
     48     void printPCRelImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
     49     void printRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
     50                             const char* Modifier = 0);
     51     void printRRIAddrOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
     52                              const char* Modifier = 0);
     53     void printS16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
     54       O << (int16_t)MI->getOperand(OpNum).getImm();
     55     }
     56     void printU16ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
     57       O << (uint16_t)MI->getOperand(OpNum).getImm();
     58     }
     59     void printS32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
     60       O << (int32_t)MI->getOperand(OpNum).getImm();
     61     }
     62     void printU32ImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O) {
     63       O << (uint32_t)MI->getOperand(OpNum).getImm();
     64     }
     65 
     66     void printInstruction(const MachineInstr *MI, raw_ostream &O);
     67     static const char *getRegisterName(unsigned RegNo);
     68 
     69     void EmitInstruction(const MachineInstr *MI);
     70   };
     71 } // end of anonymous namespace
     72 
     73 #include "SystemZGenAsmWriter.inc"
     74 
     75 void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
     76   SmallString<128> Str;
     77   raw_svector_ostream OS(Str);
     78   printInstruction(MI, OS);
     79   OutStreamer.EmitRawText(OS.str());
     80 }
     81 
     82 void SystemZAsmPrinter::printPCRelImmOperand(const MachineInstr *MI, int OpNum,
     83                                              raw_ostream &O) {
     84   const MachineOperand &MO = MI->getOperand(OpNum);
     85   switch (MO.getType()) {
     86   case MachineOperand::MO_Immediate:
     87     O << MO.getImm();
     88     return;
     89   case MachineOperand::MO_MachineBasicBlock:
     90     O << *MO.getMBB()->getSymbol();
     91     return;
     92   case MachineOperand::MO_GlobalAddress: {
     93     const GlobalValue *GV = MO.getGlobal();
     94     O << *Mang->getSymbol(GV);
     95 
     96     // Assemble calls via PLT for externally visible symbols if PIC.
     97     if (TM.getRelocationModel() == Reloc::PIC_ &&
     98         !GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
     99         !GV->hasLocalLinkage())
    100       O << "@PLT";
    101 
    102     printOffset(MO.getOffset(), O);
    103     return;
    104   }
    105   case MachineOperand::MO_ExternalSymbol: {
    106     std::string Name(MAI->getGlobalPrefix());
    107     Name += MO.getSymbolName();
    108     O << Name;
    109 
    110     if (TM.getRelocationModel() == Reloc::PIC_)
    111       O << "@PLT";
    112 
    113     return;
    114   }
    115   default:
    116     assert(0 && "Not implemented yet!");
    117   }
    118 }
    119 
    120 
    121 void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
    122                                      raw_ostream &O, const char *Modifier) {
    123   const MachineOperand &MO = MI->getOperand(OpNum);
    124   switch (MO.getType()) {
    125   case MachineOperand::MO_Register: {
    126     assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
    127             "Virtual registers should be already mapped!");
    128     unsigned Reg = MO.getReg();
    129     if (Modifier && strncmp(Modifier, "subreg", 6) == 0) {
    130       if (strncmp(Modifier + 7, "even", 4) == 0)
    131         Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_32bit);
    132       else if (strncmp(Modifier + 7, "odd", 3) == 0)
    133         Reg = TM.getRegisterInfo()->getSubReg(Reg, SystemZ::subreg_odd32);
    134       else
    135         assert(0 && "Invalid subreg modifier");
    136     }
    137 
    138     O << '%' << getRegisterName(Reg);
    139     return;
    140   }
    141   case MachineOperand::MO_Immediate:
    142     O << MO.getImm();
    143     return;
    144   case MachineOperand::MO_MachineBasicBlock:
    145     O << *MO.getMBB()->getSymbol();
    146     return;
    147   case MachineOperand::MO_JumpTableIndex:
    148     O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
    149       << MO.getIndex();
    150 
    151     return;
    152   case MachineOperand::MO_ConstantPoolIndex:
    153     O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
    154       << MO.getIndex();
    155 
    156     printOffset(MO.getOffset(), O);
    157     break;
    158   case MachineOperand::MO_GlobalAddress:
    159     O << *Mang->getSymbol(MO.getGlobal());
    160     break;
    161   case MachineOperand::MO_ExternalSymbol: {
    162     O << *GetExternalSymbolSymbol(MO.getSymbolName());
    163     break;
    164   }
    165   default:
    166     assert(0 && "Not implemented yet!");
    167   }
    168 
    169   switch (MO.getTargetFlags()) {
    170   default: assert(0 && "Unknown target flag on GV operand");
    171   case SystemZII::MO_NO_FLAG:
    172     break;
    173   case SystemZII::MO_GOTENT:    O << "@GOTENT";    break;
    174   case SystemZII::MO_PLT:       O << "@PLT";       break;
    175   }
    176 
    177   printOffset(MO.getOffset(), O);
    178 }
    179 
    180 void SystemZAsmPrinter::printRIAddrOperand(const MachineInstr *MI, int OpNum,
    181                                            raw_ostream &O,
    182                                            const char *Modifier) {
    183   const MachineOperand &Base = MI->getOperand(OpNum);
    184 
    185   // Print displacement operand.
    186   printOperand(MI, OpNum+1, O);
    187 
    188   // Print base operand (if any)
    189   if (Base.getReg()) {
    190     O << '(';
    191     printOperand(MI, OpNum, O);
    192     O << ')';
    193   }
    194 }
    195 
    196 void SystemZAsmPrinter::printRRIAddrOperand(const MachineInstr *MI, int OpNum,
    197                                             raw_ostream &O,
    198                                             const char *Modifier) {
    199   const MachineOperand &Base = MI->getOperand(OpNum);
    200   const MachineOperand &Index = MI->getOperand(OpNum+2);
    201 
    202   // Print displacement operand.
    203   printOperand(MI, OpNum+1, O);
    204 
    205   // Print base operand (if any)
    206   if (Base.getReg()) {
    207     O << '(';
    208     printOperand(MI, OpNum, O);
    209     if (Index.getReg()) {
    210       O << ',';
    211       printOperand(MI, OpNum+2, O);
    212     }
    213     O << ')';
    214   } else
    215     assert(!Index.getReg() && "Should allocate base register first!");
    216 }
    217 
    218 // Force static initialization.
    219 extern "C" void LLVMInitializeSystemZAsmPrinter() {
    220   RegisterAsmPrinter<SystemZAsmPrinter> X(TheSystemZTarget);
    221 }
    222