Skip to content

Commit 802e63a

Browse files
authored
Merge pull request #67973 from zachary0kent/lazy-immediate-globals
[Immediate] JIT'ing Globals
2 parents c0fa16e + 6aafeec commit 802e63a

36 files changed

+1236
-540
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ SWIFT_TYPEID(FragileFunctionKind)
3737
SWIFT_TYPEID(PolymorphicEffectKind)
3838
SWIFT_TYPEID(PolymorphicEffectRequirementList)
3939
SWIFT_TYPEID(TangentPropertyInfo)
40-
SWIFT_TYPEID(SymbolSourceMap)
4140
SWIFT_TYPEID(Type)
4241
SWIFT_TYPEID(TypePair)
4342
SWIFT_TYPEID(TypeWitnessAndDecl)

include/swift/AST/ASTTypeIDs.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ struct FragileFunctionKind;
7070
enum class PolymorphicEffectKind : uint8_t;
7171
class PolymorphicEffectRequirementList;
7272
class SourceFile;
73-
class SymbolSourceMap;
7473
struct TangentPropertyInfo;
7574
class Type;
7675
class TypeAliasDecl;

include/swift/AST/SILGenRequests.h

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/EvaluatorDependencies.h"
2222
#include "swift/AST/SimpleRequest.h"
2323
#include "swift/AST/SourceFile.h"
24+
#include "swift/AST/TBDGenRequests.h"
2425
#include "swift/SIL/SILDeclRef.h"
2526

