File: | llvm/include/llvm/ADT/FunctionExtras.h |
Warning: | line 190, column 3 Potential memory leak |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-------- OrcMCJITReplacement.cpp - Orc-based MCJIT replacement -------===// | |||
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 "OrcMCJITReplacement.h" | |||
10 | #include "llvm/ExecutionEngine/GenericValue.h" | |||
11 | ||||
12 | namespace { | |||
13 | ||||
14 | static struct RegisterJIT { | |||
15 | RegisterJIT() { llvm::orc::OrcMCJITReplacement::Register(); } | |||
16 | } JITRegistrator; | |||
17 | ||||
18 | } | |||
19 | ||||
20 | extern "C" void LLVMLinkInOrcMCJITReplacement() {} | |||
21 | ||||
22 | namespace llvm { | |||
23 | namespace orc { | |||
24 | ||||
25 | GenericValue | |||
26 | OrcMCJITReplacement::runFunction(Function *F, | |||
27 | ArrayRef<GenericValue> ArgValues) { | |||
28 | assert(F && "Function *F was null at entry to run()")((F && "Function *F was null at entry to run()") ? static_cast <void> (0) : __assert_fail ("F && \"Function *F was null at entry to run()\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 28, __PRETTY_FUNCTION__)); | |||
| ||||
29 | ||||
30 | void *FPtr = getPointerToFunction(F); | |||
31 | assert(FPtr && "Pointer to fn's code was null after getPointerToFunction")((FPtr && "Pointer to fn's code was null after getPointerToFunction" ) ? static_cast<void> (0) : __assert_fail ("FPtr && \"Pointer to fn's code was null after getPointerToFunction\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 31, __PRETTY_FUNCTION__)); | |||
32 | FunctionType *FTy = F->getFunctionType(); | |||
33 | Type *RetTy = FTy->getReturnType(); | |||
34 | ||||
35 | assert((FTy->getNumParams() == ArgValues.size() ||(((FTy->getNumParams() == ArgValues.size() || (FTy->isVarArg () && FTy->getNumParams() <= ArgValues.size())) && "Wrong number of arguments passed into function!" ) ? static_cast<void> (0) : __assert_fail ("(FTy->getNumParams() == ArgValues.size() || (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && \"Wrong number of arguments passed into function!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 37, __PRETTY_FUNCTION__)) | |||
36 | (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&(((FTy->getNumParams() == ArgValues.size() || (FTy->isVarArg () && FTy->getNumParams() <= ArgValues.size())) && "Wrong number of arguments passed into function!" ) ? static_cast<void> (0) : __assert_fail ("(FTy->getNumParams() == ArgValues.size() || (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && \"Wrong number of arguments passed into function!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 37, __PRETTY_FUNCTION__)) | |||
37 | "Wrong number of arguments passed into function!")(((FTy->getNumParams() == ArgValues.size() || (FTy->isVarArg () && FTy->getNumParams() <= ArgValues.size())) && "Wrong number of arguments passed into function!" ) ? static_cast<void> (0) : __assert_fail ("(FTy->getNumParams() == ArgValues.size() || (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) && \"Wrong number of arguments passed into function!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 37, __PRETTY_FUNCTION__)); | |||
38 | assert(FTy->getNumParams() == ArgValues.size() &&((FTy->getNumParams() == ArgValues.size() && "This doesn't support passing arguments through varargs (yet)!" ) ? static_cast<void> (0) : __assert_fail ("FTy->getNumParams() == ArgValues.size() && \"This doesn't support passing arguments through varargs (yet)!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 39, __PRETTY_FUNCTION__)) | |||
39 | "This doesn't support passing arguments through varargs (yet)!")((FTy->getNumParams() == ArgValues.size() && "This doesn't support passing arguments through varargs (yet)!" ) ? static_cast<void> (0) : __assert_fail ("FTy->getNumParams() == ArgValues.size() && \"This doesn't support passing arguments through varargs (yet)!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 39, __PRETTY_FUNCTION__)); | |||
40 | ||||
41 | // Handle some common cases first. These cases correspond to common `main' | |||
42 | // prototypes. | |||
43 | if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) { | |||
44 | switch (ArgValues.size()) { | |||
45 | case 3: | |||
46 | if (FTy->getParamType(0)->isIntegerTy(32) && | |||
47 | FTy->getParamType(1)->isPointerTy() && | |||
48 | FTy->getParamType(2)->isPointerTy()) { | |||
49 | int (*PF)(int, char **, const char **) = | |||
50 | (int (*)(int, char **, const char **))(intptr_t)FPtr; | |||
51 | ||||
52 | // Call the function. | |||
53 | GenericValue rv; | |||
54 | rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), | |||
55 | (char **)GVTOP(ArgValues[1]), | |||
56 | (const char **)GVTOP(ArgValues[2]))); | |||
57 | return rv; | |||
58 | } | |||
59 | break; | |||
60 | case 2: | |||
61 | if (FTy->getParamType(0)->isIntegerTy(32) && | |||
62 | FTy->getParamType(1)->isPointerTy()) { | |||
63 | int (*PF)(int, char **) = (int (*)(int, char **))(intptr_t)FPtr; | |||
64 | ||||
65 | // Call the function. | |||
66 | GenericValue rv; | |||
67 | rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(), | |||
68 | (char **)GVTOP(ArgValues[1]))); | |||
69 | return rv; | |||
70 | } | |||
71 | break; | |||
72 | case 1: | |||
73 | if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) { | |||
74 | GenericValue rv; | |||
75 | int (*PF)(int) = (int (*)(int))(intptr_t)FPtr; | |||
76 | rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); | |||
77 | return rv; | |||
78 | } | |||
79 | break; | |||
80 | } | |||
81 | } | |||
82 | ||||
83 | // Handle cases where no arguments are passed first. | |||
84 | if (ArgValues.empty()) { | |||
85 | GenericValue rv; | |||
86 | switch (RetTy->getTypeID()) { | |||
87 | default: | |||
88 | llvm_unreachable("Unknown return type for function call!")::llvm::llvm_unreachable_internal("Unknown return type for function call!" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 88); | |||
89 | case Type::IntegerTyID: { | |||
90 | unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth(); | |||
91 | if (BitWidth == 1) | |||
92 | rv.IntVal = APInt(BitWidth, ((bool (*)())(intptr_t)FPtr)()); | |||
93 | else if (BitWidth <= 8) | |||
94 | rv.IntVal = APInt(BitWidth, ((char (*)())(intptr_t)FPtr)()); | |||
95 | else if (BitWidth <= 16) | |||
96 | rv.IntVal = APInt(BitWidth, ((short (*)())(intptr_t)FPtr)()); | |||
97 | else if (BitWidth <= 32) | |||
98 | rv.IntVal = APInt(BitWidth, ((int (*)())(intptr_t)FPtr)()); | |||
99 | else if (BitWidth <= 64) | |||
100 | rv.IntVal = APInt(BitWidth, ((int64_t (*)())(intptr_t)FPtr)()); | |||
101 | else | |||
102 | llvm_unreachable("Integer types > 64 bits not supported")::llvm::llvm_unreachable_internal("Integer types > 64 bits not supported" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 102); | |||
103 | return rv; | |||
104 | } | |||
105 | case Type::VoidTyID: | |||
106 | rv.IntVal = APInt(32, ((int (*)())(intptr_t)FPtr)()); | |||
107 | return rv; | |||
108 | case Type::FloatTyID: | |||
109 | rv.FloatVal = ((float (*)())(intptr_t)FPtr)(); | |||
110 | return rv; | |||
111 | case Type::DoubleTyID: | |||
112 | rv.DoubleVal = ((double (*)())(intptr_t)FPtr)(); | |||
113 | return rv; | |||
114 | case Type::X86_FP80TyID: | |||
115 | case Type::FP128TyID: | |||
116 | case Type::PPC_FP128TyID: | |||
117 | llvm_unreachable("long double not supported yet")::llvm::llvm_unreachable_internal("long double not supported yet" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 117); | |||
118 | case Type::PointerTyID: | |||
119 | return PTOGV(((void *(*)())(intptr_t)FPtr)()); | |||
120 | } | |||
121 | } | |||
122 | ||||
123 | llvm_unreachable("Full-featured argument passing not supported yet!")::llvm::llvm_unreachable_internal("Full-featured argument passing not supported yet!" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.cpp" , 123); | |||
124 | } | |||
125 | ||||
126 | void OrcMCJITReplacement::runStaticConstructorsDestructors(bool isDtors) { | |||
127 | auto &CtorDtorsMap = isDtors ? UnexecutedDestructors : UnexecutedConstructors; | |||
128 | ||||
129 | for (auto &KV : CtorDtorsMap) | |||
130 | cantFail(LegacyCtorDtorRunner<LazyEmitLayerT>( | |||
131 | AcknowledgeORCv1Deprecation, std::move(KV.second), KV.first) | |||
132 | .runViaLayer(LazyEmitLayer)); | |||
133 | ||||
134 | CtorDtorsMap.clear(); | |||
135 | } | |||
136 | ||||
137 | } // End namespace orc. | |||
138 | } // End namespace llvm. |
1 | //===- OrcMCJITReplacement.h - Orc based MCJIT replacement ------*- 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 | // Orc based MCJIT replacement. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H |
14 | #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H |
15 | |
16 | #include "llvm/ADT/ArrayRef.h" |
17 | #include "llvm/ADT/STLExtras.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/ExecutionEngine/ExecutionEngine.h" |
20 | #include "llvm/ExecutionEngine/GenericValue.h" |
21 | #include "llvm/ExecutionEngine/JITSymbol.h" |
22 | #include "llvm/ExecutionEngine/Orc/CompileUtils.h" |
23 | #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" |
24 | #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" |
25 | #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" |
26 | #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" |
27 | #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" |
28 | #include "llvm/ExecutionEngine/RuntimeDyld.h" |
29 | #include "llvm/IR/DataLayout.h" |
30 | #include "llvm/IR/Function.h" |
31 | #include "llvm/IR/Mangler.h" |
32 | #include "llvm/IR/Module.h" |
33 | #include "llvm/Object/Archive.h" |
34 | #include "llvm/Object/Binary.h" |
35 | #include "llvm/Object/ObjectFile.h" |
36 | #include "llvm/Support/Error.h" |
37 | #include "llvm/Support/ErrorHandling.h" |
38 | #include "llvm/Support/raw_ostream.h" |
39 | #include "llvm/Target/TargetMachine.h" |
40 | #include <algorithm> |
41 | #include <cassert> |
42 | #include <cstddef> |
43 | #include <cstdint> |
44 | #include <map> |
45 | #include <memory> |
46 | #include <set> |
47 | #include <string> |
48 | #include <vector> |
49 | |
50 | namespace llvm { |
51 | |
52 | class ObjectCache; |
53 | |
54 | namespace orc { |
55 | |
56 | class OrcMCJITReplacement : public ExecutionEngine { |
57 | |
58 | // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that |
59 | // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are |
60 | // expecting - see finalizeMemory. |
61 | class MCJITReplacementMemMgr : public MCJITMemoryManager { |
62 | public: |
63 | MCJITReplacementMemMgr(OrcMCJITReplacement &M, |
64 | std::shared_ptr<MCJITMemoryManager> ClientMM) |
65 | : M(M), ClientMM(std::move(ClientMM)) {} |
66 | |
67 | uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, |
68 | unsigned SectionID, |
69 | StringRef SectionName) override { |
70 | uint8_t *Addr = |
71 | ClientMM->allocateCodeSection(Size, Alignment, SectionID, |
72 | SectionName); |
73 | M.SectionsAllocatedSinceLastLoad.insert(Addr); |
74 | return Addr; |
75 | } |
76 | |
77 | uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, |
78 | unsigned SectionID, StringRef SectionName, |
79 | bool IsReadOnly) override { |
80 | uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID, |
81 | SectionName, IsReadOnly); |
82 | M.SectionsAllocatedSinceLastLoad.insert(Addr); |
83 | return Addr; |
84 | } |
85 | |
86 | void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, |
87 | uintptr_t RODataSize, uint32_t RODataAlign, |
88 | uintptr_t RWDataSize, |
89 | uint32_t RWDataAlign) override { |
90 | return ClientMM->reserveAllocationSpace(CodeSize, CodeAlign, |
91 | RODataSize, RODataAlign, |
92 | RWDataSize, RWDataAlign); |
93 | } |
94 | |
95 | bool needsToReserveAllocationSpace() override { |
96 | return ClientMM->needsToReserveAllocationSpace(); |
97 | } |
98 | |
99 | void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, |
100 | size_t Size) override { |
101 | return ClientMM->registerEHFrames(Addr, LoadAddr, Size); |
102 | } |
103 | |
104 | void deregisterEHFrames() override { |
105 | return ClientMM->deregisterEHFrames(); |
106 | } |
107 | |
108 | void notifyObjectLoaded(RuntimeDyld &RTDyld, |
109 | const object::ObjectFile &O) override { |
110 | return ClientMM->notifyObjectLoaded(RTDyld, O); |
111 | } |
112 | |
113 | void notifyObjectLoaded(ExecutionEngine *EE, |
114 | const object::ObjectFile &O) override { |
115 | return ClientMM->notifyObjectLoaded(EE, O); |
116 | } |
117 | |
118 | bool finalizeMemory(std::string *ErrMsg = nullptr) override { |
119 | // Each set of objects loaded will be finalized exactly once, but since |
120 | // symbol lookup during relocation may recursively trigger the |
121 | // loading/relocation of other modules, and since we're forwarding all |
122 | // finalizeMemory calls to a single underlying memory manager, we need to |
123 | // defer forwarding the call on until all necessary objects have been |
124 | // loaded. Otherwise, during the relocation of a leaf object, we will end |
125 | // up finalizing memory, causing a crash further up the stack when we |
126 | // attempt to apply relocations to finalized memory. |
127 | // To avoid finalizing too early, look at how many objects have been |
128 | // loaded but not yet finalized. This is a bit of a hack that relies on |
129 | // the fact that we're lazily emitting object files: The only way you can |
130 | // get more than one set of objects loaded but not yet finalized is if |
131 | // they were loaded during relocation of another set. |
132 | if (M.UnfinalizedSections.size() == 1) |
133 | return ClientMM->finalizeMemory(ErrMsg); |
134 | return false; |
135 | } |
136 | |
137 | private: |
138 | OrcMCJITReplacement &M; |
139 | std::shared_ptr<MCJITMemoryManager> ClientMM; |
140 | }; |
141 | |
142 | class LinkingORCResolver : public orc::SymbolResolver { |
143 | public: |
144 | LinkingORCResolver(OrcMCJITReplacement &M) : M(M) {} |
145 | |
146 | SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) override { |
147 | SymbolNameSet Result; |
148 | |
149 | for (auto &S : Symbols) { |
150 | if (auto Sym = M.findMangledSymbol(*S)) { |
151 | if (!Sym.getFlags().isStrong()) |
152 | Result.insert(S); |
153 | } else if (auto Err = Sym.takeError()) { |
154 | M.reportError(std::move(Err)); |
155 | return SymbolNameSet(); |
156 | } else { |
157 | if (auto Sym2 = |
158 | M.ClientResolver->findSymbolInLogicalDylib(std::string(*S))) { |
159 | if (!Sym2.getFlags().isStrong()) |
160 | Result.insert(S); |
161 | } else if (auto Err = Sym2.takeError()) { |
162 | M.reportError(std::move(Err)); |
163 | return SymbolNameSet(); |
164 | } else |
165 | Result.insert(S); |
166 | } |
167 | } |
168 | |
169 | return Result; |
170 | } |
171 | |
172 | SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query, |
173 | SymbolNameSet Symbols) override { |
174 | SymbolNameSet UnresolvedSymbols; |
175 | bool NewSymbolsResolved = false; |
176 | |
177 | for (auto &S : Symbols) { |
178 | if (auto Sym = M.findMangledSymbol(*S)) { |
179 | if (auto Addr = Sym.getAddress()) { |
180 | Query->notifySymbolMetRequiredState( |
181 | S, JITEvaluatedSymbol(*Addr, Sym.getFlags())); |
182 | NewSymbolsResolved = true; |
183 | } else { |
184 | M.ES.legacyFailQuery(*Query, Addr.takeError()); |
185 | return SymbolNameSet(); |
186 | } |
187 | } else if (auto Err = Sym.takeError()) { |
188 | M.ES.legacyFailQuery(*Query, std::move(Err)); |
189 | return SymbolNameSet(); |
190 | } else { |
191 | if (auto Sym2 = M.ClientResolver->findSymbol(std::string(*S))) { |
192 | if (auto Addr = Sym2.getAddress()) { |
193 | Query->notifySymbolMetRequiredState( |
194 | S, JITEvaluatedSymbol(*Addr, Sym2.getFlags())); |
195 | NewSymbolsResolved = true; |
196 | } else { |
197 | M.ES.legacyFailQuery(*Query, Addr.takeError()); |
198 | return SymbolNameSet(); |
199 | } |
200 | } else if (auto Err = Sym2.takeError()) { |
201 | M.ES.legacyFailQuery(*Query, std::move(Err)); |
202 | return SymbolNameSet(); |
203 | } else |
204 | UnresolvedSymbols.insert(S); |
205 | } |
206 | } |
207 | |
208 | if (NewSymbolsResolved && Query->isComplete()) |
209 | Query->handleComplete(); |
210 | |
211 | return UnresolvedSymbols; |
212 | } |
213 | |
214 | private: |
215 | OrcMCJITReplacement &M; |
216 | }; |
217 | |
218 | private: |
219 | static ExecutionEngine * |
220 | createOrcMCJITReplacement(std::string *ErrorMsg, |
221 | std::shared_ptr<MCJITMemoryManager> MemMgr, |
222 | std::shared_ptr<LegacyJITSymbolResolver> Resolver, |
223 | std::unique_ptr<TargetMachine> TM) { |
224 | return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver), |
225 | std::move(TM)); |
226 | } |
227 | |
228 | void reportError(Error Err) { |
229 | logAllUnhandledErrors(std::move(Err), errs(), "MCJIT error: "); |
230 | } |
231 | |
232 | public: |
233 | OrcMCJITReplacement(std::shared_ptr<MCJITMemoryManager> MemMgr, |
234 | std::shared_ptr<LegacyJITSymbolResolver> ClientResolver, |
235 | std::unique_ptr<TargetMachine> TM) |
236 | : ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)), |
237 | MemMgr( |
238 | std::make_shared<MCJITReplacementMemMgr>(*this, std::move(MemMgr))), |
239 | Resolver(std::make_shared<LinkingORCResolver>(*this)), |
240 | ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this), |
241 | NotifyFinalized(*this), |
242 | ObjectLayer( |
243 | AcknowledgeORCv1Deprecation, ES, |
244 | [this](VModuleKey K) { |
245 | return ObjectLayerT::Resources{this->MemMgr, this->Resolver}; |
246 | }, |
247 | NotifyObjectLoaded, NotifyFinalized), |
248 | CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer, |
249 | SimpleCompiler(*this->TM), |
250 | [this](VModuleKey K, std::unique_ptr<Module> M) { |
251 | Modules.push_back(std::move(M)); |
252 | }), |
253 | LazyEmitLayer(AcknowledgeORCv1Deprecation, CompileLayer) {} |
254 | |
255 | static void Register() { |
256 | OrcMCJITReplacementCtor = createOrcMCJITReplacement; |
257 | } |
258 | |
259 | void addModule(std::unique_ptr<Module> M) override { |
260 | // If this module doesn't have a DataLayout attached then attach the |
261 | // default. |
262 | if (M->getDataLayout().isDefault()) { |
263 | M->setDataLayout(getDataLayout()); |
264 | } else { |
265 | assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch")((M->getDataLayout() == getDataLayout() && "DataLayout Mismatch" ) ? static_cast<void> (0) : __assert_fail ("M->getDataLayout() == getDataLayout() && \"DataLayout Mismatch\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h" , 265, __PRETTY_FUNCTION__)); |
266 | } |
267 | |
268 | // Rename, bump linkage and record static constructors and destructors. |
269 | // We have to do this before we hand over ownership of the module to the |
270 | // JIT. |
271 | std::vector<std::string> CtorNames, DtorNames; |
272 | { |
273 | unsigned CtorId = 0, DtorId = 0; |
274 | for (auto Ctor : orc::getConstructors(*M)) { |
275 | std::string NewCtorName = ("__ORCstatic_ctor." + Twine(CtorId++)).str(); |
276 | Ctor.Func->setName(NewCtorName); |
277 | Ctor.Func->setLinkage(GlobalValue::ExternalLinkage); |
278 | Ctor.Func->setVisibility(GlobalValue::HiddenVisibility); |
279 | CtorNames.push_back(mangle(NewCtorName)); |
280 | } |
281 | for (auto Dtor : orc::getDestructors(*M)) { |
282 | std::string NewDtorName = ("__ORCstatic_dtor." + Twine(DtorId++)).str(); |
283 | dbgs() << "Found dtor: " << NewDtorName << "\n"; |
284 | Dtor.Func->setName(NewDtorName); |
285 | Dtor.Func->setLinkage(GlobalValue::ExternalLinkage); |
286 | Dtor.Func->setVisibility(GlobalValue::HiddenVisibility); |
287 | DtorNames.push_back(mangle(NewDtorName)); |
288 | } |
289 | } |
290 | |
291 | auto K = ES.allocateVModule(); |
292 | |
293 | UnexecutedConstructors[K] = std::move(CtorNames); |
294 | UnexecutedDestructors[K] = std::move(DtorNames); |
295 | |
296 | cantFail(LazyEmitLayer.addModule(K, std::move(M))); |
297 | } |
298 | |
299 | void addObjectFile(std::unique_ptr<object::ObjectFile> O) override { |
300 | cantFail(ObjectLayer.addObject( |
301 | ES.allocateVModule(), MemoryBuffer::getMemBufferCopy(O->getData()))); |
302 | } |
303 | |
304 | void addObjectFile(object::OwningBinary<object::ObjectFile> O) override { |
305 | std::unique_ptr<object::ObjectFile> Obj; |
306 | std::unique_ptr<MemoryBuffer> ObjBuffer; |
307 | std::tie(Obj, ObjBuffer) = O.takeBinary(); |
308 | cantFail(ObjectLayer.addObject(ES.allocateVModule(), std::move(ObjBuffer))); |
309 | } |
310 | |
311 | void addArchive(object::OwningBinary<object::Archive> A) override { |
312 | Archives.push_back(std::move(A)); |
313 | } |
314 | |
315 | bool removeModule(Module *M) override { |
316 | auto I = Modules.begin(); |
317 | for (auto E = Modules.end(); I != E; ++I) |
318 | if (I->get() == M) |
319 | break; |
320 | if (I == Modules.end()) |
321 | return false; |
322 | Modules.erase(I); |
323 | return true; |
324 | } |
325 | |
326 | uint64_t getSymbolAddress(StringRef Name) { |
327 | return cantFail(findSymbol(Name).getAddress()); |
328 | } |
329 | |
330 | JITSymbol findSymbol(StringRef Name) { |
331 | return findMangledSymbol(mangle(Name)); |
332 | } |
333 | |
334 | void finalizeObject() override { |
335 | // This is deprecated - Aim to remove in ExecutionEngine. |
336 | // REMOVE IF POSSIBLE - Doesn't make sense for New JIT. |
337 | } |
338 | |
339 | void mapSectionAddress(const void *LocalAddress, |
340 | uint64_t TargetAddress) override { |
341 | for (auto &P : UnfinalizedSections) |
342 | if (P.second.count(LocalAddress)) |
343 | ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress); |
344 | } |
345 | |
346 | uint64_t getGlobalValueAddress(const std::string &Name) override { |
347 | return getSymbolAddress(Name); |
348 | } |
349 | |
350 | uint64_t getFunctionAddress(const std::string &Name) override { |
351 | return getSymbolAddress(Name); |
352 | } |
353 | |
354 | void *getPointerToFunction(Function *F) override { |
355 | uint64_t FAddr = getSymbolAddress(F->getName()); |
356 | return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr)); |
357 | } |
358 | |
359 | void *getPointerToNamedFunction(StringRef Name, |
360 | bool AbortOnFailure = true) override { |
361 | uint64_t Addr = getSymbolAddress(Name); |
362 | if (!Addr && AbortOnFailure) |
363 | llvm_unreachable("Missing symbol!")::llvm::llvm_unreachable_internal("Missing symbol!", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h" , 363); |
364 | return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr)); |
365 | } |
366 | |
367 | GenericValue runFunction(Function *F, |
368 | ArrayRef<GenericValue> ArgValues) override; |
369 | |
370 | void setObjectCache(ObjectCache *NewCache) override { |
371 | CompileLayer.getCompiler().setObjectCache(NewCache); |
372 | } |
373 | |
374 | void setProcessAllSections(bool ProcessAllSections) override { |
375 | ObjectLayer.setProcessAllSections(ProcessAllSections); |
376 | } |
377 | |
378 | void runStaticConstructorsDestructors(bool isDtors) override; |
379 | |
380 | private: |
381 | JITSymbol findMangledSymbol(StringRef Name) { |
382 | if (auto Sym = LazyEmitLayer.findSymbol(std::string(Name), false)) |
383 | return Sym; |
384 | if (auto Sym = ClientResolver->findSymbol(std::string(Name))) |
385 | return Sym; |
386 | if (auto Sym = scanArchives(Name)) |
387 | return Sym; |
388 | |
389 | return nullptr; |
390 | } |
391 | |
392 | JITSymbol scanArchives(StringRef Name) { |
393 | for (object::OwningBinary<object::Archive> &OB : Archives) { |
394 | object::Archive *A = OB.getBinary(); |
395 | // Look for our symbols in each Archive |
396 | auto OptionalChildOrErr = A->findSym(Name); |
397 | if (!OptionalChildOrErr) |
398 | report_fatal_error(OptionalChildOrErr.takeError()); |
399 | auto &OptionalChild = *OptionalChildOrErr; |
400 | if (OptionalChild) { |
401 | // FIXME: Support nested archives? |
402 | Expected<std::unique_ptr<object::Binary>> ChildBinOrErr = |
403 | OptionalChild->getAsBinary(); |
404 | if (!ChildBinOrErr) { |
405 | // TODO: Actually report errors helpfully. |
406 | consumeError(ChildBinOrErr.takeError()); |
407 | continue; |
408 | } |
409 | std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get(); |
410 | if (ChildBin->isObject()) { |
411 | cantFail(ObjectLayer.addObject( |
412 | ES.allocateVModule(), |
413 | MemoryBuffer::getMemBufferCopy(ChildBin->getData()))); |
414 | if (auto Sym = ObjectLayer.findSymbol(Name, true)) |
415 | return Sym; |
416 | } |
417 | } |
418 | } |
419 | return nullptr; |
420 | } |
421 | |
422 | class NotifyObjectLoadedT { |
423 | public: |
424 | using LoadedObjInfoListT = |
425 | std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>; |
426 | |
427 | NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {} |
428 | |
429 | void operator()(VModuleKey K, const object::ObjectFile &Obj, |
430 | const RuntimeDyld::LoadedObjectInfo &Info) const { |
431 | M.UnfinalizedSections[K] = std::move(M.SectionsAllocatedSinceLastLoad); |
432 | M.SectionsAllocatedSinceLastLoad = SectionAddrSet(); |
433 | M.MemMgr->notifyObjectLoaded(&M, Obj); |
434 | } |
435 | private: |
436 | OrcMCJITReplacement &M; |
437 | }; |
438 | |
439 | class NotifyFinalizedT { |
440 | public: |
441 | NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {} |
442 | |
443 | void operator()(VModuleKey K, const object::ObjectFile &Obj, |
444 | const RuntimeDyld::LoadedObjectInfo &Info) { |
445 | M.UnfinalizedSections.erase(K); |
446 | } |
447 | |
448 | private: |
449 | OrcMCJITReplacement &M; |
450 | }; |
451 | |
452 | std::string mangle(StringRef Name) { |
453 | std::string MangledName; |
454 | { |
455 | raw_string_ostream MangledNameStream(MangledName); |
456 | Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout()); |
457 | } |
458 | return MangledName; |
459 | } |
460 | |
461 | using ObjectLayerT = LegacyRTDyldObjectLinkingLayer; |
462 | using CompileLayerT = LegacyIRCompileLayer<ObjectLayerT, orc::SimpleCompiler>; |
463 | using LazyEmitLayerT = LazyEmittingLayer<CompileLayerT>; |
464 | |
465 | ExecutionSession ES; |
466 | |
467 | std::unique_ptr<TargetMachine> TM; |
468 | std::shared_ptr<MCJITReplacementMemMgr> MemMgr; |
469 | std::shared_ptr<LinkingORCResolver> Resolver; |
470 | std::shared_ptr<LegacyJITSymbolResolver> ClientResolver; |
471 | Mangler Mang; |
472 | |
473 | // IMPORTANT: ShouldDelete *must* come before LocalModules: The shared_ptr |
474 | // delete blocks in LocalModules refer to the ShouldDelete map, so |
475 | // LocalModules needs to be destructed before ShouldDelete. |
476 | std::map<Module*, bool> ShouldDelete; |
477 | |
478 | NotifyObjectLoadedT NotifyObjectLoaded; |
479 | NotifyFinalizedT NotifyFinalized; |
480 | |
481 | ObjectLayerT ObjectLayer; |
482 | CompileLayerT CompileLayer; |
483 | LazyEmitLayerT LazyEmitLayer; |
484 | |
485 | std::map<VModuleKey, std::vector<std::string>> UnexecutedConstructors; |
486 | std::map<VModuleKey, std::vector<std::string>> UnexecutedDestructors; |
487 | |
488 | // We need to store ObjLayerT::ObjSetHandles for each of the object sets |
489 | // that have been emitted but not yet finalized so that we can forward the |
490 | // mapSectionAddress calls appropriately. |
491 | using SectionAddrSet = std::set<const void *>; |
492 | SectionAddrSet SectionsAllocatedSinceLastLoad; |
493 | std::map<VModuleKey, SectionAddrSet> UnfinalizedSections; |
494 | |
495 | std::vector<object::OwningBinary<object::Archive>> Archives; |
496 | }; |
497 | |
498 | } // end namespace orc |
499 | |
500 | } // end namespace llvm |
501 | |
502 | #endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H |
1 | //===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- 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 | // Contains the definition for a lazy-emitting layer for the JIT. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H |
14 | #define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H |
15 | |
16 | #include "llvm/ADT/STLExtras.h" |
17 | #include "llvm/ADT/StringMap.h" |
18 | #include "llvm/ADT/StringRef.h" |
19 | #include "llvm/ExecutionEngine/JITSymbol.h" |
20 | #include "llvm/ExecutionEngine/Orc/Core.h" |
21 | #include "llvm/IR/GlobalValue.h" |
22 | #include "llvm/IR/Mangler.h" |
23 | #include "llvm/IR/Module.h" |
24 | #include "llvm/Support/ErrorHandling.h" |
25 | #include "llvm/Support/raw_ostream.h" |
26 | #include <algorithm> |
27 | #include <cassert> |
28 | #include <list> |
29 | #include <memory> |
30 | #include <string> |
31 | |
32 | namespace llvm { |
33 | namespace orc { |
34 | |
35 | /// Lazy-emitting IR layer. |
36 | /// |
37 | /// This layer accepts LLVM IR Modules (via addModule) but does not |
38 | /// immediately emit them the layer below. Instead, emission to the base layer |
39 | /// is deferred until the first time the client requests the address (via |
40 | /// JITSymbol::getAddress) for a symbol contained in this layer. |
41 | template <typename BaseLayerT> class LazyEmittingLayer { |
42 | private: |
43 | class EmissionDeferredModule { |
44 | public: |
45 | EmissionDeferredModule(VModuleKey K, std::unique_ptr<Module> M) |
46 | : K(std::move(K)), M(std::move(M)) {} |
47 | |
48 | JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) { |
49 | switch (EmitState) { |
50 | case NotEmitted: |
51 | if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) { |
52 | JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV); |
53 | auto GetAddress = [this, ExportedSymbolsOnly, Name = Name.str(), |
54 | &B]() -> Expected<JITTargetAddress> { |
55 | if (this->EmitState == Emitting) |
56 | return 0; |
57 | else if (this->EmitState == NotEmitted) { |
58 | this->EmitState = Emitting; |
59 | if (auto Err = this->emitToBaseLayer(B)) |
60 | return std::move(Err); |
61 | this->EmitState = Emitted; |
62 | } |
63 | if (auto Sym = B.findSymbolIn(K, Name, ExportedSymbolsOnly)) |
64 | return Sym.getAddress(); |
65 | else if (auto Err = Sym.takeError()) |
66 | return std::move(Err); |
67 | else |
68 | llvm_unreachable("Successful symbol lookup should return "::llvm::llvm_unreachable_internal("Successful symbol lookup should return " "definition address here", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" , 69) |
69 | "definition address here")::llvm::llvm_unreachable_internal("Successful symbol lookup should return " "definition address here", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" , 69); |
70 | }; |
71 | return JITSymbol(std::move(GetAddress), Flags); |
72 | } else |
73 | return nullptr; |
74 | case Emitting: |
75 | // Calling "emit" can trigger a recursive call to 'find' (e.g. to check |
76 | // for pre-existing definitions of common-symbol), but any symbol in |
77 | // this module would already have been found internally (in the |
78 | // RuntimeDyld that did the lookup), so just return a nullptr here. |
79 | return nullptr; |
80 | case Emitted: |
81 | return B.findSymbolIn(K, std::string(Name), ExportedSymbolsOnly); |
82 | } |
83 | llvm_unreachable("Invalid emit-state.")::llvm::llvm_unreachable_internal("Invalid emit-state.", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" , 83); |
84 | } |
85 | |
86 | Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) { |
87 | return EmitState != NotEmitted ? BaseLayer.removeModule(K) |
88 | : Error::success(); |
89 | } |
90 | |
91 | void emitAndFinalize(BaseLayerT &BaseLayer) { |
92 | assert(EmitState != Emitting &&((EmitState != Emitting && "Cannot emitAndFinalize while already emitting" ) ? static_cast<void> (0) : __assert_fail ("EmitState != Emitting && \"Cannot emitAndFinalize while already emitting\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" , 93, __PRETTY_FUNCTION__)) |
93 | "Cannot emitAndFinalize while already emitting")((EmitState != Emitting && "Cannot emitAndFinalize while already emitting" ) ? static_cast<void> (0) : __assert_fail ("EmitState != Emitting && \"Cannot emitAndFinalize while already emitting\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" , 93, __PRETTY_FUNCTION__)); |
94 | if (EmitState == NotEmitted) { |
95 | EmitState = Emitting; |
96 | emitToBaseLayer(BaseLayer); |
97 | EmitState = Emitted; |
98 | } |
99 | BaseLayer.emitAndFinalize(K); |
100 | } |
101 | |
102 | private: |
103 | |
104 | const GlobalValue* searchGVs(StringRef Name, |
105 | bool ExportedSymbolsOnly) const { |
106 | // FIXME: We could clean all this up if we had a way to reliably demangle |
107 | // names: We could just demangle name and search, rather than |
108 | // mangling everything else. |
109 | |
110 | // If we have already built the mangled name set then just search it. |
111 | if (MangledSymbols) { |
112 | auto VI = MangledSymbols->find(Name); |
113 | if (VI == MangledSymbols->end()) |
114 | return nullptr; |
115 | auto GV = VI->second; |
116 | if (!ExportedSymbolsOnly || GV->hasDefaultVisibility()) |
117 | return GV; |
118 | return nullptr; |
119 | } |
120 | |
121 | // If we haven't built the mangled name set yet, try to build it. As an |
122 | // optimization this will leave MangledNames set to nullptr if we find |
123 | // Name in the process of building the set. |
124 | return buildMangledSymbols(Name, ExportedSymbolsOnly); |
125 | } |
126 | |
127 | Error emitToBaseLayer(BaseLayerT &BaseLayer) { |
128 | // We don't need the mangled names set any more: Once we've emitted this |
129 | // to the base layer we'll just look for symbols there. |
130 | MangledSymbols.reset(); |
131 | return BaseLayer.addModule(std::move(K), std::move(M)); |
132 | } |
133 | |
134 | // If the mangled name of the given GlobalValue matches the given search |
135 | // name (and its visibility conforms to the ExportedSymbolsOnly flag) then |
136 | // return the symbol. Otherwise, add the mangled name to the Names map and |
137 | // return nullptr. |
138 | const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names, |
139 | const GlobalValue &GV, |
140 | const Mangler &Mang, StringRef SearchName, |
141 | bool ExportedSymbolsOnly) const { |
142 | // Modules don't "provide" decls or common symbols. |
143 | if (GV.isDeclaration() || GV.hasCommonLinkage()) |
144 | return nullptr; |
145 | |
146 | // Mangle the GV name. |
147 | std::string MangledName; |
148 | { |
149 | raw_string_ostream MangledNameStream(MangledName); |
150 | Mang.getNameWithPrefix(MangledNameStream, &GV, false); |
151 | } |
152 | |
153 | // Check whether this is the name we were searching for, and if it is then |
154 | // bail out early. |
155 | if (MangledName == SearchName) |
156 | if (!ExportedSymbolsOnly || GV.hasDefaultVisibility()) |
157 | return &GV; |
158 | |
159 | // Otherwise add this to the map for later. |
160 | Names[MangledName] = &GV; |
161 | return nullptr; |
162 | } |
163 | |
164 | // Build the MangledSymbols map. Bails out early (with MangledSymbols left set |
165 | // to nullptr) if the given SearchName is found while building the map. |
166 | const GlobalValue* buildMangledSymbols(StringRef SearchName, |
167 | bool ExportedSymbolsOnly) const { |
168 | assert(!MangledSymbols && "Mangled symbols map already exists?")((!MangledSymbols && "Mangled symbols map already exists?" ) ? static_cast<void> (0) : __assert_fail ("!MangledSymbols && \"Mangled symbols map already exists?\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" , 168, __PRETTY_FUNCTION__)); |
169 | |
170 | auto Symbols = std::make_unique<StringMap<const GlobalValue*>>(); |
171 | |
172 | Mangler Mang; |
173 | |
174 | for (const auto &GO : M->global_objects()) |
175 | if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName, |
176 | ExportedSymbolsOnly)) |
177 | return GV; |
178 | |
179 | MangledSymbols = std::move(Symbols); |
180 | return nullptr; |
181 | } |
182 | |
183 | enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted; |
184 | VModuleKey K; |
185 | std::unique_ptr<Module> M; |
186 | mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols; |
187 | }; |
188 | |
189 | BaseLayerT &BaseLayer; |
190 | std::map<VModuleKey, std::unique_ptr<EmissionDeferredModule>> ModuleMap; |
191 | |
192 | public: |
193 | |
194 | /// Construct a lazy emitting layer. |
195 | LLVM_ATTRIBUTE_DEPRECATED(LazyEmittingLayer(BaseLayerT &BaseLayer) __attribute__((deprecated ("ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use " "ORCv2, where lazy emission is the default"))) |
196 | LazyEmittingLayer(BaseLayerT &BaseLayer),LazyEmittingLayer(BaseLayerT &BaseLayer) __attribute__((deprecated ("ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use " "ORCv2, where lazy emission is the default"))) |
197 | "ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use "LazyEmittingLayer(BaseLayerT &BaseLayer) __attribute__((deprecated ("ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use " "ORCv2, where lazy emission is the default"))) |
198 | "ORCv2, where lazy emission is the default")LazyEmittingLayer(BaseLayerT &BaseLayer) __attribute__((deprecated ("ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use " "ORCv2, where lazy emission is the default"))); |
199 | |
200 | /// Construct a lazy emitting layer. |
201 | LazyEmittingLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer) |
202 | : BaseLayer(BaseLayer) {} |
203 | |
204 | /// Add the given module to the lazy emitting layer. |
205 | Error addModule(VModuleKey K, std::unique_ptr<Module> M) { |
206 | assert(!ModuleMap.count(K) && "VModuleKey K already in use")((!ModuleMap.count(K) && "VModuleKey K already in use" ) ? static_cast<void> (0) : __assert_fail ("!ModuleMap.count(K) && \"VModuleKey K already in use\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" , 206, __PRETTY_FUNCTION__)); |
207 | ModuleMap[K] = |
208 | std::make_unique<EmissionDeferredModule>(std::move(K), std::move(M)); |
209 | return Error::success(); |
210 | } |
211 | |
212 | /// Remove the module represented by the given handle. |
213 | /// |
214 | /// This method will free the memory associated with the given module, both |
215 | /// in this layer, and the base layer. |
216 | Error removeModule(VModuleKey K) { |
217 | auto I = ModuleMap.find(K); |
218 | assert(I != ModuleMap.end() && "VModuleKey K not valid here")((I != ModuleMap.end() && "VModuleKey K not valid here" ) ? static_cast<void> (0) : __assert_fail ("I != ModuleMap.end() && \"VModuleKey K not valid here\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" , 218, __PRETTY_FUNCTION__)); |
219 | auto EDM = std::move(I.second); |
220 | ModuleMap.erase(I); |
221 | return EDM->removeModuleFromBaseLayer(BaseLayer); |
222 | } |
223 | |
224 | /// Search for the given named symbol. |
225 | /// @param Name The name of the symbol to search for. |
226 | /// @param ExportedSymbolsOnly If true, search only for exported symbols. |
227 | /// @return A handle for the given named symbol, if it exists. |
228 | JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { |
229 | // Look for the symbol among existing definitions. |
230 | if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly)) |
231 | return Symbol; |
232 | |
233 | // If not found then search the deferred modules. If any of these contain a |
234 | // definition of 'Name' then they will return a JITSymbol that will emit |
235 | // the corresponding module when the symbol address is requested. |
236 | for (auto &KV : ModuleMap) |
237 | if (auto Symbol = KV.second->find(Name, ExportedSymbolsOnly, BaseLayer)) |
238 | return Symbol; |
239 | |
240 | // If no definition found anywhere return a null symbol. |
241 | return nullptr; |
242 | } |
243 | |
244 | /// Get the address of the given symbol in the context of the of |
245 | /// compiled modules represented by the key K. |
246 | JITSymbol findSymbolIn(VModuleKey K, const std::string &Name, |
247 | bool ExportedSymbolsOnly) { |
248 | assert(ModuleMap.count(K) && "VModuleKey K not valid here")((ModuleMap.count(K) && "VModuleKey K not valid here" ) ? static_cast<void> (0) : __assert_fail ("ModuleMap.count(K) && \"VModuleKey K not valid here\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" , 248, __PRETTY_FUNCTION__)); |
249 | return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer); |
250 | } |
251 | |
252 | /// Immediately emit and finalize the module represented by the given |
253 | /// key. |
254 | Error emitAndFinalize(VModuleKey K) { |
255 | assert(ModuleMap.count(K) && "VModuleKey K not valid here")((ModuleMap.count(K) && "VModuleKey K not valid here" ) ? static_cast<void> (0) : __assert_fail ("ModuleMap.count(K) && \"VModuleKey K not valid here\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" , 255, __PRETTY_FUNCTION__)); |
256 | return ModuleMap[K]->emitAndFinalize(BaseLayer); |
257 | } |
258 | }; |
259 | |
260 | template <typename BaseLayerT> |
261 | LazyEmittingLayer<BaseLayerT>::LazyEmittingLayer(BaseLayerT &BaseLayer) |
262 | : BaseLayer(BaseLayer) {} |
263 | |
264 | } // end namespace orc |
265 | } // end namespace llvm |
266 | |
267 | #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H |
1 | //===- FunctionExtras.h - Function type erasure utilities -------*- 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 | /// \file | ||||||||||
9 | /// This file provides a collection of function (or more generally, callable) | ||||||||||
10 | /// type erasure utilities supplementing those provided by the standard library | ||||||||||
11 | /// in `<function>`. | ||||||||||
12 | /// | ||||||||||
13 | /// It provides `unique_function`, which works like `std::function` but supports | ||||||||||
14 | /// move-only callable objects. | ||||||||||
15 | /// | ||||||||||
16 | /// Future plans: | ||||||||||
17 | /// - Add a `function` that provides const, volatile, and ref-qualified support, | ||||||||||
18 | /// which doesn't work with `std::function`. | ||||||||||
19 | /// - Provide support for specifying multiple signatures to type erase callable | ||||||||||
20 | /// objects with an overload set, such as those produced by generic lambdas. | ||||||||||
21 | /// - Expand to include a copyable utility that directly replaces std::function | ||||||||||
22 | /// but brings the above improvements. | ||||||||||
23 | /// | ||||||||||
24 | /// Note that LLVM's utilities are greatly simplified by not supporting | ||||||||||
25 | /// allocators. | ||||||||||
26 | /// | ||||||||||
27 | /// If the standard library ever begins to provide comparable facilities we can | ||||||||||
28 | /// consider switching to those. | ||||||||||
29 | /// | ||||||||||
30 | //===----------------------------------------------------------------------===// | ||||||||||
31 | |||||||||||
32 | #ifndef LLVM_ADT_FUNCTION_EXTRAS_H | ||||||||||
33 | #define LLVM_ADT_FUNCTION_EXTRAS_H | ||||||||||
34 | |||||||||||
35 | #include "llvm/ADT/PointerIntPair.h" | ||||||||||
36 | #include "llvm/ADT/PointerUnion.h" | ||||||||||
37 | #include "llvm/Support/type_traits.h" | ||||||||||
38 | #include <memory> | ||||||||||
39 | |||||||||||
40 | namespace llvm { | ||||||||||
41 | |||||||||||
42 | template <typename FunctionT> class unique_function; | ||||||||||
43 | |||||||||||
44 | template <typename ReturnT, typename... ParamTs> | ||||||||||
45 | class unique_function<ReturnT(ParamTs...)> { | ||||||||||
46 | static constexpr size_t InlineStorageSize = sizeof(void *) * 3; | ||||||||||
47 | |||||||||||
48 | // MSVC has a bug and ICEs if we give it a particular dependent value | ||||||||||
49 | // expression as part of the `std::conditional` below. To work around this, | ||||||||||
50 | // we build that into a template struct's constexpr bool. | ||||||||||
51 | template <typename T> struct IsSizeLessThanThresholdT { | ||||||||||
52 | static constexpr bool value = sizeof(T) <= (2 * sizeof(void *)); | ||||||||||
53 | }; | ||||||||||
54 | |||||||||||
55 | // Provide a type function to map parameters that won't observe extra copies | ||||||||||
56 | // or moves and which are small enough to likely pass in register to values | ||||||||||
57 | // and all other types to l-value reference types. We use this to compute the | ||||||||||
58 | // types used in our erased call utility to minimize copies and moves unless | ||||||||||
59 | // doing so would force things unnecessarily into memory. | ||||||||||
60 | // | ||||||||||
61 | // The heuristic used is related to common ABI register passing conventions. | ||||||||||
62 | // It doesn't have to be exact though, and in one way it is more strict | ||||||||||
63 | // because we want to still be able to observe either moves *or* copies. | ||||||||||
64 | template <typename T> | ||||||||||
65 | using AdjustedParamT = typename std::conditional< | ||||||||||
66 | !std::is_reference<T>::value && | ||||||||||
67 | llvm::is_trivially_copy_constructible<T>::value && | ||||||||||
68 | llvm::is_trivially_move_constructible<T>::value && | ||||||||||
69 | IsSizeLessThanThresholdT<T>::value, | ||||||||||
70 | T, T &>::type; | ||||||||||
71 | |||||||||||
72 | // The type of the erased function pointer we use as a callback to dispatch to | ||||||||||
73 | // the stored callable when it is trivial to move and destroy. | ||||||||||
74 | using CallPtrT = ReturnT (*)(void *CallableAddr, | ||||||||||
75 | AdjustedParamT<ParamTs>... Params); | ||||||||||
76 | using MovePtrT = void (*)(void *LHSCallableAddr, void *RHSCallableAddr); | ||||||||||
77 | using DestroyPtrT = void (*)(void *CallableAddr); | ||||||||||
78 | |||||||||||
79 | /// A struct to hold a single trivial callback with sufficient alignment for | ||||||||||
80 | /// our bitpacking. | ||||||||||
81 | struct alignas(8) TrivialCallback { | ||||||||||
82 | CallPtrT CallPtr; | ||||||||||
83 | }; | ||||||||||
84 | |||||||||||
85 | /// A struct we use to aggregate three callbacks when we need full set of | ||||||||||
86 | /// operations. | ||||||||||
87 | struct alignas(8) NonTrivialCallbacks { | ||||||||||
88 | CallPtrT CallPtr; | ||||||||||
89 | MovePtrT MovePtr; | ||||||||||
90 | DestroyPtrT DestroyPtr; | ||||||||||
91 | }; | ||||||||||
92 | |||||||||||
93 | // Create a pointer union between either a pointer to a static trivial call | ||||||||||
94 | // pointer in a struct or a pointer to a static struct of the call, move, and | ||||||||||
95 | // destroy pointers. | ||||||||||
96 | using CallbackPointerUnionT = | ||||||||||
97 | PointerUnion<TrivialCallback *, NonTrivialCallbacks *>; | ||||||||||
98 | |||||||||||
99 | // The main storage buffer. This will either have a pointer to out-of-line | ||||||||||
100 | // storage or an inline buffer storing the callable. | ||||||||||
101 | union StorageUnionT { | ||||||||||
102 | // For out-of-line storage we keep a pointer to the underlying storage and | ||||||||||
103 | // the size. This is enough to deallocate the memory. | ||||||||||
104 | struct OutOfLineStorageT { | ||||||||||
105 | void *StoragePtr; | ||||||||||
106 | size_t Size; | ||||||||||
107 | size_t Alignment; | ||||||||||
108 | } OutOfLineStorage; | ||||||||||
109 | static_assert( | ||||||||||
110 | sizeof(OutOfLineStorageT) <= InlineStorageSize, | ||||||||||
111 | "Should always use all of the out-of-line storage for inline storage!"); | ||||||||||
112 | |||||||||||
113 | // For in-line storage, we just provide an aligned character buffer. We | ||||||||||
114 | // provide three pointers worth of storage here. | ||||||||||
115 | typename std::aligned_storage<InlineStorageSize, alignof(void *)>::type | ||||||||||
116 | InlineStorage; | ||||||||||
117 | } StorageUnion; | ||||||||||
118 | |||||||||||
119 | // A compressed pointer to either our dispatching callback or our table of | ||||||||||
120 | // dispatching callbacks and the flag for whether the callable itself is | ||||||||||
121 | // stored inline or not. | ||||||||||
122 | PointerIntPair<CallbackPointerUnionT, 1, bool> CallbackAndInlineFlag; | ||||||||||
123 | |||||||||||
124 | bool isInlineStorage() const { return CallbackAndInlineFlag.getInt(); } | ||||||||||
125 | |||||||||||
126 | bool isTrivialCallback() const { | ||||||||||
127 | return CallbackAndInlineFlag.getPointer().template is<TrivialCallback *>(); | ||||||||||
128 | } | ||||||||||
129 | |||||||||||
130 | CallPtrT getTrivialCallback() const { | ||||||||||
131 | return CallbackAndInlineFlag.getPointer().template get<TrivialCallback *>()->CallPtr; | ||||||||||
132 | } | ||||||||||
133 | |||||||||||
134 | NonTrivialCallbacks *getNonTrivialCallbacks() const { | ||||||||||
135 | return CallbackAndInlineFlag.getPointer() | ||||||||||
136 | .template get<NonTrivialCallbacks *>(); | ||||||||||
137 | } | ||||||||||
138 | |||||||||||
139 | void *getInlineStorage() { return &StorageUnion.InlineStorage; } | ||||||||||
140 | |||||||||||
141 | void *getOutOfLineStorage() { | ||||||||||
142 | return StorageUnion.OutOfLineStorage.StoragePtr; | ||||||||||
143 | } | ||||||||||
144 | size_t getOutOfLineStorageSize() const { | ||||||||||
145 | return StorageUnion.OutOfLineStorage.Size; | ||||||||||
146 | } | ||||||||||
147 | size_t getOutOfLineStorageAlignment() const { | ||||||||||
148 | return StorageUnion.OutOfLineStorage.Alignment; | ||||||||||
149 | } | ||||||||||
150 | |||||||||||
151 | void setOutOfLineStorage(void *Ptr, size_t Size, size_t Alignment) { | ||||||||||
152 | StorageUnion.OutOfLineStorage = {Ptr, Size, Alignment}; | ||||||||||
153 | } | ||||||||||
154 | |||||||||||
155 | template <typename CallableT> | ||||||||||
156 | static ReturnT CallImpl(void *CallableAddr, AdjustedParamT<ParamTs>... Params) { | ||||||||||
157 | return (*reinterpret_cast<CallableT *>(CallableAddr))( | ||||||||||
158 | std::forward<ParamTs>(Params)...); | ||||||||||
159 | } | ||||||||||
160 | |||||||||||
161 | template <typename CallableT> | ||||||||||
162 | static void MoveImpl(void *LHSCallableAddr, void *RHSCallableAddr) noexcept { | ||||||||||
163 | new (LHSCallableAddr) | ||||||||||
164 | CallableT(std::move(*reinterpret_cast<CallableT *>(RHSCallableAddr))); | ||||||||||
165 | } | ||||||||||
166 | |||||||||||
167 | template <typename CallableT> | ||||||||||
168 | static void DestroyImpl(void *CallableAddr) noexcept { | ||||||||||
169 | reinterpret_cast<CallableT *>(CallableAddr)->~CallableT(); | ||||||||||
170 | } | ||||||||||
171 | |||||||||||
172 | public: | ||||||||||
173 | unique_function() = default; | ||||||||||
174 | unique_function(std::nullptr_t /*null_callable*/) {} | ||||||||||
175 | |||||||||||
176 | ~unique_function() { | ||||||||||
177 | if (!CallbackAndInlineFlag.getPointer()) | ||||||||||
178 | return; | ||||||||||
179 | |||||||||||
180 | // Cache this value so we don't re-check it after type-erased operations. | ||||||||||
181 | bool IsInlineStorage = isInlineStorage(); | ||||||||||
182 | |||||||||||
183 | if (!isTrivialCallback()) | ||||||||||
184 | getNonTrivialCallbacks()->DestroyPtr( | ||||||||||
185 | IsInlineStorage ? getInlineStorage() : getOutOfLineStorage()); | ||||||||||
186 | |||||||||||
187 | if (!IsInlineStorage) | ||||||||||
188 | deallocate_buffer(getOutOfLineStorage(), getOutOfLineStorageSize(), | ||||||||||
189 | getOutOfLineStorageAlignment()); | ||||||||||
190 | } | ||||||||||
| |||||||||||
191 | |||||||||||
192 | unique_function(unique_function &&RHS) noexcept { | ||||||||||
193 | // Copy the callback and inline flag. | ||||||||||
194 | CallbackAndInlineFlag = RHS.CallbackAndInlineFlag; | ||||||||||
195 | |||||||||||
196 | // If the RHS is empty, just copying the above is sufficient. | ||||||||||
197 | if (!RHS) | ||||||||||
198 | return; | ||||||||||
199 | |||||||||||
200 | if (!isInlineStorage()) { | ||||||||||
201 | // The out-of-line case is easiest to move. | ||||||||||
202 | StorageUnion.OutOfLineStorage = RHS.StorageUnion.OutOfLineStorage; | ||||||||||
203 | } else if (isTrivialCallback()) { | ||||||||||
204 | // Move is trivial, just memcpy the bytes across. | ||||||||||
205 | memcpy(getInlineStorage(), RHS.getInlineStorage(), InlineStorageSize); | ||||||||||
206 | } else { | ||||||||||
207 | // Non-trivial move, so dispatch to a type-erased implementation. | ||||||||||
208 | getNonTrivialCallbacks()->MovePtr(getInlineStorage(), | ||||||||||
209 | RHS.getInlineStorage()); | ||||||||||
210 | } | ||||||||||
211 | |||||||||||
212 | // Clear the old callback and inline flag to get back to as-if-null. | ||||||||||
213 | RHS.CallbackAndInlineFlag = {}; | ||||||||||
214 | |||||||||||
215 | #ifndef NDEBUG | ||||||||||
216 | // In debug builds, we also scribble across the rest of the storage. | ||||||||||
217 | memset(RHS.getInlineStorage(), 0xAD, InlineStorageSize); | ||||||||||
218 | #endif | ||||||||||
219 | } | ||||||||||
220 | |||||||||||
221 | unique_function &operator=(unique_function &&RHS) noexcept { | ||||||||||
222 | if (this == &RHS) | ||||||||||
223 | return *this; | ||||||||||
224 | |||||||||||
225 | // Because we don't try to provide any exception safety guarantees we can | ||||||||||
226 | // implement move assignment very simply by first destroying the current | ||||||||||
227 | // object and then move-constructing over top of it. | ||||||||||
228 | this->~unique_function(); | ||||||||||
229 | new (this) unique_function(std::move(RHS)); | ||||||||||
230 | return *this; | ||||||||||
231 | } | ||||||||||
232 | |||||||||||
233 | template <typename CallableT> unique_function(CallableT Callable) { | ||||||||||
234 | bool IsInlineStorage = true; | ||||||||||
235 | void *CallableAddr = getInlineStorage(); | ||||||||||
236 | if (sizeof(CallableT) > InlineStorageSize || | ||||||||||
237 | alignof(CallableT) > alignof(decltype(StorageUnion.InlineStorage))) { | ||||||||||
238 | IsInlineStorage = false; | ||||||||||
239 | // Allocate out-of-line storage. FIXME: Use an explicit alignment | ||||||||||
240 | // parameter in C++17 mode. | ||||||||||
241 | auto Size = sizeof(CallableT); | ||||||||||
242 | auto Alignment = alignof(CallableT); | ||||||||||
243 | CallableAddr = allocate_buffer(Size, Alignment); | ||||||||||
244 | setOutOfLineStorage(CallableAddr, Size, Alignment); | ||||||||||
245 | } | ||||||||||
246 | |||||||||||
247 | // Now move into the storage. | ||||||||||
248 | new (CallableAddr) CallableT(std::move(Callable)); | ||||||||||
249 | |||||||||||
250 | // See if we can create a trivial callback. We need the callable to be | ||||||||||
251 | // trivially moved and trivially destroyed so that we don't have to store | ||||||||||
252 | // type erased callbacks for those operations. | ||||||||||
253 | // | ||||||||||
254 | // FIXME: We should use constexpr if here and below to avoid instantiating | ||||||||||
255 | // the non-trivial static objects when unnecessary. While the linker should | ||||||||||
256 | // remove them, it is still wasteful. | ||||||||||
257 | if (llvm::is_trivially_move_constructible<CallableT>::value
| ||||||||||
258 | std::is_trivially_destructible<CallableT>::value) { | ||||||||||
259 | // We need to create a nicely aligned object. We use a static variable | ||||||||||
260 | // for this because it is a trivial struct. | ||||||||||
261 | static TrivialCallback Callback = { &CallImpl<CallableT> }; | ||||||||||
262 | |||||||||||
263 | CallbackAndInlineFlag = {&Callback, IsInlineStorage}; | ||||||||||
264 | return; | ||||||||||
265 | } | ||||||||||
266 | |||||||||||
267 | // Otherwise, we need to point at an object that contains all the different | ||||||||||
268 | // type erased behaviors needed. Create a static instance of the struct type | ||||||||||
269 | // here and then use a pointer to that. | ||||||||||
270 | static NonTrivialCallbacks Callbacks = { | ||||||||||
271 | &CallImpl<CallableT>, &MoveImpl<CallableT>, &DestroyImpl<CallableT>}; | ||||||||||
272 | |||||||||||
273 | CallbackAndInlineFlag = {&Callbacks, IsInlineStorage}; | ||||||||||
274 | } | ||||||||||
275 | |||||||||||
276 | ReturnT operator()(ParamTs... Params) { | ||||||||||
277 | void *CallableAddr = | ||||||||||
278 | isInlineStorage() ? getInlineStorage() : getOutOfLineStorage(); | ||||||||||
279 | |||||||||||
280 | return (isTrivialCallback() | ||||||||||
281 | ? getTrivialCallback() | ||||||||||
282 | : getNonTrivialCallbacks()->CallPtr)(CallableAddr, Params...); | ||||||||||
283 | } | ||||||||||
284 | |||||||||||
285 | explicit operator bool() const { | ||||||||||
286 | return (bool)CallbackAndInlineFlag.getPointer(); | ||||||||||
287 | } | ||||||||||
288 | }; | ||||||||||
289 | |||||||||||
290 | } // end namespace llvm | ||||||||||
291 | |||||||||||
292 | #endif // LLVM_ADT_FUNCTION_H |
1 | //===-- llvm/Support/Compiler.h - Compiler abstraction support --*- 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 defines several macros, based on the current compiler. This allows |
10 | // use of compiler-specific features in a way that remains portable. This header |
11 | // can be included from either C or C++. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_SUPPORT_COMPILER_H |
16 | #define LLVM_SUPPORT_COMPILER_H |
17 | |
18 | #include "llvm/Config/llvm-config.h" |
19 | |
20 | #ifdef __cplusplus201402L |
21 | #include <new> |
22 | #endif |
23 | #include <stddef.h> |
24 | |
25 | #if defined(_MSC_VER) |
26 | #include <sal.h> |
27 | #endif |
28 | |
29 | #ifndef __has_feature |
30 | # define0 __has_feature(x)0 0 |
31 | #endif |
32 | |
33 | #ifndef __has_extension |
34 | # define0 __has_extension(x)0 0 |
35 | #endif |
36 | |
37 | #ifndef __has_attribute |
38 | # define0 __has_attribute(x)0 0 |
39 | #endif |
40 | |
41 | #ifndef __has_builtin |
42 | # define0 __has_builtin(x)0 0 |
43 | #endif |
44 | |
45 | // Only use __has_cpp_attribute in C++ mode. GCC defines __has_cpp_attribute in |
46 | // C mode, but the :: in __has_cpp_attribute(scoped::attribute) is invalid. |
47 | #ifndef LLVM_HAS_CPP_ATTRIBUTE |
48 | #if defined(__cplusplus201402L) && defined(__has_cpp_attribute)0 |
49 | # define LLVM_HAS_CPP_ATTRIBUTE(x)0 __has_cpp_attribute(x)0 |
50 | #else |
51 | # define LLVM_HAS_CPP_ATTRIBUTE(x)0 0 |
52 | #endif |
53 | #endif |
54 | |
55 | /// \macro LLVM_GNUC_PREREQ |
56 | /// Extend the default __GNUC_PREREQ even if glibc's features.h isn't |
57 | /// available. |
58 | #ifndef LLVM_GNUC_PREREQ |
59 | # if defined(__GNUC__4) && defined(__GNUC_MINOR__2) && defined(__GNUC_PATCHLEVEL__1) |
60 | # define LLVM_GNUC_PREREQ(maj, min, patch)((4 << 20) + (2 << 10) + 1 >= ((maj) << 20 ) + ((min) << 10) + (patch)) \ |
61 | ((__GNUC__4 << 20) + (__GNUC_MINOR__2 << 10) + __GNUC_PATCHLEVEL__1 >= \ |
62 | ((maj) << 20) + ((min) << 10) + (patch)) |
63 | # elif defined(__GNUC__4) && defined(__GNUC_MINOR__2) |
64 | # define LLVM_GNUC_PREREQ(maj, min, patch)((4 << 20) + (2 << 10) + 1 >= ((maj) << 20 ) + ((min) << 10) + (patch)) \ |
65 | ((__GNUC__4 << 20) + (__GNUC_MINOR__2 << 10) >= ((maj) << 20) + ((min) << 10)) |
66 | # else |
67 | # define LLVM_GNUC_PREREQ(maj, min, patch)((4 << 20) + (2 << 10) + 1 >= ((maj) << 20 ) + ((min) << 10) + (patch)) 0 |
68 | # endif |
69 | #endif |
70 | |
71 | /// \macro LLVM_MSC_PREREQ |
72 | /// Is the compiler MSVC of at least the specified version? |
73 | /// The common \param version values to check for are: |
74 | /// * 1910: VS2017, version 15.1 & 15.2 |
75 | /// * 1911: VS2017, version 15.3 & 15.4 |
76 | /// * 1912: VS2017, version 15.5 |
77 | /// * 1913: VS2017, version 15.6 |
78 | /// * 1914: VS2017, version 15.7 |
79 | /// * 1915: VS2017, version 15.8 |
80 | /// * 1916: VS2017, version 15.9 |
81 | /// * 1920: VS2019, version 16.0 |
82 | /// * 1921: VS2019, version 16.1 |
83 | #ifdef _MSC_VER |
84 | #define LLVM_MSC_PREREQ(version)0 (_MSC_VER >= (version)) |
85 | |
86 | // We require at least MSVC 2017. |
87 | #if !LLVM_MSC_PREREQ(1910)0 |
88 | #error LLVM requires at least MSVC 2017. |
89 | #endif |
90 | |
91 | #else |
92 | #define LLVM_MSC_PREREQ(version)0 0 |
93 | #endif |
94 | |
95 | /// Does the compiler support ref-qualifiers for *this? |
96 | /// |
97 | /// Sadly, this is separate from just rvalue reference support because GCC |
98 | /// and MSVC implemented this later than everything else. This appears to be |
99 | /// corrected in MSVC 2019 but not MSVC 2017. |
100 | #if __has_feature(cxx_rvalue_references)1 || LLVM_GNUC_PREREQ(4, 8, 1)((4 << 20) + (2 << 10) + 1 >= ((4) << 20 ) + ((8) << 10) + (1)) |
101 | #define LLVM_HAS_RVALUE_REFERENCE_THIS1 1 |
102 | #else |
103 | #define LLVM_HAS_RVALUE_REFERENCE_THIS1 0 |
104 | #endif |
105 | |
106 | /// Expands to '&' if ref-qualifiers for *this are supported. |
107 | /// |
108 | /// This can be used to provide lvalue/rvalue overrides of member functions. |
109 | /// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS |
110 | #if LLVM_HAS_RVALUE_REFERENCE_THIS1 |
111 | #define LLVM_LVALUE_FUNCTION& & |
112 | #else |
113 | #define LLVM_LVALUE_FUNCTION& |
114 | #endif |
115 | |
116 | /// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked |
117 | /// into a shared library, then the class should be private to the library and |
118 | /// not accessible from outside it. Can also be used to mark variables and |
119 | /// functions, making them private to any shared library they are linked into. |
120 | /// On PE/COFF targets, library visibility is the default, so this isn't needed. |
121 | /// |
122 | /// LLVM_EXTERNAL_VISIBILITY - classes, functions, and variables marked with |
123 | /// this attribute will be made public and visible outside of any shared library |
124 | /// they are linked in to. |
125 | #if (__has_attribute(visibility)1 || LLVM_GNUC_PREREQ(4, 0, 0)((4 << 20) + (2 << 10) + 1 >= ((4) << 20 ) + ((0) << 10) + (0))) && \ |
126 | !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32) |
127 | #define LLVM_LIBRARY_VISIBILITY__attribute__ ((visibility("hidden"))) __attribute__ ((visibility("hidden"))) |
128 | #define LLVM_EXTERNAL_VISIBILITY__attribute__ ((visibility("default"))) __attribute__ ((visibility("default"))) |
129 | #else |
130 | #define LLVM_LIBRARY_VISIBILITY__attribute__ ((visibility("hidden"))) |
131 | #define LLVM_EXTERNAL_VISIBILITY__attribute__ ((visibility("default"))) |
132 | #endif |
133 | |
134 | #if defined(__GNUC__4) |
135 | #define LLVM_PREFETCH(addr, rw, locality)__builtin_prefetch(addr, rw, locality) __builtin_prefetch(addr, rw, locality) |
136 | #else |
137 | #define LLVM_PREFETCH(addr, rw, locality)__builtin_prefetch(addr, rw, locality) |
138 | #endif |
139 | |
140 | #if __has_attribute(used)1 || LLVM_GNUC_PREREQ(3, 1, 0)((4 << 20) + (2 << 10) + 1 >= ((3) << 20 ) + ((1) << 10) + (0)) |
141 | #define LLVM_ATTRIBUTE_USED__attribute__((__used__)) __attribute__((__used__)) |
142 | #else |
143 | #define LLVM_ATTRIBUTE_USED__attribute__((__used__)) |
144 | #endif |
145 | |
146 | /// LLVM_NODISCARD - Warn if a type or return value is discarded. |
147 | |
148 | // Use the 'nodiscard' attribute in C++17 or newer mode. |
149 | #if __cplusplus201402L > 201402L && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)201907L |
150 | #define LLVM_NODISCARD[[clang::warn_unused_result]] [[nodiscard]] |
151 | #elif LLVM_HAS_CPP_ATTRIBUTE(clang::warn_unused_result)201907L |
152 | #define LLVM_NODISCARD[[clang::warn_unused_result]] [[clang::warn_unused_result]] |
153 | // Clang in C++14 mode claims that it has the 'nodiscard' attribute, but also |
154 | // warns in the pedantic mode that 'nodiscard' is a C++17 extension (PR33518). |
155 | // Use the 'nodiscard' attribute in C++14 mode only with GCC. |
156 | // TODO: remove this workaround when PR33518 is resolved. |
157 | #elif defined(__GNUC__4) && LLVM_HAS_CPP_ATTRIBUTE(nodiscard)201907L |
158 | #define LLVM_NODISCARD[[clang::warn_unused_result]] [[nodiscard]] |
159 | #else |
160 | #define LLVM_NODISCARD[[clang::warn_unused_result]] |
161 | #endif |
162 | |
163 | // Indicate that a non-static, non-const C++ member function reinitializes |
164 | // the entire object to a known state, independent of the previous state of |
165 | // the object. |
166 | // |
167 | // The clang-tidy check bugprone-use-after-move recognizes this attribute as a |
168 | // marker that a moved-from object has left the indeterminate state and can be |
169 | // reused. |
170 | #if LLVM_HAS_CPP_ATTRIBUTE(clang::reinitializes)1 |
171 | #define LLVM_ATTRIBUTE_REINITIALIZES[[clang::reinitializes]] [[clang::reinitializes]] |
172 | #else |
173 | #define LLVM_ATTRIBUTE_REINITIALIZES[[clang::reinitializes]] |
174 | #endif |
175 | |
176 | // Some compilers warn about unused functions. When a function is sometimes |
177 | // used or not depending on build settings (e.g. a function only called from |
178 | // within "assert"), this attribute can be used to suppress such warnings. |
179 | // |
180 | // However, it shouldn't be used for unused *variables*, as those have a much |
181 | // more portable solution: |
182 | // (void)unused_var_name; |
183 | // Prefer cast-to-void wherever it is sufficient. |
184 | #if __has_attribute(unused)1 || LLVM_GNUC_PREREQ(3, 1, 0)((4 << 20) + (2 << 10) + 1 >= ((3) << 20 ) + ((1) << 10) + (0)) |
185 | #define LLVM_ATTRIBUTE_UNUSED__attribute__((__unused__)) __attribute__((__unused__)) |
186 | #else |
187 | #define LLVM_ATTRIBUTE_UNUSED__attribute__((__unused__)) |
188 | #endif |
189 | |
190 | // FIXME: Provide this for PE/COFF targets. |
191 | #if (__has_attribute(weak)1 || LLVM_GNUC_PREREQ(4, 0, 0)((4 << 20) + (2 << 10) + 1 >= ((4) << 20 ) + ((0) << 10) + (0))) && \ |
192 | (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(_WIN32)) |
193 | #define LLVM_ATTRIBUTE_WEAK__attribute__((__weak__)) __attribute__((__weak__)) |
194 | #else |
195 | #define LLVM_ATTRIBUTE_WEAK__attribute__((__weak__)) |
196 | #endif |
197 | |
198 | // Prior to clang 3.2, clang did not accept any spelling of |
199 | // __has_attribute(const), so assume it is supported. |
200 | #if defined(__clang__1) || defined(__GNUC__4) |
201 | // aka 'CONST' but following LLVM Conventions. |
202 | #define LLVM_READNONE__attribute__((__const__)) __attribute__((__const__)) |
203 | #else |
204 | #define LLVM_READNONE__attribute__((__const__)) |
205 | #endif |
206 | |
207 | #if __has_attribute(pure)1 || defined(__GNUC__4) |
208 | // aka 'PURE' but following LLVM Conventions. |
209 | #define LLVM_READONLY__attribute__((__pure__)) __attribute__((__pure__)) |
210 | #else |
211 | #define LLVM_READONLY__attribute__((__pure__)) |
212 | #endif |
213 | |
214 | #if __has_builtin(__builtin_expect)1 || LLVM_GNUC_PREREQ(4, 0, 0)((4 << 20) + (2 << 10) + 1 >= ((4) << 20 ) + ((0) << 10) + (0)) |
215 | #define LLVM_LIKELY(EXPR)__builtin_expect((bool)(EXPR), true) __builtin_expect((bool)(EXPR), true) |
216 | #define LLVM_UNLIKELY(EXPR)__builtin_expect((bool)(EXPR), false) __builtin_expect((bool)(EXPR), false) |
217 | #else |
218 | #define LLVM_LIKELY(EXPR)__builtin_expect((bool)(EXPR), true) (EXPR) |
219 | #define LLVM_UNLIKELY(EXPR)__builtin_expect((bool)(EXPR), false) (EXPR) |
220 | #endif |
221 | |
222 | /// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, |
223 | /// mark a method "not for inlining". |
224 | #if __has_attribute(noinline)1 || LLVM_GNUC_PREREQ(3, 4, 0)((4 << 20) + (2 << 10) + 1 >= ((3) << 20 ) + ((4) << 10) + (0)) |
225 | #define LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) __attribute__((noinline)) |
226 | #elif defined(_MSC_VER) |
227 | #define LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) __declspec(noinline) |
228 | #else |
229 | #define LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) |
230 | #endif |
231 | |
232 | /// LLVM_ATTRIBUTE_ALWAYS_INLINE - On compilers where we have a directive to do |
233 | /// so, mark a method "always inline" because it is performance sensitive. GCC |
234 | /// 3.4 supported this but is buggy in various cases and produces unimplemented |
235 | /// errors, just use it in GCC 4.0 and later. |
236 | #if __has_attribute(always_inline)1 || LLVM_GNUC_PREREQ(4, 0, 0)((4 << 20) + (2 << 10) + 1 >= ((4) << 20 ) + ((0) << 10) + (0)) |
237 | #define LLVM_ATTRIBUTE_ALWAYS_INLINE__attribute__((always_inline)) __attribute__((always_inline)) |
238 | #elif defined(_MSC_VER) |
239 | #define LLVM_ATTRIBUTE_ALWAYS_INLINE__attribute__((always_inline)) __forceinline |
240 | #else |
241 | #define LLVM_ATTRIBUTE_ALWAYS_INLINE__attribute__((always_inline)) |
242 | #endif |
243 | |
244 | #ifdef __GNUC__4 |
245 | #define LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) __attribute__((noreturn)) |
246 | #elif defined(_MSC_VER) |
247 | #define LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) __declspec(noreturn) |
248 | #else |
249 | #define LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) |
250 | #endif |
251 | |
252 | #if __has_attribute(returns_nonnull)1 || LLVM_GNUC_PREREQ(4, 9, 0)((4 << 20) + (2 << 10) + 1 >= ((4) << 20 ) + ((9) << 10) + (0)) |
253 | #define LLVM_ATTRIBUTE_RETURNS_NONNULL__attribute__((returns_nonnull)) __attribute__((returns_nonnull)) |
254 | #elif defined(_MSC_VER) |
255 | #define LLVM_ATTRIBUTE_RETURNS_NONNULL__attribute__((returns_nonnull)) _Ret_notnull_ |
256 | #else |
257 | #define LLVM_ATTRIBUTE_RETURNS_NONNULL__attribute__((returns_nonnull)) |
258 | #endif |
259 | |
260 | /// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a |
261 | /// pointer that does not alias any other valid pointer. |
262 | #ifdef __GNUC__4 |
263 | #define LLVM_ATTRIBUTE_RETURNS_NOALIAS__attribute__((__malloc__)) __attribute__((__malloc__)) |
264 | #elif defined(_MSC_VER) |
265 | #define LLVM_ATTRIBUTE_RETURNS_NOALIAS__attribute__((__malloc__)) __declspec(restrict) |
266 | #else |
267 | #define LLVM_ATTRIBUTE_RETURNS_NOALIAS__attribute__((__malloc__)) |
268 | #endif |
269 | |
270 | /// LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements. |
271 | #if __cplusplus201402L > 201402L && LLVM_HAS_CPP_ATTRIBUTE(fallthrough)201603L |
272 | #define LLVM_FALLTHROUGH[[gnu::fallthrough]] [[fallthrough]] |
273 | #elif LLVM_HAS_CPP_ATTRIBUTE(gnu::fallthrough)201603L |
274 | #define LLVM_FALLTHROUGH[[gnu::fallthrough]] [[gnu::fallthrough]] |
275 | #elif __has_attribute(fallthrough)1 |
276 | #define LLVM_FALLTHROUGH[[gnu::fallthrough]] __attribute__((fallthrough)) |
277 | #elif LLVM_HAS_CPP_ATTRIBUTE(clang::fallthrough)201603L |
278 | #define LLVM_FALLTHROUGH[[gnu::fallthrough]] [[clang::fallthrough]] |
279 | #else |
280 | #define LLVM_FALLTHROUGH[[gnu::fallthrough]] |
281 | #endif |
282 | |
283 | /// LLVM_REQUIRE_CONSTANT_INITIALIZATION - Apply this to globals to ensure that |
284 | /// they are constant initialized. |
285 | #if LLVM_HAS_CPP_ATTRIBUTE(clang::require_constant_initialization)1 |
286 | #define LLVM_REQUIRE_CONSTANT_INITIALIZATION[[clang::require_constant_initialization]] \ |
287 | [[clang::require_constant_initialization]] |
288 | #else |
289 | #define LLVM_REQUIRE_CONSTANT_INITIALIZATION[[clang::require_constant_initialization]] |
290 | #endif |
291 | |
292 | /// LLVM_EXTENSION - Support compilers where we have a keyword to suppress |
293 | /// pedantic diagnostics. |
294 | #ifdef __GNUC__4 |
295 | #define LLVM_EXTENSION__extension__ __extension__ |
296 | #else |
297 | #define LLVM_EXTENSION__extension__ |
298 | #endif |
299 | |
300 | // LLVM_ATTRIBUTE_DEPRECATED(decl, "message") |
301 | #if __has_feature(attribute_deprecated_with_message)1 |
302 | # define LLVM_ATTRIBUTE_DEPRECATED(decl, message)decl __attribute__((deprecated(message))) \ |
303 | decl __attribute__((deprecated(message))) |
304 | #elif defined(__GNUC__4) |
305 | # define LLVM_ATTRIBUTE_DEPRECATED(decl, message)decl __attribute__((deprecated(message))) \ |
306 | decl __attribute__((deprecated)) |
307 | #elif defined(_MSC_VER) |
308 | # define LLVM_ATTRIBUTE_DEPRECATED(decl, message)decl __attribute__((deprecated(message))) \ |
309 | __declspec(deprecated(message)) decl |
310 | #else |
311 | # define LLVM_ATTRIBUTE_DEPRECATED(decl, message)decl __attribute__((deprecated(message))) \ |
312 | decl |
313 | #endif |
314 | |
315 | /// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands |
316 | /// to an expression which states that it is undefined behavior for the |
317 | /// compiler to reach this point. Otherwise is not defined. |
318 | #if __has_builtin(__builtin_unreachable)1 || LLVM_GNUC_PREREQ(4, 5, 0)((4 << 20) + (2 << 10) + 1 >= ((4) << 20 ) + ((5) << 10) + (0)) |
319 | # define LLVM_BUILTIN_UNREACHABLE__builtin_unreachable() __builtin_unreachable() |
320 | #elif defined(_MSC_VER) |
321 | # define LLVM_BUILTIN_UNREACHABLE__builtin_unreachable() __assume(false) |
322 | #endif |
323 | |
324 | /// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression |
325 | /// which causes the program to exit abnormally. |
326 | #if __has_builtin(__builtin_trap)1 || LLVM_GNUC_PREREQ(4, 3, 0)((4 << 20) + (2 << 10) + 1 >= ((4) << 20 ) + ((3) << 10) + (0)) |
327 | # define LLVM_BUILTIN_TRAP__builtin_trap() __builtin_trap() |
328 | #elif defined(_MSC_VER) |
329 | // The __debugbreak intrinsic is supported by MSVC, does not require forward |
330 | // declarations involving platform-specific typedefs (unlike RaiseException), |
331 | // results in a call to vectored exception handlers, and encodes to a short |
332 | // instruction that still causes the trapping behavior we want. |
333 | # define LLVM_BUILTIN_TRAP__builtin_trap() __debugbreak() |
334 | #else |
335 | # define LLVM_BUILTIN_TRAP__builtin_trap() *(volatile int*)0x11 = 0 |
336 | #endif |
337 | |
338 | /// LLVM_BUILTIN_DEBUGTRAP - On compilers which support it, expands to |
339 | /// an expression which causes the program to break while running |
340 | /// under a debugger. |
341 | #if __has_builtin(__builtin_debugtrap)1 |
342 | # define LLVM_BUILTIN_DEBUGTRAP__builtin_debugtrap() __builtin_debugtrap() |
343 | #elif defined(_MSC_VER) |
344 | // The __debugbreak intrinsic is supported by MSVC and breaks while |
345 | // running under the debugger, and also supports invoking a debugger |
346 | // when the OS is configured appropriately. |
347 | # define LLVM_BUILTIN_DEBUGTRAP__builtin_debugtrap() __debugbreak() |
348 | #else |
349 | // Just continue execution when built with compilers that have no |
350 | // support. This is a debugging aid and not intended to force the |
351 | // program to abort if encountered. |
352 | # define LLVM_BUILTIN_DEBUGTRAP__builtin_debugtrap() |
353 | #endif |
354 | |
355 | /// \macro LLVM_ASSUME_ALIGNED |
356 | /// Returns a pointer with an assumed alignment. |
357 | #if __has_builtin(__builtin_assume_aligned)1 || LLVM_GNUC_PREREQ(4, 7, 0)((4 << 20) + (2 << 10) + 1 >= ((4) << 20 ) + ((7) << 10) + (0)) |
358 | # define LLVM_ASSUME_ALIGNED(p, a)__builtin_assume_aligned(p, a) __builtin_assume_aligned(p, a) |
359 | #elif defined(LLVM_BUILTIN_UNREACHABLE__builtin_unreachable()) |
360 | // As of today, clang does not support __builtin_assume_aligned. |
361 | # define LLVM_ASSUME_ALIGNED(p, a)__builtin_assume_aligned(p, a) \ |
362 | (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE__builtin_unreachable(), (p))) |
363 | #else |
364 | # define LLVM_ASSUME_ALIGNED(p, a)__builtin_assume_aligned(p, a) (p) |
365 | #endif |
366 | |
367 | /// \macro LLVM_PACKED |
368 | /// Used to specify a packed structure. |
369 | /// LLVM_PACKED( |
370 | /// struct A { |
371 | /// int i; |
372 | /// int j; |
373 | /// int k; |
374 | /// long long l; |
375 | /// }); |
376 | /// |
377 | /// LLVM_PACKED_START |
378 | /// struct B { |
379 | /// int i; |
380 | /// int j; |
381 | /// int k; |
382 | /// long long l; |
383 | /// }; |
384 | /// LLVM_PACKED_END |
385 | #ifdef _MSC_VER |
386 | # define LLVM_PACKED(d)d __attribute__((packed)) __pragma(pack(push, 1)) d __pragma(pack(pop)) |
387 | # define LLVM_PACKED_STARTpack(push, 1) __pragma(pack(push, 1)) |
388 | # define LLVM_PACKED_ENDpack(pop) __pragma(pack(pop)) |
389 | #else |
390 | # define LLVM_PACKED(d)d __attribute__((packed)) d __attribute__((packed)) |
391 | # define LLVM_PACKED_STARTpack(push, 1) _Pragma("pack(push, 1)")pack(push, 1) |
392 | # define LLVM_PACKED_ENDpack(pop) _Pragma("pack(pop)")pack(pop) |
393 | #endif |
394 | |
395 | /// \macro LLVM_PTR_SIZE |
396 | /// A constant integer equivalent to the value of sizeof(void*). |
397 | /// Generally used in combination with alignas or when doing computation in the |
398 | /// preprocessor. |
399 | #ifdef __SIZEOF_POINTER__8 |
400 | # define LLVM_PTR_SIZE8 __SIZEOF_POINTER__8 |
401 | #elif defined(_WIN64) |
402 | # define LLVM_PTR_SIZE8 8 |
403 | #elif defined(_WIN32) |
404 | # define LLVM_PTR_SIZE8 4 |
405 | #elif defined(_MSC_VER) |
406 | # error "could not determine LLVM_PTR_SIZE as a constant int for MSVC" |
407 | #else |
408 | # define LLVM_PTR_SIZE8 sizeof(void *) |
409 | #endif |
410 | |
411 | /// \macro LLVM_MEMORY_SANITIZER_BUILD |
412 | /// Whether LLVM itself is built with MemorySanitizer instrumentation. |
413 | #if __has_feature(memory_sanitizer)0 |
414 | # define LLVM_MEMORY_SANITIZER_BUILD0 1 |
415 | # include <sanitizer/msan_interface.h> |
416 | # define LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE __attribute__((no_sanitize_memory)) |
417 | #else |
418 | # define LLVM_MEMORY_SANITIZER_BUILD0 0 |
419 | # define __msan_allocated_memory(p, size) |
420 | # define __msan_unpoison(p, size) |
421 | # define LLVM_NO_SANITIZE_MEMORY_ATTRIBUTE |
422 | #endif |
423 | |
424 | /// \macro LLVM_ADDRESS_SANITIZER_BUILD |
425 | /// Whether LLVM itself is built with AddressSanitizer instrumentation. |
426 | #if __has_feature(address_sanitizer)0 || defined(__SANITIZE_ADDRESS__) |
427 | # define LLVM_ADDRESS_SANITIZER_BUILD0 1 |
428 | # include <sanitizer/asan_interface.h> |
429 | #else |
430 | # define LLVM_ADDRESS_SANITIZER_BUILD0 0 |
431 | # define __asan_poison_memory_region(p, size) |
432 | # define __asan_unpoison_memory_region(p, size) |
433 | #endif |
434 | |
435 | /// \macro LLVM_THREAD_SANITIZER_BUILD |
436 | /// Whether LLVM itself is built with ThreadSanitizer instrumentation. |
437 | #if __has_feature(thread_sanitizer)0 || defined(__SANITIZE_THREAD__) |
438 | # define LLVM_THREAD_SANITIZER_BUILD0 1 |
439 | #else |
440 | # define LLVM_THREAD_SANITIZER_BUILD0 0 |
441 | #endif |
442 | |
443 | #if LLVM_THREAD_SANITIZER_BUILD0 |
444 | // Thread Sanitizer is a tool that finds races in code. |
445 | // See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations . |
446 | // tsan detects these exact functions by name. |
447 | #ifdef __cplusplus201402L |
448 | extern "C" { |
449 | #endif |
450 | void AnnotateHappensAfter(const char *file, int line, const volatile void *cv); |
451 | void AnnotateHappensBefore(const char *file, int line, const volatile void *cv); |
452 | void AnnotateIgnoreWritesBegin(const char *file, int line); |
453 | void AnnotateIgnoreWritesEnd(const char *file, int line); |
454 | #ifdef __cplusplus201402L |
455 | } |
456 | #endif |
457 | |
458 | // This marker is used to define a happens-before arc. The race detector will |
459 | // infer an arc from the begin to the end when they share the same pointer |
460 | // argument. |
461 | # define TsanHappensBefore(cv) AnnotateHappensBefore(__FILE__"/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/Support/Compiler.h", __LINE__461, cv) |
462 | |
463 | // This marker defines the destination of a happens-before arc. |
464 | # define TsanHappensAfter(cv) AnnotateHappensAfter(__FILE__"/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/Support/Compiler.h", __LINE__464, cv) |
465 | |
466 | // Ignore any races on writes between here and the next TsanIgnoreWritesEnd. |
467 | # define TsanIgnoreWritesBegin() AnnotateIgnoreWritesBegin(__FILE__"/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/Support/Compiler.h", __LINE__467) |
468 | |
469 | // Resume checking for racy writes. |
470 | # define TsanIgnoreWritesEnd() AnnotateIgnoreWritesEnd(__FILE__"/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/Support/Compiler.h", __LINE__470) |
471 | #else |
472 | # define TsanHappensBefore(cv) |
473 | # define TsanHappensAfter(cv) |
474 | # define TsanIgnoreWritesBegin() |
475 | # define TsanIgnoreWritesEnd() |
476 | #endif |
477 | |
478 | /// \macro LLVM_NO_SANITIZE |
479 | /// Disable a particular sanitizer for a function. |
480 | #if __has_attribute(no_sanitize)1 |
481 | #define LLVM_NO_SANITIZE(KIND)__attribute__((no_sanitize(KIND))) __attribute__((no_sanitize(KIND))) |
482 | #else |
483 | #define LLVM_NO_SANITIZE(KIND)__attribute__((no_sanitize(KIND))) |
484 | #endif |
485 | |
486 | /// Mark debug helper function definitions like dump() that should not be |
487 | /// stripped from debug builds. |
488 | /// Note that you should also surround dump() functions with |
489 | /// `#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)` so they do always |
490 | /// get stripped in release builds. |
491 | // FIXME: Move this to a private config.h as it's not usable in public headers. |
492 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
493 | #define LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) LLVM_ATTRIBUTE_USED__attribute__((__used__)) |
494 | #else |
495 | #define LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) |
496 | #endif |
497 | |
498 | /// \macro LLVM_PRETTY_FUNCTION |
499 | /// Gets a user-friendly looking function signature for the current scope |
500 | /// using the best available method on each platform. The exact format of the |
501 | /// resulting string is implementation specific and non-portable, so this should |
502 | /// only be used, for example, for logging or diagnostics. |
503 | #if defined(_MSC_VER) |
504 | #define LLVM_PRETTY_FUNCTION__PRETTY_FUNCTION__ __FUNCSIG__ |
505 | #elif defined(__GNUC__4) || defined(__clang__1) |
506 | #define LLVM_PRETTY_FUNCTION__PRETTY_FUNCTION__ __PRETTY_FUNCTION__ |
507 | #else |
508 | #define LLVM_PRETTY_FUNCTION__PRETTY_FUNCTION__ __func__ |
509 | #endif |
510 | |
511 | /// \macro LLVM_THREAD_LOCAL |
512 | /// A thread-local storage specifier which can be used with globals, |
513 | /// extern globals, and static globals. |
514 | /// |
515 | /// This is essentially an extremely restricted analog to C++11's thread_local |
516 | /// support. It uses thread_local if available, falling back on gcc __thread |
517 | /// if not. __thread doesn't support many of the C++11 thread_local's |
518 | /// features. You should only use this for PODs that you can statically |
519 | /// initialize to some constant value. In almost all circumstances this is most |
520 | /// appropriate for use with a pointer, integer, or small aggregation of |
521 | /// pointers and integers. |
522 | #if LLVM_ENABLE_THREADS1 |
523 | #if __has_feature(cxx_thread_local)1 || defined(_MSC_VER) |
524 | #define LLVM_THREAD_LOCALthread_local thread_local |
525 | #else |
526 | // Clang, GCC, and other compatible compilers used __thread prior to C++11 and |
527 | // we only need the restricted functionality that provides. |
528 | #define LLVM_THREAD_LOCALthread_local __thread |
529 | #endif |
530 | #else // !LLVM_ENABLE_THREADS |
531 | // If threading is disabled entirely, this compiles to nothing and you get |
532 | // a normal global variable. |
533 | #define LLVM_THREAD_LOCALthread_local |
534 | #endif |
535 | |
536 | /// \macro LLVM_ENABLE_EXCEPTIONS |
537 | /// Whether LLVM is built with exception support. |
538 | #if __has_feature(cxx_exceptions)0 |
539 | #define LLVM_ENABLE_EXCEPTIONS 1 |
540 | #elif defined(__GNUC__4) && defined(__EXCEPTIONS) |
541 | #define LLVM_ENABLE_EXCEPTIONS 1 |
542 | #elif defined(_MSC_VER) && defined(_CPPUNWIND) |
543 | #define LLVM_ENABLE_EXCEPTIONS 1 |
544 | #endif |
545 | |
546 | #ifdef __cplusplus201402L |
547 | namespace llvm { |
548 | |
549 | /// Allocate a buffer of memory with the given size and alignment. |
550 | /// |
551 | /// When the compiler supports aligned operator new, this will use it to to |
552 | /// handle even over-aligned allocations. |
553 | /// |
554 | /// However, this doesn't make any attempt to leverage the fancier techniques |
555 | /// like posix_memalign due to portability. It is mostly intended to allow |
556 | /// compatibility with platforms that, after aligned allocation was added, use |
557 | /// reduced default alignment. |
558 | inline void *allocate_buffer(size_t Size, size_t Alignment) { |
559 | return ::operator new(Size |
560 | #ifdef __cpp_aligned_new |
561 | , |
562 | std::align_val_t(Alignment) |
563 | #endif |
564 | ); |
565 | } |
566 | |
567 | /// Deallocate a buffer of memory with the given size and alignment. |
568 | /// |
569 | /// If supported, this will used the sized delete operator. Also if supported, |
570 | /// this will pass the alignment to the delete operator. |
571 | /// |
572 | /// The pointer must have been allocated with the corresponding new operator, |
573 | /// most likely using the above helper. |
574 | inline void deallocate_buffer(void *Ptr, size_t Size, size_t Alignment) { |
575 | ::operator delete(Ptr |
576 | #ifdef __cpp_sized_deallocation |
577 | , |
578 | Size |
579 | #endif |
580 | #ifdef __cpp_aligned_new |
581 | , |
582 | std::align_val_t(Alignment) |
583 | #endif |
584 | ); |
585 | } |
586 | |
587 | } // End namespace llvm |
588 | |
589 | #endif // __cplusplus |
590 | #endif |