LLVM  14.0.0git
AVRAsmPrinter.cpp
Go to the documentation of this file.
1 //===-- AVRAsmPrinter.cpp - AVR LLVM assembly writer ----------------------===//
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 file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to GAS-format AVR assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "AVR.h"
15 #include "AVRMCInstLower.h"
16 #include "AVRSubtarget.h"
18 #include "MCTargetDesc/AVRMCExpr.h"
20 
26 #include "llvm/IR/Mangler.h"
27 #include "llvm/MC/MCContext.h"
28 #include "llvm/MC/MCInst.h"
29 #include "llvm/MC/MCStreamer.h"
30 #include "llvm/MC/MCSymbol.h"
31 #include "llvm/MC/TargetRegistry.h"
34 
35 #define DEBUG_TYPE "avr-asm-printer"
36 
37 namespace llvm {
38 
39 /// An AVR assembly code printer.
40 class AVRAsmPrinter : public AsmPrinter {
41 public:
42  AVRAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
43  : AsmPrinter(TM, std::move(Streamer)), MRI(*TM.getMCRegisterInfo()) {}
44 
45  StringRef getPassName() const override { return "AVR Assembly Printer"; }
46 
47  void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O);
48 
49  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
50  const char *ExtraCode, raw_ostream &O) override;
51 
52  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
53  const char *ExtraCode, raw_ostream &O) override;
54 
55  void emitInstruction(const MachineInstr *MI) override;
56 
57  const MCExpr *lowerConstant(const Constant *CV) override;
58 
59  void emitXXStructor(const DataLayout &DL, const Constant *CV) override;
60 
61  bool doFinalization(Module &M) override;
62 
63 private:
64  const MCRegisterInfo &MRI;
65  bool EmittedStructorSymbolAttrs = false;
66 };
67 
68 void AVRAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
69  raw_ostream &O) {
70  const MachineOperand &MO = MI->getOperand(OpNo);
71 
72  switch (MO.getType()) {
75  break;
77  O << MO.getImm();
78  break;
80  O << getSymbol(MO.getGlobal());
81  break;
84  break;
86  O << *MO.getMBB()->getSymbol();
87  break;
88  default:
89  llvm_unreachable("Not implemented yet!");
90  }
91 }
92 
93 bool AVRAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
94  const char *ExtraCode, raw_ostream &O) {
95  // Default asm printer can only deal with some extra codes,
96  // so try it first.
97  bool Error = AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O);
98 
99  if (Error && ExtraCode && ExtraCode[0]) {
100  if (ExtraCode[1] != 0)
101  return true; // Unknown modifier.
102 
103  if (ExtraCode[0] >= 'A' && ExtraCode[0] <= 'Z') {
104  const MachineOperand &RegOp = MI->getOperand(OpNum);
105 
106  assert(RegOp.isReg() && "Operand must be a register when you're"
107  "using 'A'..'Z' operand extracodes.");
108  Register Reg = RegOp.getReg();
109 
110  unsigned ByteNumber = ExtraCode[0] - 'A';
111 
112  unsigned OpFlags = MI->getOperand(OpNum - 1).getImm();
113  unsigned NumOpRegs = InlineAsm::getNumOperandRegisters(OpFlags);
114  (void)NumOpRegs;
115 
116  const AVRSubtarget &STI = MF->getSubtarget<AVRSubtarget>();
117  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
118 
119  const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(Reg);
120  unsigned BytesPerReg = TRI.getRegSizeInBits(*RC) / 8;
121  assert(BytesPerReg <= 2 && "Only 8 and 16 bit regs are supported.");
122 
123  unsigned RegIdx = ByteNumber / BytesPerReg;
124  assert(RegIdx < NumOpRegs && "Multibyte index out of range.");
125 
126  Reg = MI->getOperand(OpNum + RegIdx).getReg();
127 
128  if (BytesPerReg == 2) {
129  Reg = TRI.getSubReg(Reg, ByteNumber % BytesPerReg ? AVR::sub_hi
130  : AVR::sub_lo);
131  }
132 
134  return false;
135  }
136  }
137 
138  if (Error)
139  printOperand(MI, OpNum, O);
140 
141  return false;
142 }
143 
145  unsigned OpNum, const char *ExtraCode,
146  raw_ostream &O) {
147  if (ExtraCode && ExtraCode[0])
148  return true; // Unknown modifier
149 
150  const MachineOperand &MO = MI->getOperand(OpNum);
151  (void)MO;
152  assert(MO.isReg() && "Unexpected inline asm memory operand");
153 
154  // TODO: We should be able to look up the alternative name for
155  // the register if it's given.
156  // TableGen doesn't expose a way of getting retrieving names
157  // for registers.
158  if (MI->getOperand(OpNum).getReg() == AVR::R31R30) {
159  O << "Z";
160  } else {
161  assert(MI->getOperand(OpNum).getReg() == AVR::R29R28 &&
162  "Wrong register class for memory operand.");
163  O << "Y";
164  }
165 
166  // If NumOpRegs == 2, then we assume it is product of a FrameIndex expansion
167  // and the second operand is an Imm.
168  unsigned OpFlags = MI->getOperand(OpNum - 1).getImm();
169  unsigned NumOpRegs = InlineAsm::getNumOperandRegisters(OpFlags);
170 
171  if (NumOpRegs == 2) {
172  O << '+' << MI->getOperand(OpNum + 1).getImm();
173  }
174 
175  return false;
176 }
177 
179  AVRMCInstLower MCInstLowering(OutContext, *this);
180 
181  MCInst I;
182  MCInstLowering.lowerInstruction(*MI, I);
184 }
185 
187  MCContext &Ctx = OutContext;
188 
189  if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
190  bool IsProgMem = GV->getAddressSpace() == AVR::ProgramMemory;
191  if (IsProgMem) {
192  const MCExpr *Expr = MCSymbolRefExpr::create(getSymbol(GV), Ctx);
193  return AVRMCExpr::create(AVRMCExpr::VK_AVR_PM, Expr, false, Ctx);
194  }
195  }
196 
197  return AsmPrinter::lowerConstant(CV);
198 }
199 
201  if (!EmittedStructorSymbolAttrs) {
202  OutStreamer->emitRawComment(
203  " Emitting these undefined symbol references causes us to link the"
204  " libgcc code that runs our constructors/destructors");
205  OutStreamer->emitRawComment(" This matches GCC's behavior");
206 
207  MCSymbol *CtorsSym = OutContext.getOrCreateSymbol("__do_global_ctors");
208  OutStreamer->emitSymbolAttribute(CtorsSym, MCSA_Global);
209 
210  MCSymbol *DtorsSym = OutContext.getOrCreateSymbol("__do_global_dtors");
211  OutStreamer->emitSymbolAttribute(DtorsSym, MCSA_Global);
212 
213  EmittedStructorSymbolAttrs = true;
214  }
215 
217 }
218 
220  MCSymbol *DoCopyData = OutContext.getOrCreateSymbol("__do_copy_data");
221  MCSymbol *DoClearBss = OutContext.getOrCreateSymbol("__do_clear_bss");
222 
223  // FIXME: We can disable __do_copy_data if there are no static RAM variables.
224 
225  OutStreamer->emitRawComment(
226  " Declaring this symbol tells the CRT that it should");
227  OutStreamer->emitRawComment(
228  "copy all variables from program memory to RAM on startup");
229  OutStreamer->emitSymbolAttribute(DoCopyData, MCSA_Global);
230 
231  OutStreamer->emitRawComment(
232  " Declaring this symbol tells the CRT that it should");
233  OutStreamer->emitRawComment("clear the zeroed data section on startup");
234  OutStreamer->emitSymbolAttribute(DoClearBss, MCSA_Global);
235 
237 }
238 
239 } // end of namespace llvm
240 
243 }
AsmPrinter.h
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
MachineInstr.h
llvm::MachineOperand::MO_Immediate
@ MO_Immediate
Immediate operand.
Definition: MachineOperand.h:53
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1558
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
AVRInstPrinter.h
llvm::DataLayout
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:113
llvm::AsmPrinter::emitXXStructor
virtual void emitXXStructor(const DataLayout &DL, const Constant *CV)
Targets can override this to change how global constants that are part of a C++ static/global constru...
Definition: AsmPrinter.h:515
llvm::AsmPrinter::lowerConstant
virtual const MCExpr * lowerConstant(const Constant *CV)
Lower the specified LLVM Constant to an MCExpr.
Definition: AsmPrinter.cpp:2487
llvm::AVRAsmPrinter::emitInstruction
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
Definition: AVRAsmPrinter.cpp:178
llvm::MachineOperand::getGlobal
const GlobalValue * getGlobal() const
Definition: MachineOperand.h:563
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:72
AVRMCInstLower.h
llvm::AVR::ProgramMemory
@ ProgramMemory
Definition: AVR.h:42
ErrorHandling.h
llvm::AsmPrinter::doFinalization
bool doFinalization(Module &M) override
Shut down the asmprinter.
Definition: AsmPrinter.cpp:1723
llvm::TargetRegisterInfo
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Definition: TargetRegisterInfo.h:233
LLVMInitializeAVRAsmPrinter
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmPrinter()
Definition: AVRAsmPrinter.cpp:241
llvm::AVRAsmPrinter::doFinalization
bool doFinalization(Module &M) override
Shut down the asmprinter.
Definition: AVRAsmPrinter.cpp:219
llvm::MCInst
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
TRI
unsigned const TargetRegisterInfo * TRI
Definition: MachineSink.cpp:1559
llvm::MachineOperand::MO_Register
@ MO_Register
Register operand.
Definition: MachineOperand.h:52
llvm::AsmPrinter::EmitToStreamer
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:242
AVRMCExpr.h
llvm::MachineBasicBlock::getSymbol
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
Definition: MachineBasicBlock.cpp:60
llvm::MCContext::getOrCreateSymbol
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:191
llvm::AVRMCInstLower
Lowers MachineInstr objects into MCInst objects.
Definition: AVRMCInstLower.h:25
llvm::MachineOperand::MO_GlobalAddress
@ MO_GlobalAddress
Address of a global value.
Definition: MachineOperand.h:62
llvm::MachineOperand::getImm
int64_t getImm() const
Definition: MachineOperand.h:537
llvm::AsmPrinter::OutStreamer
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:96
llvm::AVRSubtarget
A specific AVR target MCU.
Definition: AVRSubtarget.h:31
MCContext.h
llvm::TargetRegisterClass
Definition: TargetRegisterInfo.h:46
MCSymbol.h
MCInst.h
llvm::getTheAVRTarget
Target & getTheAVRTarget()
Definition: AVRTargetInfo.cpp:12
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
AVRTargetInfo.h
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
X
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
llvm::AVRAsmPrinter::PrintAsmOperand
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
Definition: AVRAsmPrinter.cpp:93
llvm::MachineFunction::getSubtarget
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Definition: MachineFunction.h:634
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:206
llvm::GlobalValue
Definition: GlobalValue.h:44
llvm::AVRMCExpr::create
static const AVRMCExpr * create(VariantKind Kind, const MCExpr *Expr, bool isNegated, MCContext &Ctx)
Creates an AVR machine code expression.
Definition: AVRMCExpr.cpp:38
llvm::Constant
This is an important base class in LLVM.
Definition: Constant.h:41
llvm::MachineOperand::isReg
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Definition: MachineOperand.h:321
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
llvm::AVRInstPrinter::getPrettyRegisterName
static const char * getPrettyRegisterName(unsigned RegNo, MCRegisterInfo const &MRI)
Definition: AVRInstPrinter.cpp:89
LLVM_EXTERNAL_VISIBILITY
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
llvm::AVRAsmPrinter::printOperand
void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O)
Definition: AVRAsmPrinter.cpp:68
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::MachineOperand::getType
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Definition: MachineOperand.h:219
llvm::AVRAsmPrinter::lowerConstant
const MCExpr * lowerConstant(const Constant *CV) override
Lower the specified LLVM Constant to an MCExpr.
Definition: AVRAsmPrinter.cpp:186
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::AsmPrinter::getSymbol
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:485
llvm::TargetMachine
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:80
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1658
llvm::AsmPrinter::MF
MachineFunction * MF
The current machine function.
Definition: AsmPrinter.h:99
llvm::AsmPrinter::OutContext
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:91
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:360
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
Mangler.h
llvm::AsmPrinter::GetExternalSymbolSymbol
MCSymbol * GetExternalSymbolSymbol(StringRef Sym) const
Return the MCSymbol for the specified ExternalSymbol.
Definition: AsmPrinter.cpp:3187
llvm::AVRMCExpr::VK_AVR_PM
@ VK_AVR_PM
Corresponds to pm(), reference to program memory.
Definition: AVRMCExpr.h:30
llvm::MachineOperand::getMBB
MachineBasicBlock * getMBB() const
Definition: MachineOperand.h:552
AVRSubtarget.h
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
llvm::MachineOperand::MO_MachineBasicBlock
@ MO_MachineBasicBlock
MachineBasicBlock reference.
Definition: MachineOperand.h:56
TargetSubtargetInfo.h
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
llvm::MCRegisterInfo
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Definition: MCRegisterInfo.h:135
llvm::AVRAsmPrinter::getPassName
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
Definition: AVRAsmPrinter.cpp:45
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
std
Definition: BitVector.h:838
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::MachineOperand::MO_ExternalSymbol
@ MO_ExternalSymbol
Name of external global symbol.
Definition: MachineOperand.h:61
llvm::AVRAsmPrinter::emitXXStructor
void emitXXStructor(const DataLayout &DL, const Constant *CV) override
Targets can override this to change how global constants that are part of a C++ static/global constru...
Definition: AVRAsmPrinter.cpp:200
llvm::AsmPrinter
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:81
llvm::MCSymbolRefExpr::create
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:386
AVR.h
llvm::MCSA_Global
@ MCSA_Global
.type _foo, @gnu_unique_object
Definition: MCDirectives.h:30
llvm::AVRAsmPrinter::AVRAsmPrinter
AVRAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer)
Definition: AVRAsmPrinter.cpp:42
llvm::AVRAsmPrinter
An AVR assembly code printer.
Definition: AVRAsmPrinter.cpp:40
llvm::AVRSubtarget::getRegisterInfo
const AVRRegisterInfo * getRegisterInfo() const override
Definition: AVRSubtarget.h:51
llvm::AsmPrinter::TM
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:84
llvm::AVRAsmPrinter::PrintAsmMemoryOperand
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
Definition: AVRAsmPrinter.cpp:144
llvm::InlineAsm::getNumOperandRegisters
static unsigned getNumOperandRegisters(unsigned Flag)
getNumOperandRegisters - Extract the number of registers field from the inline asm operand flag.
Definition: InlineAsm.h:339
llvm::MachineOperand::getSymbolName
const char * getSymbolName() const
Definition: MachineOperand.h:608
MCStreamer.h
llvm::RegisterAsmPrinter
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
Definition: TargetRegistry.h:1338
raw_ostream.h
MachineFunction.h
TargetRegistry.h
TargetRegisterInfo.h
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
llvm::AVRMCInstLower::lowerInstruction
void lowerInstruction(const MachineInstr &MI, MCInst &OutMI) const
Lowers a MachineInstr into a MCInst.
Definition: AVRMCInstLower.cpp:64
llvm::AsmPrinter::PrintAsmOperand
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
Definition: AsmPrinterInlineAsm.cpp:466