| File: | build/source/llvm/lib/MC/MCExpr.cpp |
| Warning: | line 630, column 28 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | //===- MCExpr.cpp - Assembly Level Expression Implementation --------------===// | ||||||
| 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 | #include "llvm/MC/MCExpr.h" | ||||||
| 10 | #include "llvm/ADT/Statistic.h" | ||||||
| 11 | #include "llvm/ADT/StringSwitch.h" | ||||||
| 12 | #include "llvm/Config/llvm-config.h" | ||||||
| 13 | #include "llvm/MC/MCAsmBackend.h" | ||||||
| 14 | #include "llvm/MC/MCAsmInfo.h" | ||||||
| 15 | #include "llvm/MC/MCAsmLayout.h" | ||||||
| 16 | #include "llvm/MC/MCAssembler.h" | ||||||
| 17 | #include "llvm/MC/MCContext.h" | ||||||
| 18 | #include "llvm/MC/MCObjectWriter.h" | ||||||
| 19 | #include "llvm/MC/MCSymbol.h" | ||||||
| 20 | #include "llvm/MC/MCValue.h" | ||||||
| 21 | #include "llvm/Support/Casting.h" | ||||||
| 22 | #include "llvm/Support/Compiler.h" | ||||||
| 23 | #include "llvm/Support/Debug.h" | ||||||
| 24 | #include "llvm/Support/ErrorHandling.h" | ||||||
| 25 | #include "llvm/Support/raw_ostream.h" | ||||||
| 26 | #include <cassert> | ||||||
| 27 | #include <cstdint> | ||||||
| 28 | |||||||
| 29 | using namespace llvm; | ||||||
| 30 | |||||||
| 31 | #define DEBUG_TYPE"mcexpr" "mcexpr" | ||||||
| 32 | |||||||
| 33 | namespace { | ||||||
| 34 | namespace stats { | ||||||
| 35 | |||||||
| 36 | STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations")static llvm::Statistic MCExprEvaluate = {"mcexpr", "MCExprEvaluate" , "Number of MCExpr evaluations"}; | ||||||
| 37 | |||||||
| 38 | } // end namespace stats | ||||||
| 39 | } // end anonymous namespace | ||||||
| 40 | |||||||
| 41 | void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const { | ||||||
| 42 | switch (getKind()) { | ||||||
| 43 | case MCExpr::Target: | ||||||
| 44 | return cast<MCTargetExpr>(this)->printImpl(OS, MAI); | ||||||
| 45 | case MCExpr::Constant: { | ||||||
| 46 | auto Value = cast<MCConstantExpr>(*this).getValue(); | ||||||
| 47 | auto PrintInHex = cast<MCConstantExpr>(*this).useHexFormat(); | ||||||
| 48 | auto SizeInBytes = cast<MCConstantExpr>(*this).getSizeInBytes(); | ||||||
| 49 | if (Value < 0 && MAI && !MAI->supportsSignedData()) | ||||||
| 50 | PrintInHex = true; | ||||||
| 51 | if (PrintInHex) | ||||||
| 52 | switch (SizeInBytes) { | ||||||
| 53 | default: | ||||||
| 54 | OS << "0x" << Twine::utohexstr(Value); | ||||||
| 55 | break; | ||||||
| 56 | case 1: | ||||||
| 57 | OS << format("0x%02" PRIx64"l" "x", Value); | ||||||
| 58 | break; | ||||||
| 59 | case 2: | ||||||
| 60 | OS << format("0x%04" PRIx64"l" "x", Value); | ||||||
| 61 | break; | ||||||
| 62 | case 4: | ||||||
| 63 | OS << format("0x%08" PRIx64"l" "x", Value); | ||||||
| 64 | break; | ||||||
| 65 | case 8: | ||||||
| 66 | OS << format("0x%016" PRIx64"l" "x", Value); | ||||||
| 67 | break; | ||||||
| 68 | } | ||||||
| 69 | else | ||||||
| 70 | OS << Value; | ||||||
| 71 | return; | ||||||
| 72 | } | ||||||
| 73 | case MCExpr::SymbolRef: { | ||||||
| 74 | const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this); | ||||||
| 75 | const MCSymbol &Sym = SRE.getSymbol(); | ||||||
| 76 | // Parenthesize names that start with $ so that they don't look like | ||||||
| 77 | // absolute names. | ||||||
| 78 | bool UseParens = MAI && MAI->useParensForDollarSignNames() && !InParens && | ||||||
| 79 | !Sym.getName().empty() && Sym.getName()[0] == '$'; | ||||||
| 80 | |||||||
| 81 | if (UseParens) { | ||||||
| 82 | OS << '('; | ||||||
| 83 | Sym.print(OS, MAI); | ||||||
| 84 | OS << ')'; | ||||||
| 85 | } else | ||||||
| 86 | Sym.print(OS, MAI); | ||||||
| 87 | |||||||
| 88 | const MCSymbolRefExpr::VariantKind Kind = SRE.getKind(); | ||||||
| 89 | if (Kind != MCSymbolRefExpr::VK_None) { | ||||||
| 90 | if (MAI && MAI->useParensForSymbolVariant()) // ARM | ||||||
| 91 | OS << '(' << MCSymbolRefExpr::getVariantKindName(Kind) << ')'; | ||||||
| 92 | else | ||||||
| 93 | OS << '@' << MCSymbolRefExpr::getVariantKindName(Kind); | ||||||
| 94 | } | ||||||
| 95 | |||||||
| 96 | return; | ||||||
| 97 | } | ||||||
| 98 | |||||||
| 99 | case MCExpr::Unary: { | ||||||
| 100 | const MCUnaryExpr &UE = cast<MCUnaryExpr>(*this); | ||||||
| 101 | switch (UE.getOpcode()) { | ||||||
| 102 | case MCUnaryExpr::LNot: OS << '!'; break; | ||||||
| 103 | case MCUnaryExpr::Minus: OS << '-'; break; | ||||||
| 104 | case MCUnaryExpr::Not: OS << '~'; break; | ||||||
| 105 | case MCUnaryExpr::Plus: OS << '+'; break; | ||||||
| 106 | } | ||||||
| 107 | bool Binary = UE.getSubExpr()->getKind() == MCExpr::Binary; | ||||||
| 108 | if (Binary) OS << "("; | ||||||
| 109 | UE.getSubExpr()->print(OS, MAI); | ||||||
| 110 | if (Binary) OS << ")"; | ||||||
| 111 | return; | ||||||
| 112 | } | ||||||
| 113 | |||||||
| 114 | case MCExpr::Binary: { | ||||||
| 115 | const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this); | ||||||
| 116 | |||||||
| 117 | // Only print parens around the LHS if it is non-trivial. | ||||||
| 118 | if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) { | ||||||
| 119 | BE.getLHS()->print(OS, MAI); | ||||||
| 120 | } else { | ||||||
| 121 | OS << '('; | ||||||
| 122 | BE.getLHS()->print(OS, MAI); | ||||||
| 123 | OS << ')'; | ||||||
| 124 | } | ||||||
| 125 | |||||||
| 126 | switch (BE.getOpcode()) { | ||||||
| 127 | case MCBinaryExpr::Add: | ||||||
| 128 | // Print "X-42" instead of "X+-42". | ||||||
| 129 | if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) { | ||||||
| 130 | if (RHSC->getValue() < 0) { | ||||||
| 131 | OS << RHSC->getValue(); | ||||||
| 132 | return; | ||||||
| 133 | } | ||||||
| 134 | } | ||||||
| 135 | |||||||
| 136 | OS << '+'; | ||||||
| 137 | break; | ||||||
| 138 | case MCBinaryExpr::AShr: OS << ">>"; break; | ||||||
| 139 | case MCBinaryExpr::And: OS << '&'; break; | ||||||
| 140 | case MCBinaryExpr::Div: OS << '/'; break; | ||||||
| 141 | case MCBinaryExpr::EQ: OS << "=="; break; | ||||||
| 142 | case MCBinaryExpr::GT: OS << '>'; break; | ||||||
| 143 | case MCBinaryExpr::GTE: OS << ">="; break; | ||||||
| 144 | case MCBinaryExpr::LAnd: OS << "&&"; break; | ||||||
| 145 | case MCBinaryExpr::LOr: OS << "||"; break; | ||||||
| 146 | case MCBinaryExpr::LShr: OS << ">>"; break; | ||||||
| 147 | case MCBinaryExpr::LT: OS << '<'; break; | ||||||
| 148 | case MCBinaryExpr::LTE: OS << "<="; break; | ||||||
| 149 | case MCBinaryExpr::Mod: OS << '%'; break; | ||||||
| 150 | case MCBinaryExpr::Mul: OS << '*'; break; | ||||||
| 151 | case MCBinaryExpr::NE: OS << "!="; break; | ||||||
| 152 | case MCBinaryExpr::Or: OS << '|'; break; | ||||||
| 153 | case MCBinaryExpr::OrNot: OS << '!'; break; | ||||||
| 154 | case MCBinaryExpr::Shl: OS << "<<"; break; | ||||||
| 155 | case MCBinaryExpr::Sub: OS << '-'; break; | ||||||
| 156 | case MCBinaryExpr::Xor: OS << '^'; break; | ||||||
| 157 | } | ||||||
| 158 | |||||||
| 159 | // Only print parens around the LHS if it is non-trivial. | ||||||
| 160 | if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) { | ||||||
| 161 | BE.getRHS()->print(OS, MAI); | ||||||
| 162 | } else { | ||||||
| 163 | OS << '('; | ||||||
| 164 | BE.getRHS()->print(OS, MAI); | ||||||
| 165 | OS << ')'; | ||||||
| 166 | } | ||||||
| 167 | return; | ||||||
| 168 | } | ||||||
| 169 | } | ||||||
| 170 | |||||||
| 171 | llvm_unreachable("Invalid expression kind!")::llvm::llvm_unreachable_internal("Invalid expression kind!", "llvm/lib/MC/MCExpr.cpp", 171); | ||||||
| 172 | } | ||||||
| 173 | |||||||
| 174 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | ||||||
| 175 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) void MCExpr::dump() const { | ||||||
| 176 | dbgs() << *this; | ||||||
| 177 | dbgs() << '\n'; | ||||||
| 178 | } | ||||||
| 179 | #endif | ||||||
| 180 | |||||||
| 181 | /* *** */ | ||||||
| 182 | |||||||
| 183 | const MCBinaryExpr *MCBinaryExpr::create(Opcode Opc, const MCExpr *LHS, | ||||||
| 184 | const MCExpr *RHS, MCContext &Ctx, | ||||||
| 185 | SMLoc Loc) { | ||||||
| 186 | return new (Ctx) MCBinaryExpr(Opc, LHS, RHS, Loc); | ||||||
| 187 | } | ||||||
| 188 | |||||||
| 189 | const MCUnaryExpr *MCUnaryExpr::create(Opcode Opc, const MCExpr *Expr, | ||||||
| 190 | MCContext &Ctx, SMLoc Loc) { | ||||||
| 191 | return new (Ctx) MCUnaryExpr(Opc, Expr, Loc); | ||||||
| 192 | } | ||||||
| 193 | |||||||
| 194 | const MCConstantExpr *MCConstantExpr::create(int64_t Value, MCContext &Ctx, | ||||||
| 195 | bool PrintInHex, | ||||||
| 196 | unsigned SizeInBytes) { | ||||||
| 197 | return new (Ctx) MCConstantExpr(Value, PrintInHex, SizeInBytes); | ||||||
| 198 | } | ||||||
| 199 | |||||||
| 200 | /* *** */ | ||||||
| 201 | |||||||
| 202 | MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, | ||||||
| 203 | const MCAsmInfo *MAI, SMLoc Loc) | ||||||
| 204 | : MCExpr(MCExpr::SymbolRef, Loc, | ||||||
| 205 | encodeSubclassData(Kind, MAI->hasSubsectionsViaSymbols())), | ||||||
| 206 | Symbol(Symbol) { | ||||||
| 207 | assert(Symbol)(static_cast <bool> (Symbol) ? void (0) : __assert_fail ("Symbol", "llvm/lib/MC/MCExpr.cpp", 207, __extension__ __PRETTY_FUNCTION__ )); | ||||||
| 208 | } | ||||||
| 209 | |||||||
| 210 | const MCSymbolRefExpr *MCSymbolRefExpr::create(const MCSymbol *Sym, | ||||||
| 211 | VariantKind Kind, | ||||||
| 212 | MCContext &Ctx, SMLoc Loc) { | ||||||
| 213 | return new (Ctx) MCSymbolRefExpr(Sym, Kind, Ctx.getAsmInfo(), Loc); | ||||||
| 214 | } | ||||||
| 215 | |||||||
| 216 | const MCSymbolRefExpr *MCSymbolRefExpr::create(StringRef Name, VariantKind Kind, | ||||||
| 217 | MCContext &Ctx) { | ||||||
| 218 | return create(Ctx.getOrCreateSymbol(Name), Kind, Ctx); | ||||||
| 219 | } | ||||||
| 220 | |||||||
| 221 | StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { | ||||||
| 222 | switch (Kind) { | ||||||
| 223 | case VK_Invalid: return "<<invalid>>"; | ||||||
| 224 | case VK_None: return "<<none>>"; | ||||||
| 225 | |||||||
| 226 | case VK_DTPOFF: return "DTPOFF"; | ||||||
| 227 | case VK_DTPREL: return "DTPREL"; | ||||||
| 228 | case VK_GOT: return "GOT"; | ||||||
| 229 | case VK_GOTOFF: return "GOTOFF"; | ||||||
| 230 | case VK_GOTREL: return "GOTREL"; | ||||||
| 231 | case VK_PCREL: return "PCREL"; | ||||||
| 232 | case VK_GOTPCREL: return "GOTPCREL"; | ||||||
| 233 | case VK_GOTPCREL_NORELAX: return "GOTPCREL_NORELAX"; | ||||||
| 234 | case VK_GOTTPOFF: return "GOTTPOFF"; | ||||||
| 235 | case VK_INDNTPOFF: return "INDNTPOFF"; | ||||||
| 236 | case VK_NTPOFF: return "NTPOFF"; | ||||||
| 237 | case VK_GOTNTPOFF: return "GOTNTPOFF"; | ||||||
| 238 | case VK_PLT: return "PLT"; | ||||||
| 239 | case VK_TLSGD: return "TLSGD"; | ||||||
| 240 | case VK_TLSLD: return "TLSLD"; | ||||||
| 241 | case VK_TLSLDM: return "TLSLDM"; | ||||||
| 242 | case VK_TPOFF: return "TPOFF"; | ||||||
| 243 | case VK_TPREL: return "TPREL"; | ||||||
| 244 | case VK_TLSCALL: return "tlscall"; | ||||||
| 245 | case VK_TLSDESC: return "tlsdesc"; | ||||||
| 246 | case VK_TLVP: return "TLVP"; | ||||||
| 247 | case VK_TLVPPAGE: return "TLVPPAGE"; | ||||||
| 248 | case VK_TLVPPAGEOFF: return "TLVPPAGEOFF"; | ||||||
| 249 | case VK_PAGE: return "PAGE"; | ||||||
| 250 | case VK_PAGEOFF: return "PAGEOFF"; | ||||||
| 251 | case VK_GOTPAGE: return "GOTPAGE"; | ||||||
| 252 | case VK_GOTPAGEOFF: return "GOTPAGEOFF"; | ||||||
| 253 | case VK_SECREL: return "SECREL32"; | ||||||
| 254 | case VK_SIZE: return "SIZE"; | ||||||
| 255 | case VK_WEAKREF: return "WEAKREF"; | ||||||
| 256 | case VK_X86_ABS8: return "ABS8"; | ||||||
| 257 | case VK_X86_PLTOFF: return "PLTOFF"; | ||||||
| 258 | case VK_ARM_NONE: return "none"; | ||||||
| 259 | case VK_ARM_GOT_PREL: return "GOT_PREL"; | ||||||
| 260 | case VK_ARM_TARGET1: return "target1"; | ||||||
| 261 | case VK_ARM_TARGET2: return "target2"; | ||||||
| 262 | case VK_ARM_PREL31: return "prel31"; | ||||||
| 263 | case VK_ARM_SBREL: return "sbrel"; | ||||||
| 264 | case VK_ARM_TLSLDO: return "tlsldo"; | ||||||
| 265 | case VK_ARM_TLSDESCSEQ: return "tlsdescseq"; | ||||||
| 266 | case VK_AVR_NONE: return "none"; | ||||||
| 267 | case VK_AVR_LO8: return "lo8"; | ||||||
| 268 | case VK_AVR_HI8: return "hi8"; | ||||||
| 269 | case VK_AVR_HLO8: return "hlo8"; | ||||||
| 270 | case VK_AVR_DIFF8: return "diff8"; | ||||||
| 271 | case VK_AVR_DIFF16: return "diff16"; | ||||||
| 272 | case VK_AVR_DIFF32: return "diff32"; | ||||||
| 273 | case VK_AVR_PM: return "pm"; | ||||||
| 274 | case VK_PPC_LO: return "l"; | ||||||
| 275 | case VK_PPC_HI: return "h"; | ||||||
| 276 | case VK_PPC_HA: return "ha"; | ||||||
| 277 | case VK_PPC_HIGH: return "high"; | ||||||
| 278 | case VK_PPC_HIGHA: return "higha"; | ||||||
| 279 | case VK_PPC_HIGHER: return "higher"; | ||||||
| 280 | case VK_PPC_HIGHERA: return "highera"; | ||||||
| 281 | case VK_PPC_HIGHEST: return "highest"; | ||||||
| 282 | case VK_PPC_HIGHESTA: return "highesta"; | ||||||
| 283 | case VK_PPC_GOT_LO: return "got@l"; | ||||||
| 284 | case VK_PPC_GOT_HI: return "got@h"; | ||||||
| 285 | case VK_PPC_GOT_HA: return "got@ha"; | ||||||
| 286 | case VK_PPC_TOCBASE: return "tocbase"; | ||||||
| 287 | case VK_PPC_TOC: return "toc"; | ||||||
| 288 | case VK_PPC_TOC_LO: return "toc@l"; | ||||||
| 289 | case VK_PPC_TOC_HI: return "toc@h"; | ||||||
| 290 | case VK_PPC_TOC_HA: return "toc@ha"; | ||||||
| 291 | case VK_PPC_U: return "u"; | ||||||
| 292 | case VK_PPC_L: return "l"; | ||||||
| 293 | case VK_PPC_DTPMOD: return "dtpmod"; | ||||||
| 294 | case VK_PPC_TPREL_LO: return "tprel@l"; | ||||||
| 295 | case VK_PPC_TPREL_HI: return "tprel@h"; | ||||||
| 296 | case VK_PPC_TPREL_HA: return "tprel@ha"; | ||||||
| 297 | case VK_PPC_TPREL_HIGH: return "tprel@high"; | ||||||
| 298 | case VK_PPC_TPREL_HIGHA: return "tprel@higha"; | ||||||
| 299 | case VK_PPC_TPREL_HIGHER: return "tprel@higher"; | ||||||
| 300 | case VK_PPC_TPREL_HIGHERA: return "tprel@highera"; | ||||||
| 301 | case VK_PPC_TPREL_HIGHEST: return "tprel@highest"; | ||||||
| 302 | case VK_PPC_TPREL_HIGHESTA: return "tprel@highesta"; | ||||||
| 303 | case VK_PPC_DTPREL_LO: return "dtprel@l"; | ||||||
| 304 | case VK_PPC_DTPREL_HI: return "dtprel@h"; | ||||||
| 305 | case VK_PPC_DTPREL_HA: return "dtprel@ha"; | ||||||
| 306 | case VK_PPC_DTPREL_HIGH: return "dtprel@high"; | ||||||
| 307 | case VK_PPC_DTPREL_HIGHA: return "dtprel@higha"; | ||||||
| 308 | case VK_PPC_DTPREL_HIGHER: return "dtprel@higher"; | ||||||
| 309 | case VK_PPC_DTPREL_HIGHERA: return "dtprel@highera"; | ||||||
| 310 | case VK_PPC_DTPREL_HIGHEST: return "dtprel@highest"; | ||||||
| 311 | case VK_PPC_DTPREL_HIGHESTA: return "dtprel@highesta"; | ||||||
| 312 | case VK_PPC_GOT_TPREL: return "got@tprel"; | ||||||
| 313 | case VK_PPC_GOT_TPREL_LO: return "got@tprel@l"; | ||||||
| 314 | case VK_PPC_GOT_TPREL_HI: return "got@tprel@h"; | ||||||
| 315 | case VK_PPC_GOT_TPREL_HA: return "got@tprel@ha"; | ||||||
| 316 | case VK_PPC_GOT_DTPREL: return "got@dtprel"; | ||||||
| 317 | case VK_PPC_GOT_DTPREL_LO: return "got@dtprel@l"; | ||||||
| 318 | case VK_PPC_GOT_DTPREL_HI: return "got@dtprel@h"; | ||||||
| 319 | case VK_PPC_GOT_DTPREL_HA: return "got@dtprel@ha"; | ||||||
| 320 | case VK_PPC_TLS: return "tls"; | ||||||
| 321 | case VK_PPC_GOT_TLSGD: return "got@tlsgd"; | ||||||
| 322 | case VK_PPC_GOT_TLSGD_LO: return "got@tlsgd@l"; | ||||||
| 323 | case VK_PPC_GOT_TLSGD_HI: return "got@tlsgd@h"; | ||||||
| 324 | case VK_PPC_GOT_TLSGD_HA: return "got@tlsgd@ha"; | ||||||
| 325 | case VK_PPC_TLSGD: return "tlsgd"; | ||||||
| 326 | case VK_PPC_AIX_TLSGD: | ||||||
| 327 | return "gd"; | ||||||
| 328 | case VK_PPC_AIX_TLSGDM: | ||||||
| 329 | return "m"; | ||||||
| 330 | case VK_PPC_GOT_TLSLD: return "got@tlsld"; | ||||||
| 331 | case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l"; | ||||||
| 332 | case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; | ||||||
| 333 | case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; | ||||||
| 334 | case VK_PPC_GOT_PCREL: | ||||||
| 335 | return "got@pcrel"; | ||||||
| 336 | case VK_PPC_GOT_TLSGD_PCREL: | ||||||
| 337 | return "got@tlsgd@pcrel"; | ||||||
| 338 | case VK_PPC_GOT_TLSLD_PCREL: | ||||||
| 339 | return "got@tlsld@pcrel"; | ||||||
| 340 | case VK_PPC_GOT_TPREL_PCREL: | ||||||
| 341 | return "got@tprel@pcrel"; | ||||||
| 342 | case VK_PPC_TLS_PCREL: | ||||||
| 343 | return "tls@pcrel"; | ||||||
| 344 | case VK_PPC_TLSLD: return "tlsld"; | ||||||
| 345 | case VK_PPC_LOCAL: return "local"; | ||||||
| 346 | case VK_PPC_NOTOC: return "notoc"; | ||||||
| 347 | case VK_PPC_PCREL_OPT: return "<<invalid>>"; | ||||||
| 348 | case VK_COFF_IMGREL32: return "IMGREL"; | ||||||
| 349 | case VK_Hexagon_LO16: return "LO16"; | ||||||
| 350 | case VK_Hexagon_HI16: return "HI16"; | ||||||
| 351 | case VK_Hexagon_GPREL: return "GPREL"; | ||||||
| 352 | case VK_Hexagon_GD_GOT: return "GDGOT"; | ||||||
| 353 | case VK_Hexagon_LD_GOT: return "LDGOT"; | ||||||
| 354 | case VK_Hexagon_GD_PLT: return "GDPLT"; | ||||||
| 355 | case VK_Hexagon_LD_PLT: return "LDPLT"; | ||||||
| 356 | case VK_Hexagon_IE: return "IE"; | ||||||
| 357 | case VK_Hexagon_IE_GOT: return "IEGOT"; | ||||||
| 358 | case VK_WASM_TYPEINDEX: return "TYPEINDEX"; | ||||||
| 359 | case VK_WASM_MBREL: return "MBREL"; | ||||||
| 360 | case VK_WASM_TLSREL: return "TLSREL"; | ||||||
| 361 | case VK_WASM_TBREL: return "TBREL"; | ||||||
| 362 | case VK_WASM_GOT_TLS: return "GOT@TLS"; | ||||||
| 363 | case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo"; | ||||||
| 364 | case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi"; | ||||||
| 365 | case VK_AMDGPU_REL32_LO: return "rel32@lo"; | ||||||
| 366 | case VK_AMDGPU_REL32_HI: return "rel32@hi"; | ||||||
| 367 | case VK_AMDGPU_REL64: return "rel64"; | ||||||
| 368 | case VK_AMDGPU_ABS32_LO: return "abs32@lo"; | ||||||
| 369 | case VK_AMDGPU_ABS32_HI: return "abs32@hi"; | ||||||
| 370 | case VK_VE_HI32: return "hi"; | ||||||
| 371 | case VK_VE_LO32: return "lo"; | ||||||
| 372 | case VK_VE_PC_HI32: return "pc_hi"; | ||||||
| 373 | case VK_VE_PC_LO32: return "pc_lo"; | ||||||
| 374 | case VK_VE_GOT_HI32: return "got_hi"; | ||||||
| 375 | case VK_VE_GOT_LO32: return "got_lo"; | ||||||
| 376 | case VK_VE_GOTOFF_HI32: return "gotoff_hi"; | ||||||
| 377 | case VK_VE_GOTOFF_LO32: return "gotoff_lo"; | ||||||
| 378 | case VK_VE_PLT_HI32: return "plt_hi"; | ||||||
| 379 | case VK_VE_PLT_LO32: return "plt_lo"; | ||||||
| 380 | case VK_VE_TLS_GD_HI32: return "tls_gd_hi"; | ||||||
| 381 | case VK_VE_TLS_GD_LO32: return "tls_gd_lo"; | ||||||
| 382 | case VK_VE_TPOFF_HI32: return "tpoff_hi"; | ||||||
| 383 | case VK_VE_TPOFF_LO32: return "tpoff_lo"; | ||||||
| 384 | } | ||||||
| 385 | llvm_unreachable("Invalid variant kind")::llvm::llvm_unreachable_internal("Invalid variant kind", "llvm/lib/MC/MCExpr.cpp" , 385); | ||||||
| 386 | } | ||||||
| 387 | |||||||
| 388 | MCSymbolRefExpr::VariantKind | ||||||
| 389 | MCSymbolRefExpr::getVariantKindForName(StringRef Name) { | ||||||
| 390 | return StringSwitch<VariantKind>(Name.lower()) | ||||||
| 391 | .Case("dtprel", VK_DTPREL) | ||||||
| 392 | .Case("dtpoff", VK_DTPOFF) | ||||||
| 393 | .Case("got", VK_GOT) | ||||||
| 394 | .Case("gotoff", VK_GOTOFF) | ||||||
| 395 | .Case("gotrel", VK_GOTREL) | ||||||
| 396 | .Case("pcrel", VK_PCREL) | ||||||
| 397 | .Case("gotpcrel", VK_GOTPCREL) | ||||||
| 398 | .Case("gotpcrel_norelax", VK_GOTPCREL_NORELAX) | ||||||
| 399 | .Case("gottpoff", VK_GOTTPOFF) | ||||||
| 400 | .Case("indntpoff", VK_INDNTPOFF) | ||||||
| 401 | .Case("ntpoff", VK_NTPOFF) | ||||||
| 402 | .Case("gotntpoff", VK_GOTNTPOFF) | ||||||
| 403 | .Case("plt", VK_PLT) | ||||||
| 404 | .Case("tlscall", VK_TLSCALL) | ||||||
| 405 | .Case("tlsdesc", VK_TLSDESC) | ||||||
| 406 | .Case("tlsgd", VK_TLSGD) | ||||||
| 407 | .Case("tlsld", VK_TLSLD) | ||||||
| 408 | .Case("tlsldm", VK_TLSLDM) | ||||||
| 409 | .Case("tpoff", VK_TPOFF) | ||||||
| 410 | .Case("tprel", VK_TPREL) | ||||||
| 411 | .Case("tlvp", VK_TLVP) | ||||||
| 412 | .Case("tlvppage", VK_TLVPPAGE) | ||||||
| 413 | .Case("tlvppageoff", VK_TLVPPAGEOFF) | ||||||
| 414 | .Case("page", VK_PAGE) | ||||||
| 415 | .Case("pageoff", VK_PAGEOFF) | ||||||
| 416 | .Case("gotpage", VK_GOTPAGE) | ||||||
| 417 | .Case("gotpageoff", VK_GOTPAGEOFF) | ||||||
| 418 | .Case("imgrel", VK_COFF_IMGREL32) | ||||||
| 419 | .Case("secrel32", VK_SECREL) | ||||||
| 420 | .Case("size", VK_SIZE) | ||||||
| 421 | .Case("abs8", VK_X86_ABS8) | ||||||
| 422 | .Case("pltoff", VK_X86_PLTOFF) | ||||||
| 423 | .Case("l", VK_PPC_LO) | ||||||
| 424 | .Case("h", VK_PPC_HI) | ||||||
| 425 | .Case("ha", VK_PPC_HA) | ||||||
| 426 | .Case("high", VK_PPC_HIGH) | ||||||
| 427 | .Case("higha", VK_PPC_HIGHA) | ||||||
| 428 | .Case("higher", VK_PPC_HIGHER) | ||||||
| 429 | .Case("highera", VK_PPC_HIGHERA) | ||||||
| 430 | .Case("highest", VK_PPC_HIGHEST) | ||||||
| 431 | .Case("highesta", VK_PPC_HIGHESTA) | ||||||
| 432 | .Case("got@l", VK_PPC_GOT_LO) | ||||||
| 433 | .Case("got@h", VK_PPC_GOT_HI) | ||||||
| 434 | .Case("got@ha", VK_PPC_GOT_HA) | ||||||
| 435 | .Case("local", VK_PPC_LOCAL) | ||||||
| 436 | .Case("tocbase", VK_PPC_TOCBASE) | ||||||
| 437 | .Case("toc", VK_PPC_TOC) | ||||||
| 438 | .Case("toc@l", VK_PPC_TOC_LO) | ||||||
| 439 | .Case("toc@h", VK_PPC_TOC_HI) | ||||||
| 440 | .Case("toc@ha", VK_PPC_TOC_HA) | ||||||
| 441 | .Case("u", VK_PPC_U) | ||||||
| 442 | .Case("l", VK_PPC_L) | ||||||
| 443 | .Case("tls", VK_PPC_TLS) | ||||||
| 444 | .Case("dtpmod", VK_PPC_DTPMOD) | ||||||
| 445 | .Case("tprel@l", VK_PPC_TPREL_LO) | ||||||
| 446 | .Case("tprel@h", VK_PPC_TPREL_HI) | ||||||
| 447 | .Case("tprel@ha", VK_PPC_TPREL_HA) | ||||||
| 448 | .Case("tprel@high", VK_PPC_TPREL_HIGH) | ||||||
| 449 | .Case("tprel@higha", VK_PPC_TPREL_HIGHA) | ||||||
| 450 | .Case("tprel@higher", VK_PPC_TPREL_HIGHER) | ||||||
| 451 | .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) | ||||||
| 452 | .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) | ||||||
| 453 | .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) | ||||||
| 454 | .Case("dtprel@l", VK_PPC_DTPREL_LO) | ||||||
| 455 | .Case("dtprel@h", VK_PPC_DTPREL_HI) | ||||||
| 456 | .Case("dtprel@ha", VK_PPC_DTPREL_HA) | ||||||
| 457 | .Case("dtprel@high", VK_PPC_DTPREL_HIGH) | ||||||
| 458 | .Case("dtprel@higha", VK_PPC_DTPREL_HIGHA) | ||||||
| 459 | .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER) | ||||||
| 460 | .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA) | ||||||
| 461 | .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST) | ||||||
| 462 | .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA) | ||||||
| 463 | .Case("got@tprel", VK_PPC_GOT_TPREL) | ||||||
| 464 | .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) | ||||||
| 465 | .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI) | ||||||
| 466 | .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) | ||||||
| 467 | .Case("got@dtprel", VK_PPC_GOT_DTPREL) | ||||||
| 468 | .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO) | ||||||
| 469 | .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI) | ||||||
| 470 | .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA) | ||||||
| 471 | .Case("got@tlsgd", VK_PPC_GOT_TLSGD) | ||||||
| 472 | .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) | ||||||
| 473 | .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI) | ||||||
| 474 | .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) | ||||||
| 475 | .Case("got@tlsld", VK_PPC_GOT_TLSLD) | ||||||
| 476 | .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) | ||||||
| 477 | .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) | ||||||
| 478 | .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) | ||||||
| 479 | .Case("got@pcrel", VK_PPC_GOT_PCREL) | ||||||
| 480 | .Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL) | ||||||
| 481 | .Case("got@tlsld@pcrel", VK_PPC_GOT_TLSLD_PCREL) | ||||||
| 482 | .Case("got@tprel@pcrel", VK_PPC_GOT_TPREL_PCREL) | ||||||
| 483 | .Case("tls@pcrel", VK_PPC_TLS_PCREL) | ||||||
| 484 | .Case("notoc", VK_PPC_NOTOC) | ||||||
| 485 | .Case("gdgot", VK_Hexagon_GD_GOT) | ||||||
| 486 | .Case("gdplt", VK_Hexagon_GD_PLT) | ||||||
| 487 | .Case("iegot", VK_Hexagon_IE_GOT) | ||||||
| 488 | .Case("ie", VK_Hexagon_IE) | ||||||
| 489 | .Case("ldgot", VK_Hexagon_LD_GOT) | ||||||
| 490 | .Case("ldplt", VK_Hexagon_LD_PLT) | ||||||
| 491 | .Case("none", VK_ARM_NONE) | ||||||
| 492 | .Case("got_prel", VK_ARM_GOT_PREL) | ||||||
| 493 | .Case("target1", VK_ARM_TARGET1) | ||||||
| 494 | .Case("target2", VK_ARM_TARGET2) | ||||||
| 495 | .Case("prel31", VK_ARM_PREL31) | ||||||
| 496 | .Case("sbrel", VK_ARM_SBREL) | ||||||
| 497 | .Case("tlsldo", VK_ARM_TLSLDO) | ||||||
| 498 | .Case("lo8", VK_AVR_LO8) | ||||||
| 499 | .Case("hi8", VK_AVR_HI8) | ||||||
| 500 | .Case("hlo8", VK_AVR_HLO8) | ||||||
| 501 | .Case("typeindex", VK_WASM_TYPEINDEX) | ||||||
| 502 | .Case("tbrel", VK_WASM_TBREL) | ||||||
| 503 | .Case("mbrel", VK_WASM_MBREL) | ||||||
| 504 | .Case("tlsrel", VK_WASM_TLSREL) | ||||||
| 505 | .Case("got@tls", VK_WASM_GOT_TLS) | ||||||
| 506 | .Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO) | ||||||
| 507 | .Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI) | ||||||
| 508 | .Case("rel32@lo", VK_AMDGPU_REL32_LO) | ||||||
| 509 | .Case("rel32@hi", VK_AMDGPU_REL32_HI) | ||||||
| 510 | .Case("rel64", VK_AMDGPU_REL64) | ||||||
| 511 | .Case("abs32@lo", VK_AMDGPU_ABS32_LO) | ||||||
| 512 | .Case("abs32@hi", VK_AMDGPU_ABS32_HI) | ||||||
| 513 | .Case("hi", VK_VE_HI32) | ||||||
| 514 | .Case("lo", VK_VE_LO32) | ||||||
| 515 | .Case("pc_hi", VK_VE_PC_HI32) | ||||||
| 516 | .Case("pc_lo", VK_VE_PC_LO32) | ||||||
| 517 | .Case("got_hi", VK_VE_GOT_HI32) | ||||||
| 518 | .Case("got_lo", VK_VE_GOT_LO32) | ||||||
| 519 | .Case("gotoff_hi", VK_VE_GOTOFF_HI32) | ||||||
| 520 | .Case("gotoff_lo", VK_VE_GOTOFF_LO32) | ||||||
| 521 | .Case("plt_hi", VK_VE_PLT_HI32) | ||||||
| 522 | .Case("plt_lo", VK_VE_PLT_LO32) | ||||||
| 523 | .Case("tls_gd_hi", VK_VE_TLS_GD_HI32) | ||||||
| 524 | .Case("tls_gd_lo", VK_VE_TLS_GD_LO32) | ||||||
| 525 | .Case("tpoff_hi", VK_VE_TPOFF_HI32) | ||||||
| 526 | .Case("tpoff_lo", VK_VE_TPOFF_LO32) | ||||||
| 527 | .Default(VK_Invalid); | ||||||
| 528 | } | ||||||
| 529 | |||||||
| 530 | /* *** */ | ||||||
| 531 | |||||||
| 532 | void MCTargetExpr::anchor() {} | ||||||
| 533 | |||||||
| 534 | /* *** */ | ||||||
| 535 | |||||||
| 536 | bool MCExpr::evaluateAsAbsolute(int64_t &Res) const { | ||||||
| 537 | return evaluateAsAbsolute(Res, nullptr, nullptr, nullptr, false); | ||||||
| 538 | } | ||||||
| 539 | |||||||
| 540 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, | ||||||
| 541 | const MCAsmLayout &Layout) const { | ||||||
| 542 | return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, false); | ||||||
| 543 | } | ||||||
| 544 | |||||||
| 545 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, | ||||||
| 546 | const MCAsmLayout &Layout, | ||||||
| 547 | const SectionAddrMap &Addrs) const { | ||||||
| 548 | // Setting InSet causes us to absolutize differences across sections and that | ||||||
| 549 | // is what the MachO writer uses Addrs for. | ||||||
| 550 | return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, &Addrs, true); | ||||||
| 551 | } | ||||||
| 552 | |||||||
| 553 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { | ||||||
| 554 | return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr, false); | ||||||
| 555 | } | ||||||
| 556 | |||||||
| 557 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const { | ||||||
| 558 | return evaluateAsAbsolute(Res, Asm, nullptr, nullptr, false); | ||||||
| 559 | } | ||||||
| 560 | |||||||
| 561 | bool MCExpr::evaluateKnownAbsolute(int64_t &Res, | ||||||
| 562 | const MCAsmLayout &Layout) const { | ||||||
| 563 | return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, | ||||||
| 564 | true); | ||||||
| 565 | } | ||||||
| 566 | |||||||
| 567 | bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, | ||||||
| 568 | const MCAsmLayout *Layout, | ||||||
| 569 | const SectionAddrMap *Addrs, bool InSet) const { | ||||||
| 570 | MCValue Value; | ||||||
| 571 | |||||||
| 572 | // Fast path constants. | ||||||
| 573 | if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(this)) { | ||||||
| 574 | Res = CE->getValue(); | ||||||
| 575 | return true; | ||||||
| 576 | } | ||||||
| 577 | |||||||
| 578 | bool IsRelocatable = | ||||||
| 579 | evaluateAsRelocatableImpl(Value, Asm, Layout, nullptr, Addrs, InSet); | ||||||
| 580 | |||||||
| 581 | // Record the current value. | ||||||
| 582 | Res = Value.getConstant(); | ||||||
| 583 | |||||||
| 584 | return IsRelocatable && Value.isAbsolute(); | ||||||
| 585 | } | ||||||
| 586 | |||||||
| 587 | /// Helper method for \see EvaluateSymbolAdd(). | ||||||
| 588 | static void AttemptToFoldSymbolOffsetDifference( | ||||||
| 589 | const MCAssembler *Asm, const MCAsmLayout *Layout, | ||||||
| 590 | const SectionAddrMap *Addrs, bool InSet, const MCSymbolRefExpr *&A, | ||||||
| 591 | const MCSymbolRefExpr *&B, int64_t &Addend) { | ||||||
| 592 | if (!A
| ||||||
| 593 | return; | ||||||
| 594 | |||||||
| 595 | const MCSymbol &SA = A->getSymbol(); | ||||||
| 596 | const MCSymbol &SB = B->getSymbol(); | ||||||
| 597 | |||||||
| 598 | if (SA.isUndefined() || SB.isUndefined()) | ||||||
| 599 | return; | ||||||
| 600 | |||||||
| 601 | if (!Asm->getWriter().isSymbolRefDifferenceFullyResolved(*Asm, A, B, InSet)) | ||||||
| 602 | return; | ||||||
| 603 | |||||||
| 604 | auto FinalizeFolding = [&]() { | ||||||
| 605 | // Pointers to Thumb symbols need to have their low-bit set to allow | ||||||
| 606 | // for interworking. | ||||||
| 607 | if (Asm->isThumbFunc(&SA)) | ||||||
| 608 | Addend |= 1; | ||||||
| 609 | |||||||
| 610 | // If symbol is labeled as micromips, we set low-bit to ensure | ||||||
| 611 | // correct offset in .gcc_except_table | ||||||
| 612 | if (Asm->getBackend().isMicroMips(&SA)) | ||||||
| 613 | Addend |= 1; | ||||||
| 614 | |||||||
| 615 | // Clear the symbol expr pointers to indicate we have folded these | ||||||
| 616 | // operands. | ||||||
| 617 | A = B = nullptr; | ||||||
| 618 | }; | ||||||
| 619 | |||||||
| 620 | const MCFragment *FA = SA.getFragment(); | ||||||
| 621 | const MCFragment *FB = SB.getFragment(); | ||||||
| 622 | // If both symbols are in the same fragment, return the difference of their | ||||||
| 623 | // offsets | ||||||
| 624 | if (FA == FB && !SA.isVariable() && !SA.isUnset() && !SB.isVariable() && | ||||||
| 625 | !SB.isUnset()) { | ||||||
| 626 | Addend += SA.getOffset() - SB.getOffset(); | ||||||
| 627 | return FinalizeFolding(); | ||||||
| 628 | } | ||||||
| 629 | |||||||
| 630 | const MCSection &SecA = *FA->getParent(); | ||||||
| |||||||
| 631 | const MCSection &SecB = *FB->getParent(); | ||||||
| 632 | |||||||
| 633 | if ((&SecA != &SecB) && !Addrs) | ||||||
| 634 | return; | ||||||
| 635 | |||||||
| 636 | if (Layout) { | ||||||
| 637 | // One of the symbol involved is part of a fragment being laid out. Quit now | ||||||
| 638 | // to avoid a self loop. | ||||||
| 639 | if (!Layout->canGetFragmentOffset(FA) || !Layout->canGetFragmentOffset(FB)) | ||||||
| 640 | return; | ||||||
| 641 | |||||||
| 642 | // Eagerly evaluate when layout is finalized. | ||||||
| 643 | Addend += Layout->getSymbolOffset(A->getSymbol()) - | ||||||
| 644 | Layout->getSymbolOffset(B->getSymbol()); | ||||||
| 645 | if (Addrs && (&SecA != &SecB)) | ||||||
| 646 | Addend += (Addrs->lookup(&SecA) - Addrs->lookup(&SecB)); | ||||||
| 647 | |||||||
| 648 | FinalizeFolding(); | ||||||
| 649 | } else { | ||||||
| 650 | // When layout is not finalized, our ability to resolve differences between | ||||||
| 651 | // symbols is limited to specific cases where the fragments between two | ||||||
| 652 | // symbols (including the fragments the symbols are defined in) are | ||||||
| 653 | // fixed-size fragments so the difference can be calculated. For example, | ||||||
| 654 | // this is important when the Subtarget is changed and a new MCDataFragment | ||||||
| 655 | // is created in the case of foo: instr; .arch_extension ext; instr .if . - | ||||||
| 656 | // foo. | ||||||
| 657 | if (SA.isVariable() || SA.isUnset() || SB.isVariable() || SB.isUnset() || | ||||||
| 658 | FA->getKind() != MCFragment::FT_Data || | ||||||
| 659 | FB->getKind() != MCFragment::FT_Data || | ||||||
| 660 | FA->getSubsectionNumber() != FB->getSubsectionNumber()) | ||||||
| 661 | return; | ||||||
| 662 | // Try to find a constant displacement from FA to FB, add the displacement | ||||||
| 663 | // between the offset in FA of SA and the offset in FB of SB. | ||||||
| 664 | int64_t Displacement = SA.getOffset() - SB.getOffset(); | ||||||
| 665 | for (auto FI = FB->getIterator(), FE = SecA.end(); FI != FE; ++FI) { | ||||||
| 666 | if (&*FI == FA) { | ||||||
| 667 | Addend += Displacement; | ||||||
| 668 | return FinalizeFolding(); | ||||||
| 669 | } | ||||||
| 670 | |||||||
| 671 | if (FI->getKind() != MCFragment::FT_Data) | ||||||
| 672 | return; | ||||||
| 673 | Displacement += cast<MCDataFragment>(FI)->getContents().size(); | ||||||
| 674 | } | ||||||
| 675 | } | ||||||
| 676 | } | ||||||
| 677 | |||||||
| 678 | /// Evaluate the result of an add between (conceptually) two MCValues. | ||||||
| 679 | /// | ||||||
| 680 | /// This routine conceptually attempts to construct an MCValue: | ||||||
| 681 | /// Result = (Result_A - Result_B + Result_Cst) | ||||||
| 682 | /// from two MCValue's LHS and RHS where | ||||||
| 683 | /// Result = LHS + RHS | ||||||
| 684 | /// and | ||||||
| 685 | /// Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). | ||||||
| 686 | /// | ||||||
| 687 | /// This routine attempts to aggressively fold the operands such that the result | ||||||
| 688 | /// is representable in an MCValue, but may not always succeed. | ||||||
| 689 | /// | ||||||
| 690 | /// \returns True on success, false if the result is not representable in an | ||||||
| 691 | /// MCValue. | ||||||
| 692 | |||||||
| 693 | /// NOTE: It is really important to have both the Asm and Layout arguments. | ||||||
| 694 | /// They might look redundant, but this function can be used before layout | ||||||
| 695 | /// is done (see the object streamer for example) and having the Asm argument | ||||||
| 696 | /// lets us avoid relaxations early. | ||||||
| 697 | static bool | ||||||
| 698 | EvaluateSymbolicAdd(const MCAssembler *Asm, const MCAsmLayout *Layout, | ||||||
| 699 | const SectionAddrMap *Addrs, bool InSet, const MCValue &LHS, | ||||||
| 700 | const MCSymbolRefExpr *RHS_A, const MCSymbolRefExpr *RHS_B, | ||||||
| 701 | int64_t RHS_Cst, MCValue &Res) { | ||||||
| 702 | // FIXME: This routine (and other evaluation parts) are *incredibly* sloppy | ||||||
| 703 | // about dealing with modifiers. This will ultimately bite us, one day. | ||||||
| 704 | const MCSymbolRefExpr *LHS_A = LHS.getSymA(); | ||||||
| 705 | const MCSymbolRefExpr *LHS_B = LHS.getSymB(); | ||||||
| 706 | int64_t LHS_Cst = LHS.getConstant(); | ||||||
| 707 | |||||||
| 708 | // Fold the result constant immediately. | ||||||
| 709 | int64_t Result_Cst = LHS_Cst + RHS_Cst; | ||||||
| 710 | |||||||
| 711 | assert((!Layout || Asm) &&(static_cast <bool> ((!Layout || Asm) && "Must have an assembler object if layout is given!" ) ? void (0) : __assert_fail ("(!Layout || Asm) && \"Must have an assembler object if layout is given!\"" , "llvm/lib/MC/MCExpr.cpp", 712, __extension__ __PRETTY_FUNCTION__ )) | ||||||
| 712 | "Must have an assembler object if layout is given!")(static_cast <bool> ((!Layout || Asm) && "Must have an assembler object if layout is given!" ) ? void (0) : __assert_fail ("(!Layout || Asm) && \"Must have an assembler object if layout is given!\"" , "llvm/lib/MC/MCExpr.cpp", 712, __extension__ __PRETTY_FUNCTION__ )); | ||||||
| 713 | |||||||
| 714 | // If we have a layout, we can fold resolved differences. | ||||||
| 715 | if (Asm
| ||||||
| 716 | // First, fold out any differences which are fully resolved. By | ||||||
| 717 | // reassociating terms in | ||||||
| 718 | // Result = (LHS_A - LHS_B + LHS_Cst) + (RHS_A - RHS_B + RHS_Cst). | ||||||
| 719 | // we have the four possible differences: | ||||||
| 720 | // (LHS_A - LHS_B), | ||||||
| 721 | // (LHS_A - RHS_B), | ||||||
| 722 | // (RHS_A - LHS_B), | ||||||
| 723 | // (RHS_A - RHS_B). | ||||||
| 724 | // Since we are attempting to be as aggressive as possible about folding, we | ||||||
| 725 | // attempt to evaluate each possible alternative. | ||||||
| 726 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, LHS_B, | ||||||
| 727 | Result_Cst); | ||||||
| 728 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, LHS_A, RHS_B, | ||||||
| 729 | Result_Cst); | ||||||
| 730 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, LHS_B, | ||||||
| 731 | Result_Cst); | ||||||
| 732 | AttemptToFoldSymbolOffsetDifference(Asm, Layout, Addrs, InSet, RHS_A, RHS_B, | ||||||
| 733 | Result_Cst); | ||||||
| 734 | } | ||||||
| 735 | |||||||
| 736 | // We can't represent the addition or subtraction of two symbols. | ||||||
| 737 | if ((LHS_A && RHS_A) || (LHS_B && RHS_B)) | ||||||
| 738 | return false; | ||||||
| 739 | |||||||
| 740 | // At this point, we have at most one additive symbol and one subtractive | ||||||
| 741 | // symbol -- find them. | ||||||
| 742 | const MCSymbolRefExpr *A = LHS_A ? LHS_A : RHS_A; | ||||||
| 743 | const MCSymbolRefExpr *B = LHS_B ? LHS_B : RHS_B; | ||||||
| 744 | |||||||
| 745 | Res = MCValue::get(A, B, Result_Cst); | ||||||
| 746 | return true; | ||||||
| 747 | } | ||||||
| 748 | |||||||
| 749 | bool MCExpr::evaluateAsRelocatable(MCValue &Res, | ||||||
| 750 | const MCAsmLayout *Layout, | ||||||
| 751 | const MCFixup *Fixup) const { | ||||||
| 752 | MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; | ||||||
| 753 | return evaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, | ||||||
| 754 | false); | ||||||
| 755 | } | ||||||
| 756 | |||||||
| 757 | bool MCExpr::evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const { | ||||||
| 758 | MCAssembler *Assembler = &Layout.getAssembler(); | ||||||
| 759 | return evaluateAsRelocatableImpl(Res, Assembler, &Layout, nullptr, nullptr, | ||||||
| 760 | true); | ||||||
| 761 | } | ||||||
| 762 | |||||||
| 763 | static bool canExpand(const MCSymbol &Sym, bool InSet) { | ||||||
| 764 | const MCExpr *Expr = Sym.getVariableValue(); | ||||||
| 765 | const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr); | ||||||
| 766 | if (Inner) { | ||||||
| 767 | if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) | ||||||
| 768 | return false; | ||||||
| 769 | } | ||||||
| 770 | |||||||
| 771 | if (InSet) | ||||||
| 772 | return true; | ||||||
| 773 | return !Sym.isInSection(); | ||||||
| 774 | } | ||||||
| 775 | |||||||
| 776 | bool MCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, | ||||||
| 777 | const MCAsmLayout *Layout, | ||||||
| 778 | const MCFixup *Fixup, | ||||||
| 779 | const SectionAddrMap *Addrs, | ||||||
| 780 | bool InSet) const { | ||||||
| 781 | ++stats::MCExprEvaluate; | ||||||
| 782 | |||||||
| 783 | switch (getKind()) { | ||||||
| |||||||
| 784 | case Target: | ||||||
| 785 | return cast<MCTargetExpr>(this)->evaluateAsRelocatableImpl(Res, Layout, | ||||||
| 786 | Fixup); | ||||||
| 787 | |||||||
| 788 | case Constant: | ||||||
| 789 | Res = MCValue::get(cast<MCConstantExpr>(this)->getValue()); | ||||||
| 790 | return true; | ||||||
| 791 | |||||||
| 792 | case SymbolRef: { | ||||||
| 793 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); | ||||||
| 794 | const MCSymbol &Sym = SRE->getSymbol(); | ||||||
| 795 | const auto Kind = SRE->getKind(); | ||||||
| 796 | |||||||
| 797 | // Evaluate recursively if this is a variable. | ||||||
| 798 | if (Sym.isVariable() && (Kind == MCSymbolRefExpr::VK_None || Layout) && | ||||||
| 799 | canExpand(Sym, InSet)) { | ||||||
| 800 | bool IsMachO = SRE->hasSubsectionsViaSymbols(); | ||||||
| 801 | if (Sym.getVariableValue()->evaluateAsRelocatableImpl( | ||||||
| 802 | Res, Asm, Layout, Fixup, Addrs, InSet || IsMachO)) { | ||||||
| 803 | if (Kind != MCSymbolRefExpr::VK_None) { | ||||||
| 804 | if (Res.isAbsolute()) { | ||||||
| 805 | Res = MCValue::get(SRE, nullptr, 0); | ||||||
| 806 | return true; | ||||||
| 807 | } | ||||||
| 808 | // If the reference has a variant kind, we can only handle expressions | ||||||
| 809 | // which evaluate exactly to a single unadorned symbol. Attach the | ||||||
| 810 | // original VariantKind to SymA of the result. | ||||||
| 811 | if (Res.getRefKind() != MCSymbolRefExpr::VK_None || !Res.getSymA() || | ||||||
| 812 | Res.getSymB() || Res.getConstant()) | ||||||
| 813 | return false; | ||||||
| 814 | Res = | ||||||
| 815 | MCValue::get(MCSymbolRefExpr::create(&Res.getSymA()->getSymbol(), | ||||||
| 816 | Kind, Asm->getContext()), | ||||||
| 817 | Res.getSymB(), Res.getConstant(), Res.getRefKind()); | ||||||
| 818 | } | ||||||
| 819 | if (!IsMachO) | ||||||
| 820 | return true; | ||||||
| 821 | |||||||
| 822 | const MCSymbolRefExpr *A = Res.getSymA(); | ||||||
| 823 | const MCSymbolRefExpr *B = Res.getSymB(); | ||||||
| 824 | // FIXME: This is small hack. Given | ||||||
| 825 | // a = b + 4 | ||||||
| 826 | // .long a | ||||||
| 827 | // the OS X assembler will completely drop the 4. We should probably | ||||||
| 828 | // include it in the relocation or produce an error if that is not | ||||||
| 829 | // possible. | ||||||
| 830 | // Allow constant expressions. | ||||||
| 831 | if (!A && !B) | ||||||
| 832 | return true; | ||||||
| 833 | // Allows aliases with zero offset. | ||||||
| 834 | if (Res.getConstant() == 0 && (!A || !B)) | ||||||
| 835 | return true; | ||||||
| 836 | } | ||||||
| 837 | } | ||||||
| 838 | |||||||
| 839 | Res = MCValue::get(SRE, nullptr, 0); | ||||||
| 840 | return true; | ||||||
| 841 | } | ||||||
| 842 | |||||||
| 843 | case Unary: { | ||||||
| 844 | const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this); | ||||||
| 845 | MCValue Value; | ||||||
| 846 | |||||||
| 847 | if (!AUE->getSubExpr()->evaluateAsRelocatableImpl(Value, Asm, Layout, Fixup, | ||||||
| 848 | Addrs, InSet)) | ||||||
| 849 | return false; | ||||||
| 850 | |||||||
| 851 | switch (AUE->getOpcode()) { | ||||||
| 852 | case MCUnaryExpr::LNot: | ||||||
| 853 | if (!Value.isAbsolute()) | ||||||
| 854 | return false; | ||||||
| 855 | Res = MCValue::get(!Value.getConstant()); | ||||||
| 856 | break; | ||||||
| 857 | case MCUnaryExpr::Minus: | ||||||
| 858 | /// -(a - b + const) ==> (b - a - const) | ||||||
| 859 | if (Value.getSymA() && !Value.getSymB()) | ||||||
| 860 | return false; | ||||||
| 861 | |||||||
| 862 | // The cast avoids undefined behavior if the constant is INT64_MIN. | ||||||
| 863 | Res = MCValue::get(Value.getSymB(), Value.getSymA(), | ||||||
| 864 | -(uint64_t)Value.getConstant()); | ||||||
| 865 | break; | ||||||
| 866 | case MCUnaryExpr::Not: | ||||||
| 867 | if (!Value.isAbsolute()) | ||||||
| 868 | return false; | ||||||
| 869 | Res = MCValue::get(~Value.getConstant()); | ||||||
| 870 | break; | ||||||
| 871 | case MCUnaryExpr::Plus: | ||||||
| 872 | Res = Value; | ||||||
| 873 | break; | ||||||
| 874 | } | ||||||
| 875 | |||||||
| 876 | return true; | ||||||
| 877 | } | ||||||
| 878 | |||||||
| 879 | case Binary: { | ||||||
| 880 | const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this); | ||||||
| 881 | MCValue LHSValue, RHSValue; | ||||||
| 882 | |||||||
| 883 | if (!ABE->getLHS()->evaluateAsRelocatableImpl(LHSValue, Asm, Layout, Fixup, | ||||||
| 884 | Addrs, InSet) || | ||||||
| 885 | !ABE->getRHS()->evaluateAsRelocatableImpl(RHSValue, Asm, Layout, Fixup, | ||||||
| 886 | Addrs, InSet)) { | ||||||
| 887 | // Check if both are Target Expressions, see if we can compare them. | ||||||
| 888 | if (const MCTargetExpr *L = dyn_cast<MCTargetExpr>(ABE->getLHS())) | ||||||
| 889 | if (const MCTargetExpr *R = cast<MCTargetExpr>(ABE->getRHS())) { | ||||||
| 890 | switch (ABE->getOpcode()) { | ||||||
| 891 | case MCBinaryExpr::EQ: | ||||||
| 892 | Res = MCValue::get((L->isEqualTo(R)) ? -1 : 0); | ||||||
| 893 | return true; | ||||||
| 894 | case MCBinaryExpr::NE: | ||||||
| 895 | Res = MCValue::get((R->isEqualTo(R)) ? 0 : -1); | ||||||
| 896 | return true; | ||||||
| 897 | default: break; | ||||||
| 898 | } | ||||||
| 899 | } | ||||||
| 900 | return false; | ||||||
| 901 | } | ||||||
| 902 | |||||||
| 903 | // We only support a few operations on non-constant expressions, handle | ||||||
| 904 | // those first. | ||||||
| 905 | if (!LHSValue.isAbsolute() || !RHSValue.isAbsolute()) { | ||||||
| 906 | switch (ABE->getOpcode()) { | ||||||
| 907 | default: | ||||||
| 908 | return false; | ||||||
| 909 | case MCBinaryExpr::Sub: | ||||||
| 910 | // Negate RHS and add. | ||||||
| 911 | // The cast avoids undefined behavior if the constant is INT64_MIN. | ||||||
| 912 | return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, | ||||||
| 913 | RHSValue.getSymB(), RHSValue.getSymA(), | ||||||
| 914 | -(uint64_t)RHSValue.getConstant(), Res); | ||||||
| 915 | |||||||
| 916 | case MCBinaryExpr::Add: | ||||||
| 917 | return EvaluateSymbolicAdd(Asm, Layout, Addrs, InSet, LHSValue, | ||||||
| 918 | RHSValue.getSymA(), RHSValue.getSymB(), | ||||||
| 919 | RHSValue.getConstant(), Res); | ||||||
| 920 | } | ||||||
| 921 | } | ||||||
| 922 | |||||||
| 923 | // FIXME: We need target hooks for the evaluation. It may be limited in | ||||||
| 924 | // width, and gas defines the result of comparisons differently from | ||||||
| 925 | // Apple as. | ||||||
| 926 | int64_t LHS = LHSValue.getConstant(), RHS = RHSValue.getConstant(); | ||||||
| 927 | int64_t Result = 0; | ||||||
| 928 | auto Op = ABE->getOpcode(); | ||||||
| 929 | switch (Op) { | ||||||
| 930 | case MCBinaryExpr::AShr: Result = LHS >> RHS; break; | ||||||
| 931 | case MCBinaryExpr::Add: Result = LHS + RHS; break; | ||||||
| 932 | case MCBinaryExpr::And: Result = LHS & RHS; break; | ||||||
| 933 | case MCBinaryExpr::Div: | ||||||
| 934 | case MCBinaryExpr::Mod: | ||||||
| 935 | // Handle division by zero. gas just emits a warning and keeps going, | ||||||
| 936 | // we try to be stricter. | ||||||
| 937 | // FIXME: Currently the caller of this function has no way to understand | ||||||
| 938 | // we're bailing out because of 'division by zero'. Therefore, it will | ||||||
| 939 | // emit a 'expected relocatable expression' error. It would be nice to | ||||||
| 940 | // change this code to emit a better diagnostic. | ||||||
| 941 | if (RHS == 0) | ||||||
| 942 | return false; | ||||||
| 943 | if (ABE->getOpcode() == MCBinaryExpr::Div) | ||||||
| 944 | Result = LHS / RHS; | ||||||
| 945 | else | ||||||
| 946 | Result = LHS % RHS; | ||||||
| 947 | break; | ||||||
| 948 | case MCBinaryExpr::EQ: Result = LHS == RHS; break; | ||||||
| 949 | case MCBinaryExpr::GT: Result = LHS > RHS; break; | ||||||
| 950 | case MCBinaryExpr::GTE: Result = LHS >= RHS; break; | ||||||
| 951 | case MCBinaryExpr::LAnd: Result = LHS && RHS; break; | ||||||
| 952 | case MCBinaryExpr::LOr: Result = LHS || RHS; break; | ||||||
| 953 | case MCBinaryExpr::LShr: Result = uint64_t(LHS) >> uint64_t(RHS); break; | ||||||
| 954 | case MCBinaryExpr::LT: Result = LHS < RHS; break; | ||||||
| 955 | case MCBinaryExpr::LTE: Result = LHS <= RHS; break; | ||||||
| 956 | case MCBinaryExpr::Mul: Result = LHS * RHS; break; | ||||||
| 957 | case MCBinaryExpr::NE: Result = LHS != RHS; break; | ||||||
| 958 | case MCBinaryExpr::Or: Result = LHS | RHS; break; | ||||||
| 959 | case MCBinaryExpr::OrNot: Result = LHS | ~RHS; break; | ||||||
| 960 | case MCBinaryExpr::Shl: Result = uint64_t(LHS) << uint64_t(RHS); break; | ||||||
| 961 | case MCBinaryExpr::Sub: Result = LHS - RHS; break; | ||||||
| 962 | case MCBinaryExpr::Xor: Result = LHS ^ RHS; break; | ||||||
| 963 | } | ||||||
| 964 | |||||||
| 965 | switch (Op) { | ||||||
| 966 | default: | ||||||
| 967 | Res = MCValue::get(Result); | ||||||
| 968 | break; | ||||||
| 969 | case MCBinaryExpr::EQ: | ||||||
| 970 | case MCBinaryExpr::GT: | ||||||
| 971 | case MCBinaryExpr::GTE: | ||||||
| 972 | case MCBinaryExpr::LT: | ||||||
| 973 | case MCBinaryExpr::LTE: | ||||||
| 974 | case MCBinaryExpr::NE: | ||||||
| 975 | // A comparison operator returns a -1 if true and 0 if false. | ||||||
| 976 | Res = MCValue::get(Result ? -1 : 0); | ||||||
| 977 | break; | ||||||
| 978 | } | ||||||
| 979 | |||||||
| 980 | return true; | ||||||
| 981 | } | ||||||
| 982 | } | ||||||
| 983 | |||||||
| 984 | llvm_unreachable("Invalid assembly expression kind!")::llvm::llvm_unreachable_internal("Invalid assembly expression kind!" , "llvm/lib/MC/MCExpr.cpp", 984); | ||||||
| 985 | } | ||||||
| 986 | |||||||
| 987 | MCFragment *MCExpr::findAssociatedFragment() const { | ||||||
| 988 | switch (getKind()) { | ||||||
| 989 | case Target: | ||||||
| 990 | // We never look through target specific expressions. | ||||||
| 991 | return cast<MCTargetExpr>(this)->findAssociatedFragment(); | ||||||
| 992 | |||||||
| 993 | case Constant: | ||||||
| 994 | return MCSymbol::AbsolutePseudoFragment; | ||||||
| 995 | |||||||
| 996 | case SymbolRef: { | ||||||
| 997 | const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this); | ||||||
| 998 | const MCSymbol &Sym = SRE->getSymbol(); | ||||||
| 999 | return Sym.getFragment(); | ||||||
| 1000 | } | ||||||
| 1001 | |||||||
| 1002 | case Unary: | ||||||
| 1003 | return cast<MCUnaryExpr>(this)->getSubExpr()->findAssociatedFragment(); | ||||||
| 1004 | |||||||
| 1005 | case Binary: { | ||||||
| 1006 | const MCBinaryExpr *BE = cast<MCBinaryExpr>(this); | ||||||
| 1007 | MCFragment *LHS_F = BE->getLHS()->findAssociatedFragment(); | ||||||
| 1008 | MCFragment *RHS_F = BE->getRHS()->findAssociatedFragment(); | ||||||
| 1009 | |||||||
| 1010 | // If either is absolute, return the other. | ||||||
| 1011 | if (LHS_F == MCSymbol::AbsolutePseudoFragment) | ||||||
| 1012 | return RHS_F; | ||||||
| 1013 | if (RHS_F == MCSymbol::AbsolutePseudoFragment) | ||||||
| 1014 | return LHS_F; | ||||||
| 1015 | |||||||
| 1016 | // Not always correct, but probably the best we can do without more context. | ||||||
| 1017 | if (BE->getOpcode() == MCBinaryExpr::Sub) | ||||||
| 1018 | return MCSymbol::AbsolutePseudoFragment; | ||||||
| 1019 | |||||||
| 1020 | // Otherwise, return the first non-null fragment. | ||||||
| 1021 | return LHS_F ? LHS_F : RHS_F; | ||||||
| 1022 | } | ||||||
| 1023 | } | ||||||
| 1024 | |||||||
| 1025 | llvm_unreachable("Invalid assembly expression kind!")::llvm::llvm_unreachable_internal("Invalid assembly expression kind!" , "llvm/lib/MC/MCExpr.cpp", 1025); | ||||||
| 1026 | } |
| 1 | //===-- llvm/MC/MCValue.h - MCValue 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 contains the declaration of the MCValue class. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #ifndef LLVM_MC_MCVALUE_H |
| 14 | #define LLVM_MC_MCVALUE_H |
| 15 | |
| 16 | #include "llvm/MC/MCExpr.h" |
| 17 | #include "llvm/Support/DataTypes.h" |
| 18 | |
| 19 | namespace llvm { |
| 20 | class raw_ostream; |
| 21 | |
| 22 | /// This represents an "assembler immediate". |
| 23 | /// |
| 24 | /// In its most general form, this can hold ":Kind:(SymbolA - SymbolB + |
| 25 | /// imm64)". Not all targets supports relocations of this general form, but we |
| 26 | /// need to represent this anyway. |
| 27 | /// |
| 28 | /// In general both SymbolA and SymbolB will also have a modifier |
| 29 | /// analogous to the top-level Kind. Current targets are not expected |
| 30 | /// to make use of both though. The choice comes down to whether |
| 31 | /// relocation modifiers apply to the closest symbol or the whole |
| 32 | /// expression. |
| 33 | /// |
| 34 | /// Note that this class must remain a simple POD value class, because we need |
| 35 | /// it to live in unions etc. |
| 36 | class MCValue { |
| 37 | const MCSymbolRefExpr *SymA = nullptr, *SymB = nullptr; |
| 38 | int64_t Cst = 0; |
| 39 | uint32_t RefKind = 0; |
| 40 | |
| 41 | public: |
| 42 | MCValue() = default; |
| 43 | int64_t getConstant() const { return Cst; } |
| 44 | const MCSymbolRefExpr *getSymA() const { return SymA; } |
| 45 | const MCSymbolRefExpr *getSymB() const { return SymB; } |
| 46 | uint32_t getRefKind() const { return RefKind; } |
| 47 | |
| 48 | /// Is this an absolute (as opposed to relocatable) value. |
| 49 | bool isAbsolute() const { return !SymA && !SymB; } |
| 50 | |
| 51 | /// Print the value to the stream \p OS. |
| 52 | void print(raw_ostream &OS) const; |
| 53 | |
| 54 | /// Print the value to stderr. |
| 55 | void dump() const; |
| 56 | |
| 57 | MCSymbolRefExpr::VariantKind getAccessVariant() const; |
| 58 | |
| 59 | static MCValue get(const MCSymbolRefExpr *SymA, |
| 60 | const MCSymbolRefExpr *SymB = nullptr, |
| 61 | int64_t Val = 0, uint32_t RefKind = 0) { |
| 62 | MCValue R; |
| 63 | R.Cst = Val; |
| 64 | R.SymA = SymA; |
| 65 | R.SymB = SymB; |
| 66 | R.RefKind = RefKind; |
| 67 | return R; |
| 68 | } |
| 69 | |
| 70 | static MCValue get(int64_t Val) { |
| 71 | MCValue R; |
| 72 | R.Cst = Val; |
| 73 | R.SymA = nullptr; |
| 74 | R.SymB = nullptr; |
| 75 | R.RefKind = 0; |
| 76 | return R; |
| 77 | } |
| 78 | |
| 79 | }; |
| 80 | |
| 81 | } // end namespace llvm |
| 82 | |
| 83 | #endif |
| 1 | //===- MCSymbol.h - Machine Code Symbols ------------------------*- 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 MCSymbol class. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #ifndef LLVM_MC_MCSYMBOL_H |
| 14 | #define LLVM_MC_MCSYMBOL_H |
| 15 | |
| 16 | #include "llvm/ADT/PointerIntPair.h" |
| 17 | #include "llvm/ADT/StringMapEntry.h" |
| 18 | #include "llvm/ADT/StringRef.h" |
| 19 | #include "llvm/MC/MCExpr.h" |
| 20 | #include "llvm/MC/MCFragment.h" |
| 21 | #include "llvm/Support/ErrorHandling.h" |
| 22 | #include "llvm/Support/MathExtras.h" |
| 23 | #include <cassert> |
| 24 | #include <cstddef> |
| 25 | #include <cstdint> |
| 26 | |
| 27 | namespace llvm { |
| 28 | |
| 29 | class MCAsmInfo; |
| 30 | class MCContext; |
| 31 | class MCSection; |
| 32 | class raw_ostream; |
| 33 | |
| 34 | /// MCSymbol - Instances of this class represent a symbol name in the MC file, |
| 35 | /// and MCSymbols are created and uniqued by the MCContext class. MCSymbols |
| 36 | /// should only be constructed with valid names for the object file. |
| 37 | /// |
| 38 | /// If the symbol is defined/emitted into the current translation unit, the |
| 39 | /// Section member is set to indicate what section it lives in. Otherwise, if |
| 40 | /// it is a reference to an external entity, it has a null section. |
| 41 | class MCSymbol { |
| 42 | protected: |
| 43 | /// The kind of the symbol. If it is any value other than unset then this |
| 44 | /// class is actually one of the appropriate subclasses of MCSymbol. |
| 45 | enum SymbolKind { |
| 46 | SymbolKindUnset, |
| 47 | SymbolKindCOFF, |
| 48 | SymbolKindELF, |
| 49 | SymbolKindGOFF, |
| 50 | SymbolKindMachO, |
| 51 | SymbolKindWasm, |
| 52 | SymbolKindXCOFF, |
| 53 | }; |
| 54 | |
| 55 | /// A symbol can contain an Offset, or Value, or be Common, but never more |
| 56 | /// than one of these. |
| 57 | enum Contents : uint8_t { |
| 58 | SymContentsUnset, |
| 59 | SymContentsOffset, |
| 60 | SymContentsVariable, |
| 61 | SymContentsCommon, |
| 62 | SymContentsTargetCommon, // Index stores the section index |
| 63 | }; |
| 64 | |
| 65 | // Special sentinal value for the absolute pseudo fragment. |
| 66 | static MCFragment *AbsolutePseudoFragment; |
| 67 | |
| 68 | /// If a symbol has a Fragment, the section is implied, so we only need |
| 69 | /// one pointer. |
| 70 | /// The special AbsolutePseudoFragment value is for absolute symbols. |
| 71 | /// If this is a variable symbol, this caches the variable value's fragment. |
| 72 | /// FIXME: We might be able to simplify this by having the asm streamer create |
| 73 | /// dummy fragments. |
| 74 | /// If this is a section, then it gives the symbol is defined in. This is null |
| 75 | /// for undefined symbols. |
| 76 | /// |
| 77 | /// If this is a fragment, then it gives the fragment this symbol's value is |
| 78 | /// relative to, if any. |
| 79 | /// |
| 80 | /// For the 'HasName' integer, this is true if this symbol is named. |
| 81 | /// A named symbol will have a pointer to the name allocated in the bytes |
| 82 | /// immediately prior to the MCSymbol. |
| 83 | mutable PointerIntPair<MCFragment *, 1> FragmentAndHasName; |
| 84 | |
| 85 | /// IsTemporary - True if this is an assembler temporary label, which |
| 86 | /// typically does not survive in the .o file's symbol table. Usually |
| 87 | /// "Lfoo" or ".foo". |
| 88 | unsigned IsTemporary : 1; |
| 89 | |
| 90 | /// True if this symbol can be redefined. |
| 91 | unsigned IsRedefinable : 1; |
| 92 | |
| 93 | /// IsUsed - True if this symbol has been used. |
| 94 | mutable unsigned IsUsed : 1; |
| 95 | |
| 96 | mutable unsigned IsRegistered : 1; |
| 97 | |
| 98 | /// True if this symbol is visible outside this translation unit. Note: ELF |
| 99 | /// uses binding instead of this bit. |
| 100 | mutable unsigned IsExternal : 1; |
| 101 | |
| 102 | /// This symbol is private extern. |
| 103 | mutable unsigned IsPrivateExtern : 1; |
| 104 | |
| 105 | /// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is |
| 106 | /// unsigned to avoid sign extension and achieve better bitpacking with MSVC. |
| 107 | unsigned Kind : 3; |
| 108 | |
| 109 | /// True if we have created a relocation that uses this symbol. |
| 110 | mutable unsigned IsUsedInReloc : 1; |
| 111 | |
| 112 | /// This is actually a Contents enumerator, but is unsigned to avoid sign |
| 113 | /// extension and achieve better bitpacking with MSVC. |
| 114 | unsigned SymbolContents : 3; |
| 115 | |
| 116 | /// The alignment of the symbol if it is 'common'. |
| 117 | /// |
| 118 | /// Internally, this is stored as log2(align) + 1. |
| 119 | /// We reserve 5 bits to encode this value which allows the following values |
| 120 | /// 0b00000 -> unset |
| 121 | /// 0b00001 -> 1ULL << 0 = 1 |
| 122 | /// 0b00010 -> 1ULL << 1 = 2 |
| 123 | /// 0b00011 -> 1ULL << 2 = 4 |
| 124 | /// ... |
| 125 | /// 0b11111 -> 1ULL << 30 = 1 GiB |
| 126 | enum : unsigned { NumCommonAlignmentBits = 5 }; |
| 127 | unsigned CommonAlignLog2 : NumCommonAlignmentBits; |
| 128 | |
| 129 | /// The Flags field is used by object file implementations to store |
| 130 | /// additional per symbol information which is not easily classified. |
| 131 | enum : unsigned { NumFlagsBits = 16 }; |
| 132 | mutable uint32_t Flags : NumFlagsBits; |
| 133 | |
| 134 | /// Index field, for use by the object file implementation. |
| 135 | mutable uint32_t Index = 0; |
| 136 | |
| 137 | union { |
| 138 | /// The offset to apply to the fragment address to form this symbol's value. |
| 139 | uint64_t Offset; |
| 140 | |
| 141 | /// The size of the symbol, if it is 'common'. |
| 142 | uint64_t CommonSize; |
| 143 | |
| 144 | /// If non-null, the value for a variable symbol. |
| 145 | const MCExpr *Value; |
| 146 | }; |
| 147 | |
| 148 | // MCContext creates and uniques these. |
| 149 | friend class MCExpr; |
| 150 | friend class MCContext; |
| 151 | |
| 152 | /// The name for a symbol. |
| 153 | /// MCSymbol contains a uint64_t so is probably aligned to 8. On a 32-bit |
| 154 | /// system, the name is a pointer so isn't going to satisfy the 8 byte |
| 155 | /// alignment of uint64_t. Account for that here. |
| 156 | using NameEntryStorageTy = union { |
| 157 | const StringMapEntry<bool> *NameEntry; |
| 158 | uint64_t AlignmentPadding; |
| 159 | }; |
| 160 | |
| 161 | MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary) |
| 162 | : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false), |
| 163 | IsRegistered(false), IsExternal(false), IsPrivateExtern(false), |
| 164 | Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset), |
| 165 | CommonAlignLog2(0), Flags(0) { |
| 166 | Offset = 0; |
| 167 | FragmentAndHasName.setInt(!!Name); |
| 168 | if (Name) |
| 169 | getNameEntryPtr() = Name; |
| 170 | } |
| 171 | |
| 172 | // Provide custom new/delete as we will only allocate space for a name |
| 173 | // if we need one. |
| 174 | void *operator new(size_t s, const StringMapEntry<bool> *Name, |
| 175 | MCContext &Ctx); |
| 176 | |
| 177 | private: |
| 178 | void operator delete(void *); |
| 179 | /// Placement delete - required by std, but never called. |
| 180 | void operator delete(void*, unsigned) { |
| 181 | llvm_unreachable("Constructor throws?")::llvm::llvm_unreachable_internal("Constructor throws?", "llvm/include/llvm/MC/MCSymbol.h" , 181); |
| 182 | } |
| 183 | /// Placement delete - required by std, but never called. |
| 184 | void operator delete(void*, unsigned, bool) { |
| 185 | llvm_unreachable("Constructor throws?")::llvm::llvm_unreachable_internal("Constructor throws?", "llvm/include/llvm/MC/MCSymbol.h" , 185); |
| 186 | } |
| 187 | |
| 188 | /// Get a reference to the name field. Requires that we have a name |
| 189 | const StringMapEntry<bool> *&getNameEntryPtr() { |
| 190 | assert(FragmentAndHasName.getInt() && "Name is required")(static_cast <bool> (FragmentAndHasName.getInt() && "Name is required") ? void (0) : __assert_fail ("FragmentAndHasName.getInt() && \"Name is required\"" , "llvm/include/llvm/MC/MCSymbol.h", 190, __extension__ __PRETTY_FUNCTION__ )); |
| 191 | NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this); |
| 192 | return (*(Name - 1)).NameEntry; |
| 193 | } |
| 194 | const StringMapEntry<bool> *&getNameEntryPtr() const { |
| 195 | return const_cast<MCSymbol*>(this)->getNameEntryPtr(); |
| 196 | } |
| 197 | |
| 198 | public: |
| 199 | MCSymbol(const MCSymbol &) = delete; |
| 200 | MCSymbol &operator=(const MCSymbol &) = delete; |
| 201 | |
| 202 | /// getName - Get the symbol name. |
| 203 | StringRef getName() const { |
| 204 | if (!FragmentAndHasName.getInt()) |
| 205 | return StringRef(); |
| 206 | |
| 207 | return getNameEntryPtr()->first(); |
| 208 | } |
| 209 | |
| 210 | bool isRegistered() const { return IsRegistered; } |
| 211 | void setIsRegistered(bool Value) const { IsRegistered = Value; } |
| 212 | |
| 213 | void setUsedInReloc() const { IsUsedInReloc = true; } |
| 214 | bool isUsedInReloc() const { return IsUsedInReloc; } |
| 215 | |
| 216 | /// \name Accessors |
| 217 | /// @{ |
| 218 | |
| 219 | /// isTemporary - Check if this is an assembler temporary symbol. |
| 220 | bool isTemporary() const { return IsTemporary; } |
| 221 | |
| 222 | /// isUsed - Check if this is used. |
| 223 | bool isUsed() const { return IsUsed; } |
| 224 | |
| 225 | /// Check if this symbol is redefinable. |
| 226 | bool isRedefinable() const { return IsRedefinable; } |
| 227 | /// Mark this symbol as redefinable. |
| 228 | void setRedefinable(bool Value) { IsRedefinable = Value; } |
| 229 | /// Prepare this symbol to be redefined. |
| 230 | void redefineIfPossible() { |
| 231 | if (IsRedefinable) { |
| 232 | if (SymbolContents == SymContentsVariable) { |
| 233 | Value = nullptr; |
| 234 | SymbolContents = SymContentsUnset; |
| 235 | } |
| 236 | setUndefined(); |
| 237 | IsRedefinable = false; |
| 238 | } |
| 239 | } |
| 240 | |
| 241 | /// @} |
| 242 | /// \name Associated Sections |
| 243 | /// @{ |
| 244 | |
| 245 | /// isDefined - Check if this symbol is defined (i.e., it has an address). |
| 246 | /// |
| 247 | /// Defined symbols are either absolute or in some section. |
| 248 | bool isDefined() const { return !isUndefined(); } |
| 249 | |
| 250 | /// isInSection - Check if this symbol is defined in some section (i.e., it |
| 251 | /// is defined but not absolute). |
| 252 | bool isInSection() const { |
| 253 | return isDefined() && !isAbsolute(); |
| 254 | } |
| 255 | |
| 256 | /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). |
| 257 | bool isUndefined(bool SetUsed = true) const { |
| 258 | return getFragment(SetUsed) == nullptr; |
| 259 | } |
| 260 | |
| 261 | /// isAbsolute - Check if this is an absolute symbol. |
| 262 | bool isAbsolute() const { |
| 263 | return getFragment() == AbsolutePseudoFragment; |
| 264 | } |
| 265 | |
| 266 | /// Get the section associated with a defined, non-absolute symbol. |
| 267 | MCSection &getSection() const { |
| 268 | assert(isInSection() && "Invalid accessor!")(static_cast <bool> (isInSection() && "Invalid accessor!" ) ? void (0) : __assert_fail ("isInSection() && \"Invalid accessor!\"" , "llvm/include/llvm/MC/MCSymbol.h", 268, __extension__ __PRETTY_FUNCTION__ )); |
| 269 | return *getFragment()->getParent(); |
| 270 | } |
| 271 | |
| 272 | /// Mark the symbol as defined in the fragment \p F. |
| 273 | void setFragment(MCFragment *F) const { |
| 274 | assert(!isVariable() && "Cannot set fragment of variable")(static_cast <bool> (!isVariable() && "Cannot set fragment of variable" ) ? void (0) : __assert_fail ("!isVariable() && \"Cannot set fragment of variable\"" , "llvm/include/llvm/MC/MCSymbol.h", 274, __extension__ __PRETTY_FUNCTION__ )); |
| 275 | FragmentAndHasName.setPointer(F); |
| 276 | } |
| 277 | |
| 278 | /// Mark the symbol as undefined. |
| 279 | void setUndefined() { FragmentAndHasName.setPointer(nullptr); } |
| 280 | |
| 281 | bool isELF() const { return Kind == SymbolKindELF; } |
| 282 | |
| 283 | bool isCOFF() const { return Kind == SymbolKindCOFF; } |
| 284 | |
| 285 | bool isGOFF() const { return Kind == SymbolKindGOFF; } |
| 286 | |
| 287 | bool isMachO() const { return Kind == SymbolKindMachO; } |
| 288 | |
| 289 | bool isWasm() const { return Kind == SymbolKindWasm; } |
| 290 | |
| 291 | bool isXCOFF() const { return Kind == SymbolKindXCOFF; } |
| 292 | |
| 293 | /// @} |
| 294 | /// \name Variable Symbols |
| 295 | /// @{ |
| 296 | |
| 297 | /// isVariable - Check if this is a variable symbol. |
| 298 | bool isVariable() const { |
| 299 | return SymbolContents == SymContentsVariable; |
| 300 | } |
| 301 | |
| 302 | /// getVariableValue - Get the value for variable symbols. |
| 303 | const MCExpr *getVariableValue(bool SetUsed = true) const { |
| 304 | assert(isVariable() && "Invalid accessor!")(static_cast <bool> (isVariable() && "Invalid accessor!" ) ? void (0) : __assert_fail ("isVariable() && \"Invalid accessor!\"" , "llvm/include/llvm/MC/MCSymbol.h", 304, __extension__ __PRETTY_FUNCTION__ )); |
| 305 | IsUsed |= SetUsed; |
| 306 | return Value; |
| 307 | } |
| 308 | |
| 309 | void setVariableValue(const MCExpr *Value); |
| 310 | |
| 311 | /// @} |
| 312 | |
| 313 | /// Get the (implementation defined) index. |
| 314 | uint32_t getIndex() const { |
| 315 | return Index; |
| 316 | } |
| 317 | |
| 318 | /// Set the (implementation defined) index. |
| 319 | void setIndex(uint32_t Value) const { |
| 320 | Index = Value; |
| 321 | } |
| 322 | |
| 323 | bool isUnset() const { return SymbolContents == SymContentsUnset; } |
| 324 | |
| 325 | uint64_t getOffset() const { |
| 326 | assert((SymbolContents == SymContentsUnset ||(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot get offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot get offset for a common/variable symbol\"" , "llvm/include/llvm/MC/MCSymbol.h", 328, __extension__ __PRETTY_FUNCTION__ )) |
| 327 | SymbolContents == SymContentsOffset) &&(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot get offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot get offset for a common/variable symbol\"" , "llvm/include/llvm/MC/MCSymbol.h", 328, __extension__ __PRETTY_FUNCTION__ )) |
| 328 | "Cannot get offset for a common/variable symbol")(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot get offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot get offset for a common/variable symbol\"" , "llvm/include/llvm/MC/MCSymbol.h", 328, __extension__ __PRETTY_FUNCTION__ )); |
| 329 | return Offset; |
| 330 | } |
| 331 | void setOffset(uint64_t Value) { |
| 332 | assert((SymbolContents == SymContentsUnset ||(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot set offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot set offset for a common/variable symbol\"" , "llvm/include/llvm/MC/MCSymbol.h", 334, __extension__ __PRETTY_FUNCTION__ )) |
| 333 | SymbolContents == SymContentsOffset) &&(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot set offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot set offset for a common/variable symbol\"" , "llvm/include/llvm/MC/MCSymbol.h", 334, __extension__ __PRETTY_FUNCTION__ )) |
| 334 | "Cannot set offset for a common/variable symbol")(static_cast <bool> ((SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && "Cannot set offset for a common/variable symbol" ) ? void (0) : __assert_fail ("(SymbolContents == SymContentsUnset || SymbolContents == SymContentsOffset) && \"Cannot set offset for a common/variable symbol\"" , "llvm/include/llvm/MC/MCSymbol.h", 334, __extension__ __PRETTY_FUNCTION__ )); |
| 335 | Offset = Value; |
| 336 | SymbolContents = SymContentsOffset; |
| 337 | } |
| 338 | |
| 339 | /// Return the size of a 'common' symbol. |
| 340 | uint64_t getCommonSize() const { |
| 341 | assert(isCommon() && "Not a 'common' symbol!")(static_cast <bool> (isCommon() && "Not a 'common' symbol!" ) ? void (0) : __assert_fail ("isCommon() && \"Not a 'common' symbol!\"" , "llvm/include/llvm/MC/MCSymbol.h", 341, __extension__ __PRETTY_FUNCTION__ )); |
| 342 | return CommonSize; |
| 343 | } |
| 344 | |
| 345 | /// Mark this symbol as being 'common'. |
| 346 | /// |
| 347 | /// \param Size - The size of the symbol. |
| 348 | /// \param Alignment - The alignment of the symbol. |
| 349 | /// \param Target - Is the symbol a target-specific common-like symbol. |
| 350 | void setCommon(uint64_t Size, Align Alignment, bool Target = false) { |
| 351 | assert(getOffset() == 0)(static_cast <bool> (getOffset() == 0) ? void (0) : __assert_fail ("getOffset() == 0", "llvm/include/llvm/MC/MCSymbol.h", 351, __extension__ __PRETTY_FUNCTION__)); |
| 352 | CommonSize = Size; |
| 353 | SymbolContents = Target ? SymContentsTargetCommon : SymContentsCommon; |
| 354 | |
| 355 | unsigned Log2Align = encode(Alignment); |
| 356 | assert(Log2Align < (1U << NumCommonAlignmentBits) &&(static_cast <bool> (Log2Align < (1U << NumCommonAlignmentBits ) && "Out of range alignment") ? void (0) : __assert_fail ("Log2Align < (1U << NumCommonAlignmentBits) && \"Out of range alignment\"" , "llvm/include/llvm/MC/MCSymbol.h", 357, __extension__ __PRETTY_FUNCTION__ )) |
| 357 | "Out of range alignment")(static_cast <bool> (Log2Align < (1U << NumCommonAlignmentBits ) && "Out of range alignment") ? void (0) : __assert_fail ("Log2Align < (1U << NumCommonAlignmentBits) && \"Out of range alignment\"" , "llvm/include/llvm/MC/MCSymbol.h", 357, __extension__ __PRETTY_FUNCTION__ )); |
| 358 | CommonAlignLog2 = Log2Align; |
| 359 | } |
| 360 | |
| 361 | /// Return the alignment of a 'common' symbol. |
| 362 | MaybeAlign getCommonAlignment() const { |
| 363 | assert(isCommon() && "Not a 'common' symbol!")(static_cast <bool> (isCommon() && "Not a 'common' symbol!" ) ? void (0) : __assert_fail ("isCommon() && \"Not a 'common' symbol!\"" , "llvm/include/llvm/MC/MCSymbol.h", 363, __extension__ __PRETTY_FUNCTION__ )); |
| 364 | return decodeMaybeAlign(CommonAlignLog2); |
| 365 | } |
| 366 | |
| 367 | /// Declare this symbol as being 'common'. |
| 368 | /// |
| 369 | /// \param Size - The size of the symbol. |
| 370 | /// \param Alignment - The alignment of the symbol. |
| 371 | /// \param Target - Is the symbol a target-specific common-like symbol. |
| 372 | /// \return True if symbol was already declared as a different type |
| 373 | bool declareCommon(uint64_t Size, Align Alignment, bool Target = false) { |
| 374 | assert(isCommon() || getOffset() == 0)(static_cast <bool> (isCommon() || getOffset() == 0) ? void (0) : __assert_fail ("isCommon() || getOffset() == 0", "llvm/include/llvm/MC/MCSymbol.h" , 374, __extension__ __PRETTY_FUNCTION__)); |
| 375 | if(isCommon()) { |
| 376 | if (CommonSize != Size || getCommonAlignment() != Alignment || |
| 377 | isTargetCommon() != Target) |
| 378 | return true; |
| 379 | } else |
| 380 | setCommon(Size, Alignment, Target); |
| 381 | return false; |
| 382 | } |
| 383 | |
| 384 | /// Is this a 'common' symbol. |
| 385 | bool isCommon() const { |
| 386 | return SymbolContents == SymContentsCommon || |
| 387 | SymbolContents == SymContentsTargetCommon; |
| 388 | } |
| 389 | |
| 390 | /// Is this a target-specific common-like symbol. |
| 391 | bool isTargetCommon() const { |
| 392 | return SymbolContents == SymContentsTargetCommon; |
| 393 | } |
| 394 | |
| 395 | MCFragment *getFragment(bool SetUsed = true) const { |
| 396 | MCFragment *Fragment = FragmentAndHasName.getPointer(); |
| 397 | if (Fragment || !isVariable()) |
| 398 | return Fragment; |
| 399 | Fragment = getVariableValue(SetUsed)->findAssociatedFragment(); |
| 400 | FragmentAndHasName.setPointer(Fragment); |
| 401 | return Fragment; |
| 402 | } |
| 403 | |
| 404 | bool isExternal() const { return IsExternal; } |
| 405 | void setExternal(bool Value) const { IsExternal = Value; } |
| 406 | |
| 407 | bool isPrivateExtern() const { return IsPrivateExtern; } |
| 408 | void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } |
| 409 | |
| 410 | /// print - Print the value to the stream \p OS. |
| 411 | void print(raw_ostream &OS, const MCAsmInfo *MAI) const; |
| 412 | |
| 413 | /// dump - Print the value to stderr. |
| 414 | void dump() const; |
| 415 | |
| 416 | protected: |
| 417 | /// Get the (implementation defined) symbol flags. |
| 418 | uint32_t getFlags() const { return Flags; } |
| 419 | |
| 420 | /// Set the (implementation defined) symbol flags. |
| 421 | void setFlags(uint32_t Value) const { |
| 422 | assert(Value < (1U << NumFlagsBits) && "Out of range flags")(static_cast <bool> (Value < (1U << NumFlagsBits ) && "Out of range flags") ? void (0) : __assert_fail ("Value < (1U << NumFlagsBits) && \"Out of range flags\"" , "llvm/include/llvm/MC/MCSymbol.h", 422, __extension__ __PRETTY_FUNCTION__ )); |
| 423 | Flags = Value; |
| 424 | } |
| 425 | |
| 426 | /// Modify the flags via a mask |
| 427 | void modifyFlags(uint32_t Value, uint32_t Mask) const { |
| 428 | assert(Value < (1U << NumFlagsBits) && "Out of range flags")(static_cast <bool> (Value < (1U << NumFlagsBits ) && "Out of range flags") ? void (0) : __assert_fail ("Value < (1U << NumFlagsBits) && \"Out of range flags\"" , "llvm/include/llvm/MC/MCSymbol.h", 428, __extension__ __PRETTY_FUNCTION__ )); |
| 429 | Flags = (Flags & ~Mask) | Value; |
| 430 | } |
| 431 | }; |
| 432 | |
| 433 | inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { |
| 434 | Sym.print(OS, nullptr); |
| 435 | return OS; |
| 436 | } |
| 437 | |
| 438 | } // end namespace llvm |
| 439 | |
| 440 | #endif // LLVM_MC_MCSYMBOL_H |