LLVM 22.0.0git
XtensaAsmBackend.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
12#include "llvm/MC/MCAssembler.h"
13#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCInst.h"
18#include "llvm/MC/MCValue.h"
20
21using namespace llvm;
22
23namespace llvm {
25}
26namespace {
27class XtensaAsmBackend : public MCAsmBackend {
28 uint8_t OSABI;
29 bool IsLittleEndian;
30
31public:
32 XtensaAsmBackend(uint8_t osABI, bool isLE)
33 : MCAsmBackend(llvm::endianness::little), OSABI(osABI),
34 IsLittleEndian(isLE) {}
35
36 MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
37 std::optional<bool> evaluateFixup(const MCFragment &, MCFixup &, MCValue &,
38 uint64_t &) override;
39 void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
40 uint8_t *Data, uint64_t Value, bool IsResolved) override;
41 bool writeNopData(raw_ostream &OS, uint64_t Count,
42 const MCSubtargetInfo *STI) const override;
43
44 std::unique_ptr<MCObjectTargetWriter> createObjectTargetWriter() const override {
45 return createXtensaObjectWriter(OSABI, IsLittleEndian);
46 }
47};
48} // namespace
49
50MCFixupKindInfo XtensaAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
51 const static MCFixupKindInfo Infos[Xtensa::NumTargetFixupKinds] = {
52 // name offset bits flags
53 {"fixup_xtensa_branch_6", 0, 16, 0},
54 {"fixup_xtensa_branch_8", 16, 8, 0},
55 {"fixup_xtensa_branch_12", 12, 12, 0},
56 {"fixup_xtensa_jump_18", 6, 18, 0},
57 {"fixup_xtensa_call_18", 6, 18, 0},
58 {"fixup_xtensa_l32r_16", 8, 16, 0},
59 {"fixup_xtensa_loop_8", 16, 8, 0},
60 };
61
62 if (Kind < FirstTargetFixupKind)
65 "Invalid kind!");
66 return Infos[Kind - FirstTargetFixupKind];
67}
68
70 MCContext &Ctx) {
71 unsigned Kind = Fixup.getKind();
72 switch (Kind) {
73 default:
74 llvm_unreachable("Unknown fixup kind!");
75 case FK_Data_1:
76 case FK_Data_2:
77 case FK_Data_4:
78 case FK_Data_8:
79 return Value;
81 if (!Value)
82 return 0;
83 Value -= 4;
84 if (!isUInt<6>(Value))
85 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
86 unsigned Hi2 = (Value >> 4) & 0x3;
87 unsigned Lo4 = Value & 0xf;
88 return (Hi2 << 4) | (Lo4 << 12);
89 }
91 Value -= 4;
92 if (!isInt<8>(Value))
93 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
94 return (Value & 0xff);
96 Value -= 4;
97 if (!isInt<12>(Value))
98 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
99 return (Value & 0xfff);
101 Value -= 4;
102 if (!isInt<18>(Value))
103 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
104 return (Value & 0x3ffff);
106 Value -= 4;
107 if (!isInt<20>(Value))
108 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
109 if (Value & 0x3)
110 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
111 return (Value & 0xffffc) >> 2;
113 Value -= 4;
114 if (!isUInt<8>(Value))
115 Ctx.reportError(Fixup.getLoc(), "loop fixup value out of range");
116 return (Value & 0xff);
118 unsigned Offset = Fixup.getOffset();
119 if (Offset & 0x3)
120 Value -= 4;
121 if (!isInt<18>(Value) && (Value & 0x20000))
122 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
123 if (Value & 0x3)
124 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned");
125 return (Value & 0x3fffc) >> 2;
126 }
127}
128
129static unsigned getSize(unsigned Kind) {
130 switch (Kind) {
131 default:
132 return 3;
133 case FK_Data_4:
134 return 4;
136 return 2;
137 }
138}
139
140std::optional<bool> XtensaAsmBackend::evaluateFixup(const MCFragment &F,
142 uint64_t &Value) {
143 // For a few PC-relative fixups, offsets need to be aligned down. We
144 // compensate here because the default handler's `Value` decrement doesn't
145 // account for this alignment.
146 switch (Fixup.getKind()) {
149 Value = (Asm->getFragmentOffset(F) + Fixup.getOffset()) % 4;
150 }
151 return {};
152}
153
154void XtensaAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
155 const MCValue &Target, uint8_t *Data,
156 uint64_t Value, bool IsResolved) {
157 maybeAddReloc(F, Fixup, Target, Value, IsResolved);
158 MCContext &Ctx = getContext();
159 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
160
162
163 // Shift the value into position.
164 Value <<= Info.TargetOffset;
165
166 if (!Value)
167 return; // Doesn't change encoding.
168
169 unsigned FullSize = getSize(Fixup.getKind());
170
171 for (unsigned i = 0; i != FullSize; ++i) {
172 Data[i] |= uint8_t((Value >> (i * 8)) & 0xff);
173 }
174}
175
176bool XtensaAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
177 const MCSubtargetInfo *STI) const {
178 uint64_t NumNops24b = Count / 3;
179
180 for (uint64_t i = 0; i != NumNops24b; ++i) {
181 // Currently just little-endian machine supported,
182 // but probably big-endian will be also implemented in future
183 if (IsLittleEndian) {
184 OS.write("\xf0", 1);
185 OS.write("\x20", 1);
186 OS.write("\0x00", 1);
187 } else {
188 report_fatal_error("Big-endian mode currently is not supported!");
189 }
190 Count -= 3;
191 }
192
193 // TODO maybe function should return error if (Count > 0)
194 switch (Count) {
195 default:
196 break;
197 case 1:
198 OS.write("\0", 1);
199 break;
200 case 2:
201 // NOP.N instruction
202 OS.write("\x3d", 1);
203 OS.write("\xf0", 1);
204 break;
205 }
206
207 return true;
208}
209
211 const MCSubtargetInfo &STI,
212 const MCRegisterInfo &MRI,
213 const MCTargetOptions &Options) {
214 uint8_t OSABI =
216 return new XtensaAsmBackend(OSABI, true);
217}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
static LVOptions Options
Definition: LVOptions.cpp:25
#define F(x, y, z)
Definition: MD5.cpp:55
PowerPC TLS Dynamic Call Fixup
raw_pwrite_stream & OS
static unsigned getSize(unsigned Kind)
static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, MCContext &Ctx)
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:55
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
Context object for machine code objects.
Definition: MCContext.h:83
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1115
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:61
Base class for classes that define behaviour that is specific to both the target and the object forma...
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
Target - Wrapper for Target specific information.
OSType getOS() const
Get the parsed operating system type of this triple.
Definition: Triple.h:417
LLVM Value Representation.
Definition: Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
raw_ostream & write(unsigned char C)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
@ FirstTargetFixupKind
Definition: MCFixup.h:44
@ FK_Data_8
A eight-byte fixup.
Definition: MCFixup.h:37
@ FK_Data_1
A one-byte fixup.
Definition: MCFixup.h:34
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:36
@ FK_Data_2
A two-byte fixup.
Definition: MCFixup.h:35
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
std::unique_ptr< MCObjectTargetWriter > createXtensaObjectWriter(uint8_t OSABI, bool IsLittleEndian)
endianness
Definition: bit.h:71
MCAsmBackend * createXtensaAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
Target independent information on a fixup kind.
Definition: MCAsmBackend.h:38