1 | //=====-- AArch64MCAsmInfo.h - AArch64 asm properties ---------*- 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 contains the declaration of the AArch64MCAsmInfo class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCASMINFO_H |
14 | #define LLVM_LIB_TARGET_AARCH64_MCTARGETDESC_AARCH64MCASMINFO_H |
15 | |
16 | #include "Utils/AArch64BaseInfo.h" |
17 | #include "llvm/MC/MCAsmInfoCOFF.h" |
18 | #include "llvm/MC/MCAsmInfoDarwin.h" |
19 | #include "llvm/MC/MCAsmInfoELF.h" |
20 | #include "llvm/MC/MCExpr.h" |
21 | #include "llvm/Support/Casting.h" |
22 | |
23 | namespace llvm { |
24 | class MCStreamer; |
25 | class MCValue; |
26 | class Triple; |
27 | |
28 | struct AArch64MCAsmInfoDarwin : public MCAsmInfoDarwin { |
29 | explicit AArch64MCAsmInfoDarwin(bool IsILP32); |
30 | const MCExpr * |
31 | getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding, |
32 | MCStreamer &Streamer) const override; |
33 | void printSpecifierExpr(raw_ostream &OS, |
34 | const MCSpecifierExpr &Expr) const override; |
35 | bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res, |
36 | const MCAssembler *Asm) const override; |
37 | }; |
38 | |
39 | struct AArch64MCAsmInfoELF : public MCAsmInfoELF { |
40 | explicit AArch64MCAsmInfoELF(const Triple &T); |
41 | void printSpecifierExpr(raw_ostream &OS, |
42 | const MCSpecifierExpr &Expr) const override; |
43 | bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res, |
44 | const MCAssembler *Asm) const override; |
45 | }; |
46 | |
47 | struct AArch64MCAsmInfoMicrosoftCOFF : public MCAsmInfoMicrosoft { |
48 | explicit AArch64MCAsmInfoMicrosoftCOFF(); |
49 | void printSpecifierExpr(raw_ostream &OS, |
50 | const MCSpecifierExpr &Expr) const override; |
51 | bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res, |
52 | const MCAssembler *Asm) const override; |
53 | }; |
54 | |
55 | struct AArch64MCAsmInfoGNUCOFF : public MCAsmInfoGNUCOFF { |
56 | explicit AArch64MCAsmInfoGNUCOFF(); |
57 | void printSpecifierExpr(raw_ostream &OS, |
58 | const MCSpecifierExpr &Expr) const override; |
59 | bool evaluateAsRelocatableImpl(const MCSpecifierExpr &Expr, MCValue &Res, |
60 | const MCAssembler *Asm) const override; |
61 | }; |
62 | |
63 | namespace AArch64 { |
64 | using Specifier = uint16_t; |
65 | |
66 | enum { |
67 | // clang-format off |
68 | S_None = 0, |
69 | // Symbol locations specifying (roughly speaking) what calculation should be |
70 | // performed to construct the final address for the relocated |
71 | // symbol. E.g. direct, via the GOT, ... |
72 | S_ABS = 0x001, |
73 | S_SABS = 0x002, |
74 | S_PREL = 0x003, |
75 | S_GOT = 0x004, |
76 | S_DTPREL = 0x005, |
77 | S_GOTTPREL = 0x006, |
78 | S_TPREL = 0x007, |
79 | S_TLSDESC = 0x008, |
80 | S_SECREL = 0x009, |
81 | S_AUTH = 0x00a, |
82 | S_AUTHADDR = 0x00b, |
83 | S_GOT_AUTH = 0x00c, |
84 | S_TLSDESC_AUTH = 0x00d, |
85 | S_SymLocBits = 0x00f, |
86 | |
87 | // Variants specifying which part of the final address calculation is |
88 | // used. E.g. the low 12 bits for an ADD/LDR, the middle 16 bits for a |
89 | // MOVZ/MOVK. |
90 | S_PAGE = 0x010, |
91 | S_PAGEOFF = 0x020, |
92 | S_HI12 = 0x030, |
93 | S_G0 = 0x040, |
94 | S_G1 = 0x050, |
95 | S_G2 = 0x060, |
96 | S_G3 = 0x070, |
97 | S_LO15 = 0x080, |
98 | S_AddressFragBits = 0x0f0, |
99 | |
100 | // Whether the final relocation is a checked one (where a linker should |
101 | // perform a range-check on the final address) or not. Note that this field |
102 | // is unfortunately sometimes omitted from the assembly syntax. E.g. :lo12: |
103 | // on its own is a non-checked relocation. We side with ELF on being |
104 | // explicit about this! |
105 | S_NC = 0x100, |
106 | |
107 | // Convenience definitions for referring to specific textual representations |
108 | // of relocation specifiers. Note that this means the "_NC" is sometimes |
109 | // omitted in line with assembly syntax here (S_LO12 rather than VK_LO12_NC |
110 | // since a user would write ":lo12:"). |
111 | S_CALL = S_ABS, |
112 | S_ABS_PAGE = S_ABS | S_PAGE, |
113 | S_ABS_PAGE_NC = S_ABS | S_PAGE | S_NC, |
114 | S_ABS_G3 = S_ABS | S_G3, |
115 | S_ABS_G2 = S_ABS | S_G2, |
116 | S_ABS_G2_S = S_SABS | S_G2, |
117 | S_ABS_G2_NC = S_ABS | S_G2 | S_NC, |
118 | S_ABS_G1 = S_ABS | S_G1, |
119 | S_ABS_G1_S = S_SABS | S_G1, |
120 | S_ABS_G1_NC = S_ABS | S_G1 | S_NC, |
121 | S_ABS_G0 = S_ABS | S_G0, |
122 | S_ABS_G0_S = S_SABS | S_G0, |
123 | S_ABS_G0_NC = S_ABS | S_G0 | S_NC, |
124 | S_LO12 = S_ABS | S_PAGEOFF | S_NC, |
125 | S_PREL_G3 = S_PREL | S_G3, |
126 | S_PREL_G2 = S_PREL | S_G2, |
127 | S_PREL_G2_NC = S_PREL | S_G2 | S_NC, |
128 | S_PREL_G1 = S_PREL | S_G1, |
129 | S_PREL_G1_NC = S_PREL | S_G1 | S_NC, |
130 | S_PREL_G0 = S_PREL | S_G0, |
131 | S_PREL_G0_NC = S_PREL | S_G0 | S_NC, |
132 | S_GOT_LO12 = S_GOT | S_PAGEOFF | S_NC, |
133 | S_GOT_PAGE = S_GOT | S_PAGE, |
134 | S_GOT_PAGE_LO15 = S_GOT | S_LO15 | S_NC, |
135 | S_GOT_AUTH_LO12 = S_GOT_AUTH | S_PAGEOFF | S_NC, |
136 | S_GOT_AUTH_PAGE = S_GOT_AUTH | S_PAGE, |
137 | S_DTPREL_G2 = S_DTPREL | S_G2, |
138 | S_DTPREL_G1 = S_DTPREL | S_G1, |
139 | S_DTPREL_G1_NC = S_DTPREL | S_G1 | S_NC, |
140 | S_DTPREL_G0 = S_DTPREL | S_G0, |
141 | S_DTPREL_G0_NC = S_DTPREL | S_G0 | S_NC, |
142 | S_DTPREL_HI12 = S_DTPREL | S_HI12, |
143 | S_DTPREL_LO12 = S_DTPREL | S_PAGEOFF, |
144 | S_DTPREL_LO12_NC = S_DTPREL | S_PAGEOFF | S_NC, |
145 | S_GOTTPREL_PAGE = S_GOTTPREL | S_PAGE, |
146 | S_GOTTPREL_LO12_NC = S_GOTTPREL | S_PAGEOFF | S_NC, |
147 | S_GOTTPREL_G1 = S_GOTTPREL | S_G1, |
148 | S_GOTTPREL_G0_NC = S_GOTTPREL | S_G0 | S_NC, |
149 | S_TPREL_G2 = S_TPREL | S_G2, |
150 | S_TPREL_G1 = S_TPREL | S_G1, |
151 | S_TPREL_G1_NC = S_TPREL | S_G1 | S_NC, |
152 | S_TPREL_G0 = S_TPREL | S_G0, |
153 | S_TPREL_G0_NC = S_TPREL | S_G0 | S_NC, |
154 | S_TPREL_HI12 = S_TPREL | S_HI12, |
155 | S_TPREL_LO12 = S_TPREL | S_PAGEOFF, |
156 | S_TPREL_LO12_NC = S_TPREL | S_PAGEOFF | S_NC, |
157 | S_TLSDESC_LO12 = S_TLSDESC | S_PAGEOFF, |
158 | S_TLSDESC_PAGE = S_TLSDESC | S_PAGE, |
159 | S_TLSDESC_AUTH_LO12 = S_TLSDESC_AUTH | S_PAGEOFF, |
160 | S_TLSDESC_AUTH_PAGE = S_TLSDESC_AUTH | S_PAGE, |
161 | S_SECREL_LO12 = S_SECREL | S_PAGEOFF, |
162 | S_SECREL_HI12 = S_SECREL | S_HI12, |
163 | |
164 | // ELF relocation specifiers in data directives: |
165 | S_PLT = 0x400, |
166 | S_GOTPCREL, |
167 | |
168 | // Mach-O @ relocation specifiers: |
169 | S_MACHO_GOT, |
170 | S_MACHO_GOTPAGE, |
171 | S_MACHO_GOTPAGEOFF, |
172 | S_MACHO_PAGE, |
173 | S_MACHO_PAGEOFF, |
174 | S_MACHO_TLVP, |
175 | S_MACHO_TLVPPAGE, |
176 | S_MACHO_TLVPPAGEOFF, |
177 | |
178 | S_INVALID = 0xfff |
179 | // clang-format on |
180 | }; |
181 | |
182 | /// Return the string representation of the ELF relocation specifier |
183 | /// (e.g. ":got:", ":lo12:"). |
184 | StringRef getSpecifierName(const MCSpecifierExpr &Expr); |
185 | |
186 | inline Specifier getSymbolLoc(Specifier S) { |
187 | return static_cast<Specifier>(S & AArch64::S_SymLocBits); |
188 | } |
189 | |
190 | inline Specifier getAddressFrag(Specifier S) { |
191 | return static_cast<Specifier>(S & AArch64::S_AddressFragBits); |
192 | } |
193 | |
194 | inline bool isNotChecked(Specifier S) { return S & AArch64::S_NC; } |
195 | } // namespace AArch64 |
196 | |
197 | class AArch64AuthMCExpr final : public MCSpecifierExpr { |
198 | uint16_t Discriminator; |
199 | AArch64PACKey::ID Key; |
200 | |
201 | explicit AArch64AuthMCExpr(const MCExpr *Expr, uint16_t Discriminator, |
202 | AArch64PACKey::ID Key, bool HasAddressDiversity) |
203 | : MCSpecifierExpr(Expr, HasAddressDiversity ? AArch64::S_AUTHADDR |
204 | : AArch64::S_AUTH), |
205 | Discriminator(Discriminator), Key(Key) {} |
206 | |
207 | public: |
208 | static const AArch64AuthMCExpr * |
209 | create(const MCExpr *Expr, uint16_t Discriminator, AArch64PACKey::ID Key, |
210 | bool HasAddressDiversity, MCContext &Ctx); |
211 | |
212 | AArch64PACKey::ID getKey() const { return Key; } |
213 | uint16_t getDiscriminator() const { return Discriminator; } |
214 | bool hasAddressDiversity() const { |
215 | return getSpecifier() == AArch64::S_AUTHADDR; |
216 | } |
217 | |
218 | void print(raw_ostream &OS, const MCAsmInfo *MAI) const; |
219 | |
220 | static bool classof(const MCExpr *E) { |
221 | auto *SE = dyn_cast<MCSpecifierExpr>(Val: E); |
222 | return SE && (SE->getSpecifier() == AArch64::S_AUTH || |
223 | SE->getSpecifier() == AArch64::S_AUTHADDR); |
224 | } |
225 | }; |
226 | |
227 | } // namespace llvm |
228 | |
229 | #endif |
230 | |