Skip to content

[embedded] Add a frontend flag to drop all code from a module and emit an empty object file #72669

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,10 @@ def enable_single_module_llvm_emission: Flag<["-"], "enable-single-module-llvm-e
Flags<[FrontendOption, NoInteractiveOption]>,
HelpText<"Emit LLVM IR into a single LLVM module in multithreaded mode.">;

def emit_empty_object_file : Flag<["-"], "emit-empty-object-file">,
Flags<[FrontendOption, NoInteractiveOption]>,
HelpText<"Produce a valid but dummy object file when building a library module">;

def stack_promotion_checks : Flag<["-"], "emit-stack-promotion-checks">,
HelpText<"Emit runtime checks for correct stack promotion of objects.">;

Expand Down
4 changes: 4 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2185,6 +2185,10 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
FEOpts.RequestedAction == FrontendOptions::ActionType::CompileModuleFromInterface)
Opts.StopOptimizationAfterSerialization = true;

if (Args.getLastArg(OPT_emit_empty_object_file)) {
Opts.StopOptimizationAfterSerialization = true;
}

// Propagate the typechecker's understanding of
// -experimental-skip-*-function-bodies to SIL.
Opts.SkipFunctionBodies = TCOpts.SkipFunctionBodies;
Expand Down
15 changes: 15 additions & 0 deletions lib/IRGen/GenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,11 @@ class PrettySynthesizedFileUnitEmission : public llvm::PrettyStackTraceEntry {

/// Emit all the top-level code in the source file.
void IRGenModule::emitSourceFile(SourceFile &SF) {
if (getSILModule().getOptions().StopOptimizationAfterSerialization) {
// We're asked to emit an empty IR module
return;
}

// Type-check the file if we haven't already (this may be necessary for .sil
// files, which don't get fully type-checked by parsing).
performTypeChecking(SF);
Expand Down Expand Up @@ -1259,6 +1264,11 @@ static bool isLazilyEmittedFunction(SILFunction &f, SILModule &m) {

void IRGenerator::emitGlobalTopLevel(
const std::vector<std::string> &linkerDirectives) {
if (PrimaryIGM->getSILModule().getOptions().StopOptimizationAfterSerialization) {
// We're asked to emit an empty IR module
return;
}

// Generate order numbers for the functions in the SIL module that
// correspond to definitions in the LLVM module.
unsigned nextOrderNumber = 0;
Expand Down Expand Up @@ -2195,6 +2205,11 @@ void IRGenerator::emitObjCActorsNeedingSuperclassSwizzle() {
/// from other modules. This happens e.g. if a public class contains a (dead)
/// private method.
void IRGenModule::emitVTableStubs() {
if (getSILModule().getOptions().StopOptimizationAfterSerialization) {
// We're asked to emit an empty IR module
return;
}

llvm::Function *stub = nullptr;
for (auto I = getSILModule().zombies_begin();
I != getSILModule().zombies_end(); ++I) {
Expand Down
5 changes: 5 additions & 0 deletions lib/IRGen/GenReflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1667,6 +1667,11 @@ llvm::ArrayRef<CanType> IRGenModule::getOrCreateSpecialStlibBuiltinTypes() {
}

void IRGenModule::emitBuiltinReflectionMetadata() {
if (getSILModule().getOptions().StopOptimizationAfterSerialization) {
// We're asked to emit an empty IR module
return;
}

if (getSwiftModule()->isStdlibModule()) {
auto SpecialBuiltins = getOrCreateSpecialStlibBuiltinTypes();
BuiltinTypes.insert(SpecialBuiltins.begin(), SpecialBuiltins.end());
Expand Down
11 changes: 10 additions & 1 deletion lib/IRGen/IRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1912,7 +1912,8 @@ void IRGenModule::cleanupClangCodeGenMetadata() {
bool IRGenModule::finalize() {
const char *ModuleHashVarName = "llvm.swift_module_hash";
if (IRGen.Opts.OutputKind == IRGenOutputKind::ObjectFile &&
!Module.getGlobalVariable(ModuleHashVarName)) {
!Module.getGlobalVariable(ModuleHashVarName) &&
!getSILModule().getOptions().StopOptimizationAfterSerialization) {
// Create a global variable into which we will store the hash of the
// module (used for incremental compilation).
// We have to create the variable now (before we emit the global lists).
Expand Down Expand Up @@ -1969,6 +1970,14 @@ bool IRGenModule::finalize() {
if (F.hasDLLImportStorageClass())
F.setDSOLocal(false);

if (getSILModule().getOptions().StopOptimizationAfterSerialization) {
// We're asked to emit an empty IR module, check that that's actually true
if (Module.global_size() != 0 || Module.size() != 0) {
Module.dump();
llvm::report_fatal_error("Module is not empty");
}
}

return true;
}

Expand Down