]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp
Fix a memory leak in if_delgroups() introduced in r334118.
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Target / AVR / MCTargetDesc / AVRInstPrinter.cpp
1 //===-- AVRInstPrinter.cpp - Convert AVR MCInst to assembly syntax --------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This class prints an AVR MCInst to a .s file.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "AVRInstPrinter.h"
14
15 #include "MCTargetDesc/AVRMCTargetDesc.h"
16
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCInstrDesc.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/FormattedStream.h"
24
25 #include <cstring>
26
27 #define DEBUG_TYPE "asm-printer"
28
29 namespace llvm {
30
31 // Include the auto-generated portion of the assembly writer.
32 #define PRINT_ALIAS_INSTR
33 #include "AVRGenAsmWriter.inc"
34
35 void AVRInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
36                                StringRef Annot, const MCSubtargetInfo &STI) {
37   unsigned Opcode = MI->getOpcode();
38
39   // First handle load and store instructions with postinc or predec
40   // of the form "ld reg, X+".
41   // TODO: We should be able to rewrite this using TableGen data.
42   switch (Opcode) {
43   case AVR::LDRdPtr:
44   case AVR::LDRdPtrPi:
45   case AVR::LDRdPtrPd:
46     O << "\tld\t";
47     printOperand(MI, 0, O);
48     O << ", ";
49
50     if (Opcode == AVR::LDRdPtrPd)
51       O << '-';
52
53     printOperand(MI, 1, O);
54
55     if (Opcode == AVR::LDRdPtrPi)
56       O << '+';
57     break;
58   case AVR::STPtrRr:
59     O << "\tst\t";
60     printOperand(MI, 0, O);
61     O << ", ";
62     printOperand(MI, 1, O);
63     break;
64   case AVR::STPtrPiRr:
65   case AVR::STPtrPdRr:
66     O << "\tst\t";
67
68     if (Opcode == AVR::STPtrPdRr)
69       O << '-';
70
71     printOperand(MI, 1, O);
72
73     if (Opcode == AVR::STPtrPiRr)
74       O << '+';
75
76     O << ", ";
77     printOperand(MI, 2, O);
78     break;
79   default:
80     if (!printAliasInstr(MI, O))
81       printInstruction(MI, O);
82
83     printAnnotation(O, Annot);
84     break;
85   }
86 }
87
88 const char *AVRInstPrinter::getPrettyRegisterName(unsigned RegNum,
89                                                   MCRegisterInfo const &MRI) {
90   // GCC prints register pairs by just printing the lower register
91   // If the register contains a subregister, print it instead
92   if (MRI.getNumSubRegIndices() > 0) {
93     unsigned RegLoNum = MRI.getSubReg(RegNum, AVR::sub_lo);
94     RegNum = (RegLoNum != AVR::NoRegister) ? RegLoNum : RegNum;
95   }
96
97   return getRegisterName(RegNum);
98 }
99
100 void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
101                                   raw_ostream &O) {
102   const MCOperand &Op = MI->getOperand(OpNo);
103   const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).OpInfo[OpNo];
104
105   if (Op.isReg()) {
106     bool isPtrReg = (MOI.RegClass == AVR::PTRREGSRegClassID) ||
107                     (MOI.RegClass == AVR::PTRDISPREGSRegClassID) ||
108                     (MOI.RegClass == AVR::ZREGRegClassID);
109
110     if (isPtrReg) {
111       O << getRegisterName(Op.getReg(), AVR::ptr);
112     } else {
113       O << getPrettyRegisterName(Op.getReg(), MRI);
114     }
115   } else if (Op.isImm()) {
116     O << Op.getImm();
117   } else {
118     assert(Op.isExpr() && "Unknown operand kind in printOperand");
119     O << *Op.getExpr();
120   }
121 }
122
123 /// This is used to print an immediate value that ends up
124 /// being encoded as a pc-relative value.
125 void AVRInstPrinter::printPCRelImm(const MCInst *MI, unsigned OpNo,
126                                    raw_ostream &O) {
127   const MCOperand &Op = MI->getOperand(OpNo);
128
129   if (Op.isImm()) {
130     int64_t Imm = Op.getImm();
131     O << '.';
132
133     // Print a position sign if needed.
134     // Negative values have their sign printed automatically.
135     if (Imm >= 0)
136       O << '+';
137
138     O << Imm;
139   } else {
140     assert(Op.isExpr() && "Unknown pcrel immediate operand");
141     O << *Op.getExpr();
142   }
143 }
144
145 void AVRInstPrinter::printMemri(const MCInst *MI, unsigned OpNo,
146                                 raw_ostream &O) {
147   assert(MI->getOperand(OpNo).isReg() && "Expected a register for the first operand");
148
149   const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
150
151   // Print the register.
152   printOperand(MI, OpNo, O);
153
154   // Print the {+,-}offset.
155   if (OffsetOp.isImm()) {
156     int64_t Offset = OffsetOp.getImm();
157
158     if (Offset >= 0)
159       O << '+';
160
161     O << Offset;
162   } else if (OffsetOp.isExpr()) {
163     O << *OffsetOp.getExpr();
164   } else {
165     llvm_unreachable("unknown type for offset");
166   }
167 }
168
169 } // end of namespace llvm
170