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"
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  llvm_unreachable("This branch is not implemented yet");
149  }
150 
151  const MachineOperand &MO = MI->getOperand(OpNum);
152  (void)MO;
153  assert(MO.isReg() && "Unexpected inline asm memory operand");
154 
155  // TODO: We should be able to look up the alternative name for
156  // the register if it's given.
157  // TableGen doesn't expose a way of getting retrieving names
158  // for registers.
159  if (MI->getOperand(OpNum).getReg() == AVR::R31R30) {
160  O << "Z";
161  } else {
162  assert(MI->getOperand(OpNum).getReg() == AVR::R29R28 &&
163  "Wrong register class for memory operand.");
164  O << "Y";
165  }
166 
167  // If NumOpRegs == 2, then we assume it is product of a FrameIndex expansion
168  // and the second operand is an Imm.
169  unsigned OpFlags = MI->getOperand(OpNum - 1).getImm();
170  unsigned NumOpRegs = InlineAsm::getNumOperandRegisters(OpFlags);
171 
172  if (NumOpRegs == 2) {
173  O << '+' << MI->getOperand(OpNum + 1).getImm();
174  }
175 
176  return false;
177 }
178 
180  AVRMCInstLower MCInstLowering(OutContext, *this);
181 
182  MCInst I;
183  MCInstLowering.lowerInstruction(*MI, I);
185 }
186 
188  MCContext &Ctx = OutContext;
189 
190  if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
191  bool IsProgMem = GV->getAddressSpace() == AVR::ProgramMemory;
192  if (IsProgMem) {
193  const MCExpr *Expr = MCSymbolRefExpr::create(getSymbol(GV), Ctx);
194  return AVRMCExpr::create(AVRMCExpr::VK_AVR_PM, Expr, false, Ctx);
195  }
196  }
197 
198  return AsmPrinter::lowerConstant(CV);
199 }
200 
202  if (!EmittedStructorSymbolAttrs) {
203  OutStreamer->emitRawComment(
204  " Emitting these undefined symbol references causes us to link the"
205  " libgcc code that runs our constructors/destructors");
206  OutStreamer->emitRawComment(" This matches GCC's behavior");
207 
208  MCSymbol *CtorsSym = OutContext.getOrCreateSymbol("__do_global_ctors");
209  OutStreamer->emitSymbolAttribute(CtorsSym, MCSA_Global);
210 
211  MCSymbol *DtorsSym = OutContext.getOrCreateSymbol("__do_global_dtors");
212  OutStreamer->emitSymbolAttribute(DtorsSym, MCSA_Global);
213 
214  EmittedStructorSymbolAttrs = true;
215  }
216 
218 }
219 
221  MCSymbol *DoCopyData = OutContext.getOrCreateSymbol("__do_copy_data");
222  MCSymbol *DoClearBss = OutContext.getOrCreateSymbol("__do_clear_bss");
223 
224  // FIXME: We can disable __do_copy_data if there are no static RAM variables.
225 
226  OutStreamer->emitRawComment(
227  " Declaring this symbol tells the CRT that it should");
228  OutStreamer->emitRawComment(
229  "copy all variables from program memory to RAM on startup");
230  OutStreamer->emitSymbolAttribute(DoCopyData, MCSA_Global);
231 
232  OutStreamer->emitRawComment(
233  " Declaring this symbol tells the CRT that it should");
234  OutStreamer->emitRawComment("clear the zeroed data section on startup");
235  OutStreamer->emitSymbolAttribute(DoClearBss, MCSA_Global);
236 
238 }
239 
240 } // end of namespace llvm
241 
244 }
AsmPrinter.h
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:103
MachineInstr.h
llvm::MachineOperand::MO_Immediate
@ MO_Immediate
Immediate operand.
Definition: MachineOperand.h:53
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1566
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:112
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:516
llvm::AsmPrinter::lowerConstant
virtual const MCExpr * lowerConstant(const Constant *CV)
Lower the specified LLVM Constant to an MCExpr.
Definition: AsmPrinter.cpp:2472
llvm::AVRAsmPrinter::emitInstruction
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
Definition: AVRAsmPrinter.cpp:179
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:1707
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:242
llvm::AVRAsmPrinter::doFinalization
bool doFinalization(Module &M) override
Shut down the asmprinter.
Definition: AVRAsmPrinter.cpp:220
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:1567
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:243
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:97
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:626
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:192
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:187
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::AsmPrinter::getSymbol
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:486
llvm::TargetMachine
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:79
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:1609
llvm::AsmPrinter::MF
MachineFunction * MF
The current machine function.
Definition: AsmPrinter.h:100
llvm::AsmPrinter::OutContext
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:92
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:3172
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:58
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
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:201
llvm::AsmPrinter
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:82
llvm::MCSymbolRefExpr::create
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:385
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:85
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:599