2627
namespace swift {
@@ -43,6 +44,8 @@ void reportEvaluatedRequest(UnifiedStatsReporter &stats,
4344

4445
using SILRefsToEmit = llvm::SmallVector<SILDeclRef, 1>;
4546

47+
using SymbolSources = llvm::SmallVector<SymbolSource, 1>;
48+
4649
/// Describes a file or module to be lowered to SIL.
4750
struct ASTLoweringDescriptor {
4851
llvm::PointerUnion<FileUnit *, ModuleDecl *> context;
@@ -52,20 +55,17 @@ struct ASTLoweringDescriptor {
5255

5356
/// A specific set of SILDeclRefs to emit. If set, only these refs will be
5457
/// emitted. Otherwise the entire \c context will be emitted.
55-
llvm::Optional<SILRefsToEmit> refsToEmit;
58+
llvm::Optional<SymbolSources> SourcesToEmit;
5659

5760
friend llvm::hash_code hash_value(const ASTLoweringDescriptor &owner) {
5861
return llvm::hash_combine(owner.context, (void *)&owner.conv,
59-
(void *)&owner.opts,
60-
owner.refsToEmit);
62+
(void *)&owner.opts, owner.SourcesToEmit);
6163
}
6264

6365
friend bool operator==(const ASTLoweringDescriptor &lhs,
6466
const ASTLoweringDescriptor &rhs) {
65-
return lhs.context == rhs.context &&
66-
&lhs.conv == &rhs.conv &&
67-
&lhs.opts == &rhs.opts &&
68-
lhs.refsToEmit == rhs.refsToEmit;
67+
return lhs.context == rhs.context && &lhs.conv == &rhs.conv &&
68+
&lhs.opts == &rhs.opts && lhs.SourcesToEmit == rhs.SourcesToEmit;
6969
}
7070

7171
friend bool operator!=(const ASTLoweringDescriptor &lhs,
@@ -76,17 +76,19 @@ struct ASTLoweringDescriptor {
7676
public:
7777
static ASTLoweringDescriptor
7878
forFile(FileUnit &sf, Lowering::TypeConverter &conv, const SILOptions &opts,
79-
llvm::Optional<SILRefsToEmit> refsToEmit = llvm::None,
79+
llvm::Optional<SymbolSources> SourcesToEmit = llvm::None,
8080
const IRGenOptions *irgenOptions = nullptr) {
81-
return ASTLoweringDescriptor{&sf, conv, opts, irgenOptions, refsToEmit};
81+
return ASTLoweringDescriptor{&sf, conv, opts, irgenOptions,
82+
std::move(SourcesToEmit)};
8283
}
8384

8485
static ASTLoweringDescriptor
8586
forWholeModule(ModuleDecl *mod, Lowering::TypeConverter &conv,
8687
const SILOptions &opts,
87-
llvm::Optional<SILRefsToEmit> refsToEmit = llvm::None,
88+
llvm::Optional<SymbolSources> SourcesToEmit = llvm::None,
8889
const IRGenOptions *irgenOptions = nullptr) {
89-
return ASTLoweringDescriptor{mod, conv, opts, irgenOptions, refsToEmit};
90+
return ASTLoweringDescriptor{mod, conv, opts, irgenOptions,
91+
std::move(SourcesToEmit)};
9092
}
9193

9294
/// Retrieves the files to generate SIL for. If the descriptor is configured

include/swift/AST/SourceFile.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,14 @@ class SourceFile final : public FileUnit {
166166
/// if it were done from OpaqueResultTypeRequest.
167167
llvm::SetVector<OpaqueTypeDecl *> UnvalidatedOpaqueReturnTypes;
168168

169+
/// The list of functions defined in this file whose bodies have yet to be
170+
/// typechecked. They must be held in this list instead of eagerly validated
171+
/// because their bodies may force us to perform semantic checks of arbitrary
172+
/// complexity, and we currently cannot handle those checks in isolation. E.g.
173+
/// we cannot, in general, perform witness matching on singular requirements
174+
/// unless the entire conformance has been evaluated.
175+
std::vector<AbstractFunctionDecl *> DelayedFunctions;
176+
169177
/// The list of top-level items in the source file. This is \c None if
170178
/// they have not yet been parsed.
171179
/// FIXME: Once addTopLevelDecl/prependTopLevelDecl
@@ -259,13 +267,11 @@ class SourceFile final : public FileUnit {
259267
/// The list of local type declarations in the source file.
260268
llvm::SetVector<TypeDecl *> LocalTypeDecls;
261269

262-
/// The list of functions defined in this file whose bodies have yet to be
263-
/// typechecked. They must be held in this list instead of eagerly validated
264-
/// because their bodies may force us to perform semantic checks of arbitrary
265-
/// complexity, and we currently cannot handle those checks in isolation. E.g.
266-
/// we cannot, in general, perform witness matching on singular requirements
267-
/// unless the entire conformance has been evaluated.
268-
std::vector<AbstractFunctionDecl *> DelayedFunctions;
270+
/// Defer type checking of `AFD` to the end of `Sema`
271+
void addDelayedFunction(AbstractFunctionDecl *AFD);
272+
273+
/// Typecheck the bodies of all lazily checked functions
274+
void typeCheckDelayedFunctions();
269275

270276
/// A mapping from Objective-C selectors to the methods that have
271277
/// those selectors.

include/swift/AST/TBDGenRequests.h

Lines changed: 84 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#ifndef SWIFT_TBDGEN_REQUESTS_H
1818
#define SWIFT_TBDGEN_REQUESTS_H
1919

20+
#include "llvm/ExecutionEngine/JITSymbol.h"
21+
2022
#include "swift/AST/ASTTypeIDs.h"
2123
#include "swift/AST/SimpleRequest.h"
2224
#include "swift/IRGen/Linking.h"
@@ -148,6 +150,10 @@ class SymbolSource {
148150
/// A symbol introduced when emitting a SIL decl.
149151
SIL,
150152

153+
/// A symbol introduced when emitting a SIL global variable.
154+
/// Only used in piecewise compilation for Immediate mode.
155+
Global,
156+
151157
/// A symbol introduced when emitting LLVM IR.
152158
IR,
153159

@@ -162,13 +168,17 @@ class SymbolSource {
162168

163169
private:
164170
union {
171+
VarDecl *Global;
165172
SILDeclRef silDeclRef;
166173
irgen::LinkEntity irEntity;
167174
};
168175

169176
explicit SymbolSource(SILDeclRef ref) : kind(Kind::SIL) {
170177
silDeclRef = ref;
171178
}
179+
180+
SymbolSource(VarDecl *Global) : kind(Kind::Global), Global(Global) {}
181+
172182
explicit SymbolSource(irgen::LinkEntity entity) : kind(Kind::IR) {
173183
irEntity = entity;
174184
}
@@ -180,6 +190,9 @@ class SymbolSource {
180190
static SymbolSource forSILDeclRef(SILDeclRef ref) {
181191
return SymbolSource{ref};
182192
}
193+
194+
static SymbolSource forGlobal(VarDecl *Global) { return Global; }
195+
183196
static SymbolSource forIRLinkEntity(irgen::LinkEntity entity) {
184197
return SymbolSource{entity};
185198
}
@@ -198,49 +211,93 @@ class SymbolSource {
198211
assert(kind == Kind::SIL);
199212
return silDeclRef;
200213
}
214+
215+
VarDecl *getGlobal() const {
216+
assert(kind == Kind::Global);
217+
return Global;
218+
}
219+
201220
irgen::LinkEntity getIRLinkEntity() const {
202221
assert(kind == Kind::IR);
203222
return irEntity;
204223
}
205-
};
206-
207-
/// Maps a symbol back to its source for lazy compilation.
208-
class SymbolSourceMap {
209-
friend class SymbolSourceMapRequest;
210-
211-
using Storage = llvm::StringMap<SymbolSource>;
212-
const Storage *storage;
213224

214-
explicit SymbolSourceMap(const Storage *storage) : storage(storage) {
215-
assert(storage);
225+
/// Typecheck the entity wrapped by this `SymbolSource`
226+
void typecheck() const {
227+
switch (kind) {
228+
case Kind::SIL: {
229+
if (auto *AFD = silDeclRef.getAbstractFunctionDecl())
230+
// If this entity is a `SILFunction`, check its body
231+
AFD->getTypecheckedBody();
232+
break;
233+
}
234+
case Kind::Global:
235+
case Kind::IR:
236+
case Kind::LinkerDirective:
237+
case Kind::Unknown:
238+
// Nothing to do
239+
break;
240+
}
216241
}
217242

218-
public:
219-
llvm::Optional<SymbolSource> find(StringRef symbol) const {
220-
auto result = storage->find(symbol);
221-
if (result == storage->end())
222-
return llvm::None;
223-
return result->second;
243+
friend llvm::hash_code hash_value(const SymbolSource &S) {
244+
auto Kind = S.kind;
245+
switch (Kind) {
246+
case Kind::SIL:
247+
return llvm::hash_combine(Kind, S.silDeclRef);
248+
case Kind::Global:
249+
return llvm::hash_combine(Kind, S.Global);
250+
case Kind::IR:
251+
return llvm::hash_combine(Kind, S.irEntity);
252+
case Kind::LinkerDirective:
253+
case Kind::Unknown:
254+
return llvm::hash_value(Kind);
255+
}
224256
}
225257

226-
friend bool operator==(const SymbolSourceMap &lhs,
227-
const SymbolSourceMap &rhs) {
228-
return lhs.storage == rhs.storage;
258+
friend bool operator==(const SymbolSource &LHS, const SymbolSource &RHS) {
259+
if (LHS.kind != RHS.kind)
260+
return false;
261+
switch (LHS.kind) {
262+
case Kind::SIL:
263+
return LHS.silDeclRef == RHS.silDeclRef;
264+
case Kind::Global:
265+
return LHS.Global == RHS.Global;
266+
case Kind::IR:
267+
return LHS.irEntity == RHS.irEntity;
268+
case Kind::LinkerDirective:
269+
case Kind::Unknown:
270+
return true;
271+
}
229272
}
230-
friend bool operator!=(const SymbolSourceMap &lhs,
231-
const SymbolSourceMap &rhs) {
232-
return !(lhs == rhs);
273+
274+
friend bool operator!=(const SymbolSource &LHS, const SymbolSource &RHS) {
275+
return !(LHS == RHS);
233276
}
234277

235-
friend void simple_display(llvm::raw_ostream &out, const SymbolSourceMap &) {
236-
out << "(symbol storage map)";
278+
llvm::JITSymbolFlags getJITSymbolFlags() const {
279+
switch (kind) {
280+
case Kind::SIL:
281+
return llvm::JITSymbolFlags::Callable | llvm::JITSymbolFlags::Exported;
282+
case Kind::Global:
283+
return llvm::JITSymbolFlags::Exported;
284+
case Kind::IR:
285+
llvm_unreachable("Unimplemented: Symbol flags for LinkEntities");
286+
case Kind::LinkerDirective:
287+
llvm_unreachable("Unsupported: Symbol flags for linker directives");
288+
case Kind::Unknown:
289+
llvm_unreachable("Unsupported: Symbol flags for unknown source");
290+
}
237291
}
238292
};
239293

294+
/// Maps a symbol back to its source for lazy compilation.
295+
using SymbolSourceMap = llvm::StringMap<SymbolSource>;
296+
240297
/// Computes a map of symbols to their SymbolSource for a file or module.
241298
class SymbolSourceMapRequest
242299
: public SimpleRequest<SymbolSourceMapRequest,
243-
SymbolSourceMap(TBDGenDescriptor),
300+
const SymbolSourceMap *(TBDGenDescriptor),
244301
RequestFlags::Cached> {
245302
public:
246303
using SimpleRequest::SimpleRequest;
@@ -249,7 +306,8 @@ class SymbolSourceMapRequest
249306
friend SimpleRequest;
250307

251308
// Evaluation.
252-
SymbolSourceMap evaluate(Evaluator &evaluator, TBDGenDescriptor desc) const;
309+
const SymbolSourceMap *evaluate(Evaluator &evaluator,
310+
TBDGenDescriptor desc) const;
253311

254312
public:
255313
// Cached.

include/swift/AST/TBDGenTypeIDZone.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ SWIFT_REQUEST(TBDGen, PublicSymbolsRequest,
2020
std::vector<std::string>(TBDGenDescriptor),
2121
Uncached, NoLocationInfo)
2222
SWIFT_REQUEST(TBDGen, SymbolSourceMapRequest,
23-
SymbolSourceMap(TBDGenDescriptor),
23+
const SymbolSourceMap *(TBDGenDescriptor),
2424
Cached, NoLocationInfo)
2525
SWIFT_REQUEST(TBDGen, APIGenRequest, apigen::API(TBDGenDescriptor), Uncached,
2626
NoLocationInfo)

include/swift/AST/TypeCheckRequests.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,8 +2997,7 @@ class TypeCheckSourceFileRequest
29972997
friend SimpleRequest;
29982998

29992999
// Evaluation.
3000-
evaluator::SideEffect
3001-
evaluate(Evaluator &evaluator, SourceFile *SF) const;
3000+
evaluator::SideEffect evaluate(Evaluator &evaluator, SourceFile *SF) const;
30023001

30033002
public:
30043003
// Separate caching.

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ SUPPRESSIBLE_LANGUAGE_FEATURE(ExtensionMacroAttr, 0, "@attached(extension)", tru
129129
// Whether to enable @_used and @_section attributes
130130
EXPERIMENTAL_FEATURE(SymbolLinkageMarkers, true)
131131

132+
// Whether to compile scripts lazily in immediate mode
133+
EXPERIMENTAL_FEATURE(LazyImmediate, false)
134+
132135
// FIXME: MoveOnlyClasses is not intended to be in production,
133136
// but our tests currently rely on it, and we want to run those
134137
// tests in non-asserts builds too.

include/swift/Basic/LangOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,9 @@ namespace swift {
799799

800800
/// See \ref FrontendOptions.PrintFullConvention
801801
bool PrintFullConvention = false;
802+
803+
/// Defer typechecking of declarations to their use at runtime
804+
bool DeferToRuntime = false;
802805
};
803806

804807
/// Options for controlling the behavior of the Clang importer.

include/swift/IRGen/Linking.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,20 @@ class LinkEntity {
515515
return Kind(LINKENTITY_GET_FIELD(Data, Kind));
516516
}
517517

518+
friend llvm::hash_code hash_value(const LinkEntity &Entity) {
519+
return llvm::hash_combine(Entity.Pointer, Entity.SecondaryPointer,
520+
Entity.Data);
521+
}
522+
523+
friend bool operator==(const LinkEntity &LHS, const LinkEntity &RHS) {
524+
return LHS.Pointer == RHS.Pointer &&
525+
LHS.SecondaryPointer == RHS.SecondaryPointer && LHS.Data == RHS.Data;
526+
}
527+
528+
friend bool operator!=(const LinkEntity &LHS, const LinkEntity &RHS) {
529+
return !(LHS == RHS);
530+
}
531+
518532
static bool isDeclKind(Kind k) {
519533
return k <= Kind::AsyncFunctionPointerAST;
520534
}

include/swift/Immediate/Immediate.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ namespace swift {
4141
int RunImmediately(CompilerInstance &CI, const ProcessCmdLine &CmdLine,
4242
const IRGenOptions &IRGenOpts, const SILOptions &SILOpts,
4343
std::unique_ptr<SILModule> &&SM);
44+
45+
int RunImmediatelyFromAST(CompilerInstance &CI);
46+
4447
} // end namespace swift
4548

4649
#endif // SWIFT_IMMEDIATE_IMMEDIATE_H

0 commit comments

Comments
 (0)