LCOV - code coverage report
Current view: top level - lib/Target/AVR - AVRAsmPrinter.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 22 62 35.5 %
Date: 2018-10-20 13:21:21 Functions: 5 7 71.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- AVRAsmPrinter.cpp - AVR 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 GAS-format AVR assembly language.
      12             : //
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "AVR.h"
      16             : #include "AVRMCInstLower.h"
      17             : #include "AVRSubtarget.h"
      18             : #include "InstPrinter/AVRInstPrinter.h"
      19             : 
      20             : #include "llvm/CodeGen/AsmPrinter.h"
      21             : #include "llvm/CodeGen/MachineFunction.h"
      22             : #include "llvm/CodeGen/MachineInstr.h"
      23             : #include "llvm/CodeGen/TargetRegisterInfo.h"
      24             : #include "llvm/CodeGen/TargetSubtargetInfo.h"
      25             : #include "llvm/IR/Mangler.h"
      26             : #include "llvm/MC/MCInst.h"
      27             : #include "llvm/MC/MCStreamer.h"
      28             : #include "llvm/MC/MCSymbol.h"
      29             : #include "llvm/Support/ErrorHandling.h"
      30             : #include "llvm/Support/TargetRegistry.h"
      31             : #include "llvm/Support/raw_ostream.h"
      32             : 
      33             : #define DEBUG_TYPE "avr-asm-printer"
      34             : 
      35             : namespace llvm {
      36             : 
      37             : /// An AVR assembly code printer.
      38             : class AVRAsmPrinter : public AsmPrinter {
      39             : public:
      40          81 :   AVRAsmPrinter(TargetMachine &TM,
      41             :                 std::unique_ptr<MCStreamer> Streamer)
      42         162 :       : AsmPrinter(TM, std::move(Streamer)), MRI(*TM.getMCRegisterInfo()) { }
      43             : 
      44           0 :   StringRef getPassName() const override { return "AVR Assembly Printer"; }
      45             : 
      46             :   void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O,
      47             :                     const char *Modifier = 0);
      48             : 
      49             :   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
      50             :                        unsigned AsmVariant, const char *ExtraCode,
      51             :                        raw_ostream &O) override;
      52             : 
      53             :   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
      54             :                              unsigned AsmVariant, const char *ExtraCode,
      55             :                              raw_ostream &O) override;
      56             : 
      57             :   void EmitInstruction(const MachineInstr *MI) override;
      58             : 
      59             : private:
      60             :   const MCRegisterInfo &MRI;
      61             : };
      62             : 
      63           2 : void AVRAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
      64             :                                  raw_ostream &O, const char *Modifier) {
      65           2 :   const MachineOperand &MO = MI->getOperand(OpNo);
      66             : 
      67           2 :   switch (MO.getType()) {
      68           2 :   case MachineOperand::MO_Register:
      69           2 :     O << AVRInstPrinter::getPrettyRegisterName(MO.getReg(), MRI);
      70           2 :     break;
      71           0 :   case MachineOperand::MO_Immediate:
      72           0 :     O << MO.getImm();
      73           0 :     break;
      74           0 :   case MachineOperand::MO_GlobalAddress:
      75           0 :     O << getSymbol(MO.getGlobal());
      76           0 :     break;
      77           0 :   case MachineOperand::MO_ExternalSymbol:
      78           0 :     O << *GetExternalSymbolSymbol(MO.getSymbolName());
      79           0 :     break;
      80           0 :   case MachineOperand::MO_MachineBasicBlock:
      81           0 :     O << *MO.getMBB()->getSymbol();
      82             :     break;
      83           0 :   default:
      84           0 :     llvm_unreachable("Not implemented yet!");
      85             :   }
      86           2 : }
      87             : 
      88           3 : bool AVRAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
      89             :                                     unsigned AsmVariant, const char *ExtraCode,
      90             :                                     raw_ostream &O) {
      91             :   // Default asm printer can only deal with some extra codes,
      92             :   // so try it first.
      93           3 :   bool Error = AsmPrinter::PrintAsmOperand(MI, OpNum, AsmVariant, ExtraCode, O);
      94             : 
      95           3 :   if (Error && ExtraCode && ExtraCode[0]) {
      96           0 :     if (ExtraCode[1] != 0)
      97             :       return true; // Unknown modifier.
      98             : 
      99           0 :     if (ExtraCode[0] >= 'A' && ExtraCode[0] <= 'Z') {
     100           0 :       const MachineOperand &RegOp = MI->getOperand(OpNum);
     101             : 
     102             :       assert(RegOp.isReg() && "Operand must be a register when you're"
     103             :                               "using 'A'..'Z' operand extracodes.");
     104           0 :       unsigned Reg = RegOp.getReg();
     105             : 
     106           0 :       unsigned ByteNumber = ExtraCode[0] - 'A';
     107             : 
     108             :       unsigned OpFlags = MI->getOperand(OpNum - 1).getImm();
     109             :       unsigned NumOpRegs = InlineAsm::getNumOperandRegisters(OpFlags);
     110             :       (void)NumOpRegs;
     111             : 
     112           0 :       const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>();
     113           0 :       const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
     114             : 
     115           0 :       const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg);
     116           0 :       unsigned BytesPerReg = TRI.getRegSizeInBits(*RC) / 8;
     117             :       assert(BytesPerReg <= 2 && "Only 8 and 16 bit regs are supported.");
     118             : 
     119           0 :       unsigned RegIdx = ByteNumber / BytesPerReg;
     120             :       assert(RegIdx < NumOpRegs && "Multibyte index out of range.");
     121             : 
     122           0 :       Reg = MI->getOperand(OpNum + RegIdx).getReg();
     123             : 
     124           0 :       if (BytesPerReg == 2) {
     125           0 :         Reg = TRI.getSubReg(Reg, ByteNumber % BytesPerReg ? AVR::sub_hi
     126             :                                                           : AVR::sub_lo);
     127             :       }
     128             : 
     129           0 :       O << AVRInstPrinter::getPrettyRegisterName(Reg, MRI);
     130           0 :       return false;
     131             :     }
     132             :   }
     133             : 
     134           3 :   if (Error)
     135           2 :     printOperand(MI, OpNum, O);
     136             : 
     137             :   return false;
     138             : }
     139             : 
     140           0 : bool AVRAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
     141             :                                           unsigned OpNum, unsigned AsmVariant,
     142             :                                           const char *ExtraCode,
     143             :                                           raw_ostream &O) {
     144           0 :   if (ExtraCode && ExtraCode[0]) {
     145           0 :     llvm_unreachable("This branch is not implemented yet");
     146             :   }
     147             : 
     148           0 :   const MachineOperand &MO = MI->getOperand(OpNum);
     149             :   (void)MO;
     150             :   assert(MO.isReg() && "Unexpected inline asm memory operand");
     151             : 
     152             :   // TODO: We should be able to look up the alternative name for
     153             :   // the register if it's given.
     154             :   // TableGen doesn't expose a way of getting retrieving names
     155             :   // for registers.
     156           0 :   if (MI->getOperand(OpNum).getReg() == AVR::R31R30) {
     157           0 :     O << "Z";
     158             :   } else {
     159             :     assert(MI->getOperand(OpNum).getReg() == AVR::R29R28 &&
     160             :            "Wrong register class for memory operand.");
     161           0 :     O << "Y";
     162             :   }
     163             : 
     164             :   // If NumOpRegs == 2, then we assume it is product of a FrameIndex expansion
     165             :   // and the second operand is an Imm.
     166           0 :   unsigned OpFlags = MI->getOperand(OpNum - 1).getImm();
     167             :   unsigned NumOpRegs = InlineAsm::getNumOperandRegisters(OpFlags);
     168             : 
     169           0 :   if (NumOpRegs == 2) {
     170           0 :     O << '+' << MI->getOperand(OpNum + 1).getImm();
     171             :   }
     172             : 
     173           0 :   return false;
     174             : }
     175             : 
     176        5239 : void AVRAsmPrinter::EmitInstruction(const MachineInstr *MI) {
     177        5239 :   AVRMCInstLower MCInstLowering(OutContext, *this);
     178             : 
     179             :   MCInst I;
     180        5239 :   MCInstLowering.lowerInstruction(*MI, I);
     181        5239 :   EmitToStreamer(*OutStreamer, I);
     182        5239 : }
     183             : 
     184             : } // end of namespace llvm
     185             : 
     186       65841 : extern "C" void LLVMInitializeAVRAsmPrinter() {
     187       65841 :   llvm::RegisterAsmPrinter<llvm::AVRAsmPrinter> X(llvm::getTheAVRTarget());
     188       65841 : }
     189             : 

Generated by: LCOV version 1.13