LLVM 20.0.0git
ARMTargetStreamer.cpp
Go to the documentation of this file.
1//===- ARMTargetStreamer.cpp - ARMTargetStreamer class --*- C++ -*---------===//
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 implements the ARMTargetStreamer class.
10//
11//===----------------------------------------------------------------------===//
12
15#include "llvm/MC/MCAsmInfo.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCStreamer.h"
21
22using namespace llvm;
23
24//
25// ARMTargetStreamer Implemenation
26//
27
29 : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {}
30
32
33// The constant pool handling is shared by all ARMTargetStreamer
34// implementations.
36 return ConstantPools->addEntry(Streamer, Expr, 4, Loc);
37}
38
40 ConstantPools->emitForCurrentSection(Streamer);
41 ConstantPools->clearCacheForCurrentSection(Streamer);
42}
43
44// finish() - write out any non-empty assembler constant pools.
46 ConstantPools->emitAll(Streamer);
47}
48
49// reset() - Reset any state
51
52void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {
53 unsigned Size;
54 char Buffer[4];
55 const bool LittleEndian = getStreamer().getContext().getAsmInfo()->isLittleEndian();
56
57 switch (Suffix) {
58 case '\0':
59 Size = 4;
60
61 for (unsigned II = 0, IE = Size; II != IE; II++) {
62 const unsigned I = LittleEndian ? (Size - II - 1) : II;
63 Buffer[Size - II - 1] = uint8_t(Inst >> I * CHAR_BIT);
64 }
65
66 break;
67 case 'n':
68 case 'w':
69 Size = (Suffix == 'n' ? 2 : 4);
70
71 // Thumb wide instructions are emitted as a pair of 16-bit words of the
72 // appropriate endianness.
73 for (unsigned II = 0, IE = Size; II != IE; II = II + 2) {
74 const unsigned I0 = LittleEndian ? II + 0 : II + 1;
75 const unsigned I1 = LittleEndian ? II + 1 : II + 0;
76 Buffer[Size - II - 2] = uint8_t(Inst >> I0 * CHAR_BIT);
77 Buffer[Size - II - 1] = uint8_t(Inst >> I1 * CHAR_BIT);
78 }
79
80 break;
81 default:
82 llvm_unreachable("Invalid Suffix");
83 }
85}
86
87// The remaining callbacks should be handled separately by each
88// streamer.
95void ARMTargetStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
96 int64_t Offset) {}
97void ARMTargetStreamer::emitMovSP(unsigned Reg, int64_t Offset) {}
100 bool isVector) {}
102 const SmallVectorImpl<uint8_t> &Opcodes) {
103}
107 StringRef String) {}
109 unsigned IntValue,
110 StringRef StringValue) {}
117 const MCSymbolRefExpr *SRE) {}
119
121void ARMTargetStreamer::emitARMWinCFISaveRegMask(unsigned Mask, bool Wide) {}
130
132 if (STI.getCPU() == "xscale")
134
135 if (STI.hasFeature(ARM::HasV9_0aOps))
136 return ARMBuildAttrs::v9_A;
137 else if (STI.hasFeature(ARM::HasV8Ops)) {
138 if (STI.hasFeature(ARM::FeatureRClass))
139 return ARMBuildAttrs::v8_R;
140 return ARMBuildAttrs::v8_A;
141 } else if (STI.hasFeature(ARM::HasV8_1MMainlineOps))
143 else if (STI.hasFeature(ARM::HasV8MMainlineOps))
145 else if (STI.hasFeature(ARM::HasV7Ops)) {
146 if (STI.hasFeature(ARM::FeatureMClass) && STI.hasFeature(ARM::FeatureDSP))
148 return ARMBuildAttrs::v7;
149 } else if (STI.hasFeature(ARM::HasV6T2Ops))
150 return ARMBuildAttrs::v6T2;
151 else if (STI.hasFeature(ARM::HasV8MBaselineOps))
153 else if (STI.hasFeature(ARM::HasV6MOps))
155 else if (STI.hasFeature(ARM::HasV6Ops))
156 return ARMBuildAttrs::v6;
157 else if (STI.hasFeature(ARM::HasV5TEOps))
158 return ARMBuildAttrs::v5TE;
159 else if (STI.hasFeature(ARM::HasV5TOps))
160 return ARMBuildAttrs::v5T;
161 else if (STI.hasFeature(ARM::HasV4TOps))
162 return ARMBuildAttrs::v4T;
163 else
164 return ARMBuildAttrs::v4;
165}
166
167static bool isV8M(const MCSubtargetInfo &STI) {
168 // Note that v8M Baseline is a subset of v6T2!
169 return (STI.hasFeature(ARM::HasV8MBaselineOps) &&
170 !STI.hasFeature(ARM::HasV6T2Ops)) ||
171 STI.hasFeature(ARM::HasV8MMainlineOps);
172}
173
174/// Emit the build attributes that only depend on the hardware that we expect
175// /to be available, and not on the ABI, or any source-language choices.
177 switchVendor("aeabi");
178
179 const StringRef CPUString = STI.getCPU();
180 if (!CPUString.empty() && !CPUString.starts_with("generic")) {
181 // FIXME: remove krait check when GNU tools support krait cpu
182 if (STI.hasFeature(ARM::ProcKrait)) {
184 // We consider krait as a "cortex-a9" + hwdiv CPU
185 // Enable hwdiv through ".arch_extension idiv"
186 if (STI.hasFeature(ARM::FeatureHWDivThumb) ||
187 STI.hasFeature(ARM::FeatureHWDivARM))
189 } else {
191 }
192 }
193
195
196 if (STI.hasFeature(ARM::FeatureAClass)) {
199 } else if (STI.hasFeature(ARM::FeatureRClass)) {
202 } else if (STI.hasFeature(ARM::FeatureMClass)) {
205 }
206
210
211 if (isV8M(STI)) {
214 } else if (STI.hasFeature(ARM::FeatureThumb2)) {
217 } else if (STI.hasFeature(ARM::HasV4TOps)) {
219 }
220
221 if (STI.hasFeature(ARM::FeatureNEON)) {
222 /* NEON is not exactly a VFP architecture, but GAS emit one of
223 * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */
224 if (STI.hasFeature(ARM::FeatureFPARMv8)) {
225 if (STI.hasFeature(ARM::FeatureCrypto))
226 emitFPU(ARM::FK_CRYPTO_NEON_FP_ARMV8);
227 else
228 emitFPU(ARM::FK_NEON_FP_ARMV8);
229 } else if (STI.hasFeature(ARM::FeatureVFP4))
230 emitFPU(ARM::FK_NEON_VFPV4);
231 else
232 emitFPU(STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_NEON_FP16
233 : ARM::FK_NEON);
234 // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture
235 if (STI.hasFeature(ARM::HasV8Ops))
237 STI.hasFeature(ARM::HasV8_1aOps)
240 } else {
241 if (STI.hasFeature(ARM::FeatureFPARMv8_D16_SP)) {
242 // FPv5 and FP-ARMv8 have the same instructions, so are modeled as one
243 // FPU, but there are two different names for it depending on the CPU.
244 if (STI.hasFeature(ARM::FeatureD32))
245 emitFPU(ARM::FK_FP_ARMV8);
246 else {
247 emitFPU(STI.hasFeature(ARM::FeatureFP64) ? ARM::FK_FPV5_D16
248 : ARM::FK_FPV5_SP_D16);
249 if (STI.hasFeature(ARM::HasMVEFloatOps))
251 }
252 } else if (STI.hasFeature(ARM::FeatureVFP4_D16_SP))
253 emitFPU(STI.hasFeature(ARM::FeatureD32)
254 ? ARM::FK_VFPV4
255 : (STI.hasFeature(ARM::FeatureFP64) ? ARM::FK_VFPV4_D16
256 : ARM::FK_FPV4_SP_D16));
257 else if (STI.hasFeature(ARM::FeatureVFP3_D16_SP))
258 emitFPU(
259 STI.hasFeature(ARM::FeatureD32)
260 // +d32
261 ? (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3_FP16
262 : ARM::FK_VFPV3)
263 // -d32
264 : (STI.hasFeature(ARM::FeatureFP64)
265 ? (STI.hasFeature(ARM::FeatureFP16)
266 ? ARM::FK_VFPV3_D16_FP16
267 : ARM::FK_VFPV3_D16)
268 : (STI.hasFeature(ARM::FeatureFP16) ? ARM::FK_VFPV3XD_FP16
269 : ARM::FK_VFPV3XD)));
270 else if (STI.hasFeature(ARM::FeatureVFP2_SP))
271 emitFPU(ARM::FK_VFPV2);
272 }
273
274 // ABI_HardFP_use attribute to indicate single precision FP.
275 if (STI.hasFeature(ARM::FeatureVFP2_SP) && !STI.hasFeature(ARM::FeatureFP64))
278
279 if (STI.hasFeature(ARM::FeatureFP16))
281
282 if (STI.hasFeature(ARM::FeatureMP))
284
285 if (STI.hasFeature(ARM::HasMVEFloatOps))
287 else if (STI.hasFeature(ARM::HasMVEIntegerOps))
289
290 // Hardware divide in ARM mode is part of base arch, starting from ARMv8.
291 // If only Thumb hwdiv is present, it must also be in base arch (ARMv7-R/M).
292 // It is not possible to produce DisallowDIV: if hwdiv is present in the base
293 // arch, supplying -hwdiv downgrades the effective arch, via ClearImpliedBits.
294 // AllowDIVExt is only emitted if hwdiv isn't available in the base arch;
295 // otherwise, the default value (AllowDIVIfExists) applies.
296 if (STI.hasFeature(ARM::FeatureHWDivARM) && !STI.hasFeature(ARM::HasV8Ops))
298
299 if (STI.hasFeature(ARM::FeatureDSP) && isV8M(STI))
301
302 if (STI.hasFeature(ARM::FeatureStrictAlign))
305 else
308
309 if (STI.hasFeature(ARM::FeatureTrustZone) &&
310 STI.hasFeature(ARM::FeatureVirtualization))
313 else if (STI.hasFeature(ARM::FeatureTrustZone))
315 else if (STI.hasFeature(ARM::FeatureVirtualization))
318
319 if (STI.hasFeature(ARM::FeaturePACBTI)) {
322 }
323}
324
327 const Triple &TT = STI.getTargetTriple();
328 if (TT.isOSBinFormatELF())
330 if (TT.isOSBinFormatCOFF())
332 return new ARMTargetStreamer(S);
333}
static bool isV8M(const MCSubtargetInfo &STI)
static ARMBuildAttrs::CPUArch getArchForCPU(const MCSubtargetInfo &STI)
uint64_t Size
#define I(x, y, z)
Definition: MD5.cpp:58
uint64_t IntrinsicInst * II
virtual void emitUnwindRaw(int64_t StackOffset, const SmallVectorImpl< uint8_t > &Opcodes)
~ARMTargetStreamer() override
void emitTargetAttributes(const MCSubtargetInfo &STI)
Emit the build attributes that only depend on the hardware that we expect.
virtual void reset()
Reset any state between object emissions, i.e.
virtual void annotateTLSDescriptorSequence(const MCSymbolRefExpr *SRE)
virtual void finishAttributeSection()
ARMTargetStreamer(MCStreamer &S)
virtual void emitARMWinCFISaveSP(unsigned Reg)
virtual void emitPersonalityIndex(unsigned Index)
virtual void emitInst(uint32_t Inst, char Suffix='\0')
virtual void emitARMWinCFISaveLR(unsigned Offset)
virtual void emitArchExtension(uint64_t ArchExt)
virtual void emitRegSave(const SmallVectorImpl< unsigned > &RegList, bool isVector)
virtual void emitTextAttribute(unsigned Attribute, StringRef String)
virtual void emitARMWinCFIAllocStack(unsigned Size, bool Wide)
virtual void emitMovSP(unsigned Reg, int64_t Offset=0)
virtual void emitARMWinCFICustom(unsigned Opcode)
virtual void emitARMWinCFISaveRegMask(unsigned Mask, bool Wide)
virtual void emitARMWinCFIEpilogEnd()
virtual void emitARMWinCFIPrologEnd(bool Fragment)
virtual void switchVendor(StringRef Vendor)
virtual void emitPersonality(const MCSymbol *Personality)
virtual void emitObjectArch(ARM::ArchKind Arch)
const MCExpr * addConstantPoolEntry(const MCExpr *, SMLoc Loc)
Callback used to implement the ldr= pseudo.
virtual void emitIntTextAttribute(unsigned Attribute, unsigned IntValue, StringRef StringValue="")
virtual void emitThumbSet(MCSymbol *Symbol, const MCExpr *Value)
virtual void emitFPU(ARM::FPUKind FPU)
virtual void emitARMWinCFISaveFRegs(unsigned First, unsigned Last)
virtual void emitARMWinCFIEpilogStart(unsigned Condition)
virtual void emitPad(int64_t Offset)
void emitCurrentConstantPool()
Callback used to implement the .ltorg directive.
virtual void emitAttribute(unsigned Attribute, unsigned Value)
virtual void emitARMWinCFINop(bool Wide)
virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset=0)
void emitConstantPools() override
virtual void emitArch(ARM::ArchKind Arch)
bool isLittleEndian() const
True if the target is little endian.
Definition: MCAsmInfo.h:527
const MCAsmInfo * getAsmInfo() const
Definition: MCContext.h:412
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
Streaming machine code generation interface.
Definition: MCStreamer.h:213
MCContext & getContext() const
Definition: MCStreamer.h:300
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const Triple & getTargetTriple() const
StringRef getCPU() const
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:188
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
Target specific streamer interface.
Definition: MCStreamer.h:94
MCStreamer & getStreamer()
Definition: MCStreamer.h:102
MCStreamer & Streamer
Definition: MCStreamer.h:96
Represents a location in source code.
Definition: SMLoc.h:23
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
StackOffset holds a fixed and a scalable offset in bytes.
Definition: TypeSize.h:33
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:250
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
LLVM Value Representation.
Definition: Value.h:74
#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:480
MCTargetStreamer * createARMObjectTargetELFStreamer(MCStreamer &S)
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
MCTargetStreamer * createARMObjectTargetWinCOFFStreamer(MCStreamer &S)
MCTargetStreamer * createARMObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI)