Skip to content

Commit 90e7595

Browse files
committed
[embedded] Add a frontend flag to drop all code from a module and emit an empty object file
1 parent 2f44b0a commit 90e7595

File tree

12 files changed

+118
-1
lines changed

12 files changed

+118
-1
lines changed

include/swift/AST/SILOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ class SILOptions {
170170
/// Whether to stop the optimization pipeline after serializing SIL.
171171
bool StopOptimizationAfterSerialization = false;
172172

173+
/// Whether to drop all SIL after serializing SIL and continue compilation
174+
/// with an empty SIL module.
175+
bool DropAllSILAfterSerialization = false;
176+
173177
/// Whether to stop the optimization pipeline right before we lower ownership
174178
/// and go from OSSA to non-ownership SIL.
175179
bool StopOptimizationBeforeLoweringOwnership = false;

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,10 @@ def enable_single_module_llvm_emission: Flag<["-"], "enable-single-module-llvm-e
580580
Flags<[FrontendOption, NoInteractiveOption]>,
581581
HelpText<"Emit LLVM IR into a single LLVM module in multithreaded mode.">;
582582

583+
def emit_empty_object_file : Flag<["-"], "emit-empty-object-file">,
584+
Flags<[FrontendOption, NoInteractiveOption]>,
585+
HelpText<"Produce a valid but dummy object file when building a library module">;
586+
583587
def stack_promotion_checks : Flag<["-"], "emit-stack-promotion-checks">,
584588
HelpText<"Emit runtime checks for correct stack promotion of objects.">;
585589

include/swift/SIL/SILModule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,9 @@ class SILModule {
839839
/// Look up a specialized VTable
840840
SILVTable *lookUpSpecializedVTable(SILType classTy);
841841

842+
/// Remove all VTables and specialized VTables from the module.
843+
void eraseAllVTables();
844+
842845
/// Attempt to lookup the function corresponding to \p Member in the class
843846
/// hierarchy of \p Class.
844847
SILFunction *lookUpFunctionInVTable(ClassDecl *Class, SILDeclRef Member);

include/swift/SILOptimizer/PassManager/Passes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@ PASS(SimplifyUnreachableContainingBlocks, "simplify-unreachable-containing-block
452452
"Utility pass. Removes all non-term insts from blocks with unreachable terms")
453453
PASS(SerializeSILPass, "serialize-sil",
454454
"Utility pass. Serializes the current SILModule")
455+
PASS(DropAllSILPass, "drop-all-sil",
456+
"Utility pass. Drops all SIL from the SILModule")
455457
PASS(UnitTestRunner, "test-runner",
456458
"Utility pass. Parses arguments and runs code with them.")
457459
PASS(YieldOnceCheck, "yield-once-check",

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,6 +2185,10 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
21852185
FEOpts.RequestedAction == FrontendOptions::ActionType::CompileModuleFromInterface)
21862186
Opts.StopOptimizationAfterSerialization = true;
21872187

2188+
if (Args.getLastArg(OPT_emit_empty_object_file)) {
2189+
Opts.DropAllSILAfterSerialization = true;
2190+
}
2191+
21882192
// Propagate the typechecker's understanding of
21892193
// -experimental-skip-*-function-bodies to SIL.
21902194
Opts.SkipFunctionBodies = TCOpts.SkipFunctionBodies;

lib/IRGen/GenDecl.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,11 @@ class PrettySynthesizedFileUnitEmission : public llvm::PrettyStackTraceEntry {
454454

455455
/// Emit all the top-level code in the source file.
456456
void IRGenModule::emitSourceFile(SourceFile &SF) {
457+
if (getSILModule().getOptions().DropAllSILAfterSerialization) {
458+
// We're asked to emit an empty IR module
459+
return;
460+
}
461+
457462
// Type-check the file if we haven't already (this may be necessary for .sil
458463
// files, which don't get fully type-checked by parsing).
459464
performTypeChecking(SF);
@@ -1259,6 +1264,11 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {
12591264

12601265
void IRGenerator::emitGlobalTopLevel(
12611266
const std::vector<std::string> &linkerDirectives) {
1267+
if (PrimaryIGM->getSILModule().getOptions().DropAllSILAfterSerialization) {
1268+
// We're asked to emit an empty IR module
1269+
return;
1270+
}
1271+
12621272
// Generate order numbers for the functions in the SIL module that
12631273
// correspond to definitions in the LLVM module.
12641274
unsigned nextOrderNumber = 0;

lib/IRGen/GenReflection.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,11 @@ llvm::ArrayRef<CanType> IRGenModule::getOrCreateSpecialStlibBuiltinTypes() {
16671667
}
16681668

16691669
void IRGenModule::emitBuiltinReflectionMetadata() {
1670+
if (getSILModule().getOptions().DropAllSILAfterSerialization) {
1671+
// We're asked to emit an empty IR module
1672+
return;
1673+
}
1674+
16701675
if (getSwiftModule()->isStdlibModule()) {
16711676
auto SpecialBuiltins = getOrCreateSpecialStlibBuiltinTypes();
16721677
BuiltinTypes.insert(SpecialBuiltins.begin(), SpecialBuiltins.end());

lib/IRGen/IRGenModule.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1912,7 +1912,7 @@ void IRGenModule::cleanupClangCodeGenMetadata() {
19121912
bool IRGenModule::finalize() {
19131913
const char *ModuleHashVarName = "llvm.swift_module_hash";
19141914
if (IRGen.Opts.OutputKind == IRGenOutputKind::ObjectFile &&
1915-
!Module.getGlobalVariable(ModuleHashVarName)) {
1915+
!Module.getGlobalVariable(ModuleHashVarName) && !getSILModule().getOptions().DropAllSILAfterSerialization) {
19161916
// Create a global variable into which we will store the hash of the
19171917
// module (used for incremental compilation).
19181918
// We have to create the variable now (before we emit the global lists).
@@ -1969,6 +1969,14 @@ bool IRGenModule::finalize() {
19691969
if (F.hasDLLImportStorageClass())
19701970
F.setDSOLocal(false);
19711971

1972+
if (getSILModule().getOptions().DropAllSILAfterSerialization) {
1973+
// We're asked to emit an empty IR module, check that that's actually true
1974+
if (Module.global_size() != 0 || Module.size() != 0) {
1975+
Module.dump();
1976+
llvm::report_fatal_error("Module is not empty");
1977+
}
1978+
}
1979+
19721980
return true;
19731981
}
19741982

lib/SIL/IR/SILModule.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,16 @@ SILVTable *SILModule::lookUpVTable(const ClassDecl *C,
484484
return Vtbl;
485485
}
486486

487+
void SILModule::eraseAllVTables() {
488+
for (auto vt : vtables)
489+
vt->~SILVTable();
490+
491+
VTableMap.clear();
492+
SpecializedVTableMap.clear();
493+
vtables.clear();
494+
VTableEntryCache.clear();
495+
}
496+
487497
SILMoveOnlyDeinit *SILModule::lookUpMoveOnlyDeinit(const NominalTypeDecl *C,
488498
bool deserializeLazily) {
489499
if (!C)

lib/SILOptimizer/PassManager/PassPipeline.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,9 @@ SILPassPipelinePlan::getPerformancePassPipeline(const SILOptions &Options) {
997997
if (Options.StopOptimizationAfterSerialization)
998998
return P;
999999

1000+
if (Options.DropAllSILAfterSerialization)
1001+
P.addDropAllSILPass();
1002+
10001003
// After serialization run the function pass pipeline to iteratively lower
10011004
// high-level constructs like @_semantics calls.
10021005
addMidLevelFunctionPipeline(P);
@@ -1055,6 +1058,9 @@ SILPassPipelinePlan::getOnonePassPipeline(const SILOptions &Options) {
10551058
P.startPipeline("Serialization");
10561059
P.addSerializeSILPass();
10571060

1061+
if (Options.DropAllSILAfterSerialization)
1062+
P.addDropAllSILPass();
1063+
10581064
// Now that we have serialized, propagate debug info.
10591065
P.addMovedAsyncVarDebugInfoPropagator();
10601066

lib/SILOptimizer/UtilityPasses/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ target_sources(swiftSILOptimizer PRIVATE
1313
ComputeLoopInfo.cpp
1414
ConstantEvaluatorTester.cpp
1515
ConstantEvaluableSubsetChecker.cpp
16+
DropAllSILPass.cpp
1617
EpilogueARCMatcherDumper.cpp
1718
EpilogueRetainReleaseMatcherDumper.cpp
1819
FunctionOrderPrinter.cpp
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//===--- DropAllSILPass.cpp -----------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#define DEBUG_TYPE "drop-all-sil"
14+
#include "swift/SIL/SILFunction.h"
15+
#include "swift/SILOptimizer/PassManager/Passes.h"
16+
#include "swift/SILOptimizer/PassManager/Transforms.h"
17+
18+
using namespace swift;
19+
20+
namespace {
21+
22+
class DropAllSILPass : public SILModuleTransform {
23+
public:
24+
DropAllSILPass() {}
25+
26+
void run() override {
27+
auto &M = *getModule();
28+
29+
llvm::SmallVector<SILFunction *, 16> FunctionsToErase;
30+
llvm::SmallVector<SILGlobalVariable *, 16> GlobalsToErase;
31+
32+
for (SILFunction &F : M) {
33+
FunctionsToErase.push_back(&F);
34+
}
35+
36+
for (SILGlobalVariable &G : M.getSILGlobals()) {
37+
GlobalsToErase.push_back(&G);
38+
}
39+
40+
M.eraseAllVTables();
41+
42+
for (SILFunction *F : FunctionsToErase) {
43+
notifyWillDeleteFunction(F);
44+
M.eraseFunction(F);
45+
M.removeFromZombieList(F->getName());
46+
}
47+
48+
for (SILGlobalVariable *G : GlobalsToErase) {
49+
M.eraseGlobalVariable(G);
50+
}
51+
52+
invalidateFunctionTables();
53+
}
54+
};
55+
56+
}
57+
58+
SILTransform *swift::createDropAllSILPass() {
59+
return new DropAllSILPass();
60+
}

0 commit comments

Comments
 (0)