|
12 | 12 | #include "MCTargetDesc/AArch64FixupKinds.h"
|
13 | 13 | #include "llvm/ADT/Triple.h"
|
14 | 14 | #include "llvm/MC/MCAsmBackend.h"
|
| 15 | +#include "llvm/MC/MCContext.h" |
15 | 16 | #include "llvm/MC/MCDirectives.h"
|
16 | 17 | #include "llvm/MC/MCELFObjectWriter.h"
|
17 | 18 | #include "llvm/MC/MCFixupKindInfo.h"
|
@@ -134,69 +135,83 @@ static unsigned AdrImmBits(unsigned Value) {
|
134 | 135 | return (hi19 << 5) | (lo2 << 29);
|
135 | 136 | }
|
136 | 137 |
|
137 |
| -static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) { |
| 138 | +static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, |
| 139 | + MCContext *Ctx) { |
| 140 | + unsigned Kind = Fixup.getKind(); |
138 | 141 | int64_t SignedValue = static_cast<int64_t>(Value);
|
139 | 142 | switch (Kind) {
|
140 | 143 | default:
|
141 | 144 | llvm_unreachable("Unknown fixup kind!");
|
142 | 145 | case AArch64::fixup_aarch64_pcrel_adr_imm21:
|
143 |
| - if (SignedValue > 2097151 || SignedValue < -2097152) |
144 |
| - report_fatal_error("fixup value out of range"); |
| 146 | + if (Ctx && (SignedValue > 2097151 || SignedValue < -2097152)) |
| 147 | + Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); |
145 | 148 | return AdrImmBits(Value & 0x1fffffULL);
|
146 | 149 | case AArch64::fixup_aarch64_pcrel_adrp_imm21:
|
147 | 150 | return AdrImmBits((Value & 0x1fffff000ULL) >> 12);
|
148 | 151 | case AArch64::fixup_aarch64_ldr_pcrel_imm19:
|
149 | 152 | case AArch64::fixup_aarch64_pcrel_branch19:
|
150 | 153 | // Signed 21-bit immediate
|
151 | 154 | if (SignedValue > 2097151 || SignedValue < -2097152)
|
152 |
| - report_fatal_error("fixup value out of range"); |
| 155 | + if (Ctx) Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); |
| 156 | + if (Ctx && (Value & 0x3)) |
| 157 | + Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned"); |
153 | 158 | // Low two bits are not encoded.
|
154 | 159 | return (Value >> 2) & 0x7ffff;
|
155 | 160 | case AArch64::fixup_aarch64_add_imm12:
|
156 | 161 | case AArch64::fixup_aarch64_ldst_imm12_scale1:
|
157 | 162 | // Unsigned 12-bit immediate
|
158 |
| - if (Value >= 0x1000) |
159 |
| - report_fatal_error("invalid imm12 fixup value"); |
| 163 | + if (Ctx && Value >= 0x1000) |
| 164 | + Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); |
160 | 165 | return Value;
|
161 | 166 | case AArch64::fixup_aarch64_ldst_imm12_scale2:
|
162 | 167 | // Unsigned 12-bit immediate which gets multiplied by 2
|
163 |
| - if (Value & 1 || Value >= 0x2000) |
164 |
| - report_fatal_error("invalid imm12 fixup value"); |
| 168 | + if (Ctx && (Value >= 0x2000)) |
| 169 | + Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); |
| 170 | + if (Ctx && (Value & 0x1)) |
| 171 | + Ctx->reportError(Fixup.getLoc(), "fixup must be 2-byte aligned"); |
165 | 172 | return Value >> 1;
|
166 | 173 | case AArch64::fixup_aarch64_ldst_imm12_scale4:
|
167 | 174 | // Unsigned 12-bit immediate which gets multiplied by 4
|
168 |
| - if (Value & 3 || Value >= 0x4000) |
169 |
| - report_fatal_error("invalid imm12 fixup value"); |
| 175 | + if (Ctx && (Value >= 0x4000)) |
| 176 | + Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); |
| 177 | + if (Ctx && (Value & 0x3)) |
| 178 | + Ctx->reportError(Fixup.getLoc(), "fixup must be 4-byte aligned"); |
170 | 179 | return Value >> 2;
|
171 | 180 | case AArch64::fixup_aarch64_ldst_imm12_scale8:
|
172 | 181 | // Unsigned 12-bit immediate which gets multiplied by 8
|
173 |
| - if (Value & 7 || Value >= 0x8000) |
174 |
| - report_fatal_error("invalid imm12 fixup value"); |
| 182 | + if (Ctx && (Value >= 0x8000)) |
| 183 | + Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); |
| 184 | + if (Ctx && (Value & 0x7)) |
| 185 | + Ctx->reportError(Fixup.getLoc(), "fixup must be 8-byte aligned"); |
175 | 186 | return Value >> 3;
|
176 | 187 | case AArch64::fixup_aarch64_ldst_imm12_scale16:
|
177 | 188 | // Unsigned 12-bit immediate which gets multiplied by 16
|
178 |
| - if (Value & 15 || Value >= 0x10000) |
179 |
| - report_fatal_error("invalid imm12 fixup value"); |
| 189 | + if (Ctx && (Value >= 0x10000)) |
| 190 | + Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); |
| 191 | + if (Ctx && (Value & 0xf)) |
| 192 | + Ctx->reportError(Fixup.getLoc(), "fixup must be 16-byte aligned"); |
180 | 193 | return Value >> 4;
|
181 | 194 | case AArch64::fixup_aarch64_movw:
|
182 |
| - report_fatal_error("no resolvable MOVZ/MOVK fixups supported yet"); |
| 195 | + if (Ctx) |
| 196 | + Ctx->reportError(Fixup.getLoc(), |
| 197 | + "no resolvable MOVZ/MOVK fixups supported yet"); |
183 | 198 | return Value;
|
184 | 199 | case AArch64::fixup_aarch64_pcrel_branch14:
|
185 | 200 | // Signed 16-bit immediate
|
186 |
| - if (SignedValue > 32767 || SignedValue < -32768) |
187 |
| - report_fatal_error("fixup value out of range"); |
| 201 | + if (Ctx && (SignedValue > 32767 || SignedValue < -32768)) |
| 202 | + Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); |
188 | 203 | // Low two bits are not encoded (4-byte alignment assumed).
|
189 |
| - if (Value & 0x3) |
190 |
| - report_fatal_error("fixup not sufficiently aligned"); |
| 204 | + if (Ctx && (Value & 0x3)) |
| 205 | + Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned"); |
191 | 206 | return (Value >> 2) & 0x3fff;
|
192 | 207 | case AArch64::fixup_aarch64_pcrel_branch26:
|
193 | 208 | case AArch64::fixup_aarch64_pcrel_call26:
|
194 | 209 | // Signed 28-bit immediate
|
195 |
| - if (SignedValue > 134217727 || SignedValue < -134217728) |
196 |
| - report_fatal_error("fixup value out of range"); |
| 210 | + if (Ctx && (SignedValue > 134217727 || SignedValue < -134217728)) |
| 211 | + Ctx->reportError(Fixup.getLoc(), "fixup value out of range"); |
197 | 212 | // Low two bits are not encoded (4-byte alignment assumed).
|
198 |
| - if (Value & 0x3) |
199 |
| - report_fatal_error("fixup not sufficiently aligned"); |
| 213 | + if (Ctx && (Value & 0x3)) |
| 214 | + Ctx->reportError(Fixup.getLoc(), "fixup not sufficiently aligned"); |
200 | 215 | return (Value >> 2) & 0x3ffffff;
|
201 | 216 | case FK_Data_1:
|
202 | 217 | case FK_Data_2:
|
@@ -253,7 +268,7 @@ void AArch64AsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
|
253 | 268 | return; // Doesn't change encoding.
|
254 | 269 | MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
|
255 | 270 | // Apply any target-specific value adjustments.
|
256 |
| - Value = adjustFixupValue(Fixup.getKind(), Value); |
| 271 | + Value = adjustFixupValue(Fixup, Value, nullptr); |
257 | 272 |
|
258 | 273 | // Shift the value into position.
|
259 | 274 | Value <<= Info.TargetOffset;
|
@@ -544,6 +559,12 @@ void ELFAArch64AsmBackend::processFixupValue(
|
544 | 559 | // to the linker -- a relocation!
|
545 | 560 | if ((uint32_t)Fixup.getKind() == AArch64::fixup_aarch64_pcrel_adrp_imm21)
|
546 | 561 | IsResolved = false;
|
| 562 | + |
| 563 | + // Try to get the encoded value for the fixup as-if we're mapping it into |
| 564 | + // the instruction. This allows adjustFixupValue() to issue a diagnostic |
| 565 | + // if the value is invalid. |
| 566 | + if (IsResolved) |
| 567 | + (void)adjustFixupValue(Fixup, Value, &Asm.getContext()); |
547 | 568 | }
|
548 | 569 |
|
549 | 570 | }
|
|
0 commit comments