File indexing completed on 2026-05-10 08:43:54
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_EXECUTIONENGINE_JITSYMBOL_H
0014 #define LLVM_EXECUTIONENGINE_JITSYMBOL_H
0015
0016 #include <algorithm>
0017 #include <cassert>
0018 #include <cstddef>
0019 #include <cstdint>
0020 #include <functional>
0021 #include <map>
0022 #include <set>
0023 #include <string>
0024
0025 #include "llvm/ADT/BitmaskEnum.h"
0026 #include "llvm/ADT/FunctionExtras.h"
0027 #include "llvm/ADT/StringRef.h"
0028 #include "llvm/Support/Error.h"
0029
0030 namespace llvm {
0031
0032 class GlobalValue;
0033 class GlobalValueSummary;
0034
0035 namespace object {
0036
0037 class SymbolRef;
0038
0039 }
0040
0041
0042 using JITTargetAddress = uint64_t;
0043
0044
0045
0046
0047
0048
0049
0050 template <typename T> T jitTargetAddressToPointer(JITTargetAddress Addr) {
0051 static_assert(std::is_pointer<T>::value, "T must be a pointer type");
0052 uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
0053 assert(IntPtr == Addr && "JITTargetAddress value out of range for uintptr_t");
0054 return reinterpret_cast<T>(IntPtr);
0055 }
0056
0057
0058
0059
0060
0061 template <typename T> T jitTargetAddressToFunction(JITTargetAddress Addr) {
0062 static_assert(std::is_pointer<T>::value &&
0063 std::is_function<std::remove_pointer_t<T>>::value,
0064 "T must be a function pointer type");
0065 return jitTargetAddressToPointer<T>(Addr);
0066 }
0067
0068
0069 template <typename T> JITTargetAddress pointerToJITTargetAddress(T *Ptr) {
0070 return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Ptr));
0071 }
0072
0073
0074 class JITSymbolFlags {
0075 public:
0076 using UnderlyingType = uint8_t;
0077 using TargetFlagsType = uint8_t;
0078
0079 enum FlagNames : UnderlyingType {
0080 None = 0,
0081 HasError = 1U << 0,
0082 Weak = 1U << 1,
0083 Common = 1U << 2,
0084 Absolute = 1U << 3,
0085 Exported = 1U << 4,
0086 Callable = 1U << 5,
0087 MaterializationSideEffectsOnly = 1U << 6,
0088 LLVM_MARK_AS_BITMASK_ENUM(
0089 MaterializationSideEffectsOnly)
0090 };
0091
0092
0093 JITSymbolFlags() = default;
0094
0095
0096 JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
0097
0098
0099
0100 JITSymbolFlags(FlagNames Flags, TargetFlagsType TargetFlags)
0101 : TargetFlags(TargetFlags), Flags(Flags) {}
0102
0103
0104 explicit operator bool() const { return Flags != None || TargetFlags != 0; }
0105
0106
0107 bool operator==(const JITSymbolFlags &RHS) const {
0108 return Flags == RHS.Flags && TargetFlags == RHS.TargetFlags;
0109 }
0110
0111
0112 JITSymbolFlags &operator&=(const FlagNames &RHS) {
0113 Flags &= RHS;
0114 return *this;
0115 }
0116
0117
0118 JITSymbolFlags &operator|=(const FlagNames &RHS) {
0119 Flags |= RHS;
0120 return *this;
0121 }
0122
0123
0124 bool hasError() const {
0125 return (Flags & HasError) == HasError;
0126 }
0127
0128
0129 bool isWeak() const {
0130 return (Flags & Weak) == Weak;
0131 }
0132
0133
0134 bool isCommon() const {
0135 return (Flags & Common) == Common;
0136 }
0137
0138
0139 bool isStrong() const {
0140 return !isWeak() && !isCommon();
0141 }
0142
0143
0144 bool isExported() const {
0145 return (Flags & Exported) == Exported;
0146 }
0147
0148
0149 bool isCallable() const { return (Flags & Callable) == Callable; }
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 bool hasMaterializationSideEffectsOnly() const {
0162 return (Flags & MaterializationSideEffectsOnly) ==
0163 MaterializationSideEffectsOnly;
0164 }
0165
0166
0167 UnderlyingType getRawFlagsValue() const {
0168 return static_cast<UnderlyingType>(Flags);
0169 }
0170
0171
0172 TargetFlagsType& getTargetFlags() { return TargetFlags; }
0173
0174
0175 const TargetFlagsType& getTargetFlags() const { return TargetFlags; }
0176
0177
0178
0179 static JITSymbolFlags fromGlobalValue(const GlobalValue &GV);
0180
0181
0182
0183 static JITSymbolFlags fromSummary(GlobalValueSummary *S);
0184
0185
0186
0187 static Expected<JITSymbolFlags>
0188 fromObjectSymbol(const object::SymbolRef &Symbol);
0189
0190 private:
0191 TargetFlagsType TargetFlags = 0;
0192 FlagNames Flags = None;
0193 };
0194
0195 inline JITSymbolFlags operator&(const JITSymbolFlags &LHS,
0196 const JITSymbolFlags::FlagNames &RHS) {
0197 JITSymbolFlags Tmp = LHS;
0198 Tmp &= RHS;
0199 return Tmp;
0200 }
0201
0202 inline JITSymbolFlags operator|(const JITSymbolFlags &LHS,
0203 const JITSymbolFlags::FlagNames &RHS) {
0204 JITSymbolFlags Tmp = LHS;
0205 Tmp |= RHS;
0206 return Tmp;
0207 }
0208
0209
0210
0211 class ARMJITSymbolFlags {
0212 public:
0213 ARMJITSymbolFlags() = default;
0214
0215 enum FlagNames {
0216 None = 0,
0217 Thumb = 1 << 0
0218 };
0219
0220 operator JITSymbolFlags::TargetFlagsType&() { return Flags; }
0221
0222 static ARMJITSymbolFlags fromObjectSymbol(const object::SymbolRef &Symbol);
0223
0224 private:
0225 JITSymbolFlags::TargetFlagsType Flags = 0;
0226 };
0227
0228
0229 class JITEvaluatedSymbol {
0230 public:
0231 JITEvaluatedSymbol() = default;
0232
0233
0234 JITEvaluatedSymbol(std::nullptr_t) {}
0235
0236
0237 JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags)
0238 : Address(Address), Flags(Flags) {}
0239
0240
0241 template <typename T>
0242 static JITEvaluatedSymbol
0243 fromPointer(T *P, JITSymbolFlags Flags = JITSymbolFlags::Exported) {
0244 return JITEvaluatedSymbol(pointerToJITTargetAddress(P), Flags);
0245 }
0246
0247
0248 explicit operator bool() const { return Address != 0; }
0249
0250
0251 JITTargetAddress getAddress() const { return Address; }
0252
0253
0254 JITSymbolFlags getFlags() const { return Flags; }
0255
0256
0257 void setFlags(JITSymbolFlags Flags) { this->Flags = std::move(Flags); }
0258
0259 private:
0260 JITTargetAddress Address = 0;
0261 JITSymbolFlags Flags;
0262 };
0263
0264
0265 class JITSymbol {
0266 public:
0267 using GetAddressFtor = unique_function<Expected<JITTargetAddress>()>;
0268
0269
0270
0271 JITSymbol(std::nullptr_t)
0272 : CachedAddr(0) {}
0273
0274
0275
0276 JITSymbol(Error Err)
0277 : Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {}
0278
0279
0280 JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
0281 : CachedAddr(Addr), Flags(Flags) {}
0282
0283
0284 JITSymbol(JITEvaluatedSymbol Sym)
0285 : CachedAddr(Sym.getAddress()), Flags(Sym.getFlags()) {}
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296 JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
0297 : GetAddress(std::move(GetAddress)), CachedAddr(0), Flags(Flags) {}
0298
0299 JITSymbol(const JITSymbol&) = delete;
0300 JITSymbol& operator=(const JITSymbol&) = delete;
0301
0302 JITSymbol(JITSymbol &&Other)
0303 : GetAddress(std::move(Other.GetAddress)), Flags(std::move(Other.Flags)) {
0304 if (Flags.hasError())
0305 Err = std::move(Other.Err);
0306 else
0307 CachedAddr = std::move(Other.CachedAddr);
0308 }
0309
0310 JITSymbol& operator=(JITSymbol &&Other) {
0311 GetAddress = std::move(Other.GetAddress);
0312 Flags = std::move(Other.Flags);
0313 if (Flags.hasError())
0314 Err = std::move(Other.Err);
0315 else
0316 CachedAddr = std::move(Other.CachedAddr);
0317 return *this;
0318 }
0319
0320 ~JITSymbol() {
0321 if (Flags.hasError())
0322 Err.~Error();
0323 else
0324 CachedAddr.~JITTargetAddress();
0325 }
0326
0327
0328 explicit operator bool() const {
0329 return !Flags.hasError() && (CachedAddr || GetAddress);
0330 }
0331
0332
0333 Error takeError() {
0334 if (Flags.hasError())
0335 return std::move(Err);
0336 return Error::success();
0337 }
0338
0339
0340
0341 Expected<JITTargetAddress> getAddress() {
0342 assert(!Flags.hasError() && "getAddress called on error value");
0343 if (GetAddress) {
0344 if (auto CachedAddrOrErr = GetAddress()) {
0345 GetAddress = nullptr;
0346 CachedAddr = *CachedAddrOrErr;
0347 assert(CachedAddr && "Symbol could not be materialized.");
0348 } else
0349 return CachedAddrOrErr.takeError();
0350 }
0351 return CachedAddr;
0352 }
0353
0354 JITSymbolFlags getFlags() const { return Flags; }
0355
0356 private:
0357 GetAddressFtor GetAddress;
0358 union {
0359 JITTargetAddress CachedAddr;
0360 Error Err;
0361 };
0362 JITSymbolFlags Flags;
0363 };
0364
0365
0366
0367
0368
0369
0370
0371 class JITSymbolResolver {
0372 public:
0373 using LookupSet = std::set<StringRef>;
0374 using LookupResult = std::map<StringRef, JITEvaluatedSymbol>;
0375 using OnResolvedFunction = unique_function<void(Expected<LookupResult>)>;
0376
0377 virtual ~JITSymbolResolver() = default;
0378
0379
0380
0381
0382
0383
0384 virtual void lookup(const LookupSet &Symbols,
0385 OnResolvedFunction OnResolved) = 0;
0386
0387
0388
0389
0390 virtual Expected<LookupSet>
0391 getResponsibilitySet(const LookupSet &Symbols) = 0;
0392
0393
0394 virtual bool allowsZeroSymbols() { return false; }
0395
0396 private:
0397 virtual void anchor();
0398 };
0399
0400
0401 class LegacyJITSymbolResolver : public JITSymbolResolver {
0402 public:
0403
0404
0405
0406 void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) final;
0407
0408
0409
0410 Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) final;
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424 virtual JITSymbol findSymbolInLogicalDylib(const std::string &Name) = 0;
0425
0426
0427
0428
0429
0430
0431
0432 virtual JITSymbol findSymbol(const std::string &Name) = 0;
0433
0434 private:
0435 void anchor() override;
0436 };
0437
0438 }
0439
0440 #endif