Skip to content
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
252 changes: 233 additions & 19 deletions lib/DriverTool/sil_llvm_gen_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "swift/AST/SILOptions.h"
#include "swift/Basic/Assertions.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Basic/QuotedString.h"
#include "swift/Frontend/DiagnosticVerifier.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
Expand Down Expand Up @@ -49,6 +50,29 @@
#include <cstdio>
using namespace swift;

namespace {
enum class SILOptStrictConcurrency {
None = 0,
Complete,
Targeted,
Minimal,
};
}

static std::optional<StrictConcurrency>
convertSILOptToRawStrictConcurrencyLevel(SILOptStrictConcurrency level) {
switch (level) {
case SILOptStrictConcurrency::None:
return {};
case SILOptStrictConcurrency::Complete:
return StrictConcurrency::Complete;
case SILOptStrictConcurrency::Targeted:
return StrictConcurrency::Targeted;
case SILOptStrictConcurrency::Minimal:
return StrictConcurrency::Minimal;
}
}

struct SILLLVMGenOptions {
llvm::cl::opt<std::string>
InputFilename = llvm::cl::opt<std::string>(llvm::cl::desc("input file"),
Expand All @@ -66,12 +90,29 @@ struct SILLLVMGenOptions {
FrameworkPaths = llvm::cl::list<std::string>(
"F", llvm::cl::desc("add a directory to the framework search path"));

llvm::cl::list<std::string> VFSOverlays = llvm::cl::list<std::string>(
"vfsoverlay", llvm::cl::desc("add a VFS overlay"));

llvm::cl::opt<std::string>
ModuleName = llvm::cl::opt<std::string>("module-name",
llvm::cl::desc("The name of the module if processing"
" a module. Necessary for processing "
"stdin."));

llvm::cl::opt<bool> StrictImplicitModuleContext = llvm::cl::opt<bool>(
"strict-implicit-module-context",
llvm::cl::desc("Enable the strict forwarding of compilation "
"context to downstream implicit module dependencies"));

llvm::cl::opt<bool> DisableImplicitModules =
llvm::cl::opt<bool>("disable-implicit-swift-modules",
llvm::cl::desc("Disable implicit swift modules."));

llvm::cl::opt<std::string> ExplicitSwiftModuleMapPath =
llvm::cl::opt<std::string>(
"explicit-swift-module-map-file",
llvm::cl::desc("Explict swift module map file path"));

llvm::cl::opt<std::string>
ResourceDir = llvm::cl::opt<std::string>(
"resource-dir",
Expand All @@ -96,27 +137,94 @@ struct SILLLVMGenOptions {
llvm::cl::opt<bool>
PerformWMO = llvm::cl::opt<bool>("wmo", llvm::cl::desc("Enable whole-module optimizations"));

llvm::cl::opt<IRGenOutputKind>
OutputKind = llvm::cl::opt<IRGenOutputKind>(
llvm::cl::opt<IRGenOutputKind> OutputKind = llvm::cl::opt<IRGenOutputKind>(
"output-kind", llvm::cl::desc("Type of output to produce"),
llvm::cl::values(clEnumValN(IRGenOutputKind::LLVMAssemblyAfterOptimization,
"llvm-as", "Emit llvm assembly"),
clEnumValN(IRGenOutputKind::LLVMBitcode, "llvm-bc",
"Emit llvm bitcode"),
clEnumValN(IRGenOutputKind::NativeAssembly, "as",
"Emit native assembly"),
clEnumValN(IRGenOutputKind::ObjectFile, "object",
"Emit an object file")),
llvm::cl::values(
clEnumValN(IRGenOutputKind::LLVMAssemblyBeforeOptimization, "llvm-as",
"Emit llvm assembly before optimization"),
clEnumValN(IRGenOutputKind::LLVMAssemblyAfterOptimization,
"llvm-as-opt", "Emit llvm assembly after optimization"),
clEnumValN(IRGenOutputKind::LLVMBitcode, "llvm-bc",
"Emit llvm bitcode"),
clEnumValN(IRGenOutputKind::NativeAssembly, "as",
"Emit native assembly"),
clEnumValN(IRGenOutputKind::ObjectFile, "object",
"Emit an object file")),
llvm::cl::init(IRGenOutputKind::ObjectFile));

llvm::cl::opt<bool>
DisableLegacyTypeInfo = llvm::cl::opt<bool>("disable-legacy-type-info",
llvm::cl::desc("Don't try to load backward deployment layouts"));

llvm::cl::opt<std::string> SwiftVersionString = llvm::cl::opt<std::string>(
"swift-version",
llvm::cl::desc(
"The swift version to assume AST declarations correspond to"));

llvm::cl::opt<bool> EnableExperimentalConcurrency = llvm::cl::opt<bool>(
"enable-experimental-concurrency",
llvm::cl::desc("Enable experimental concurrency model."));

llvm::cl::opt<llvm::cl::boolOrDefault> EnableExperimentalMoveOnly =
llvm::cl::opt<llvm::cl::boolOrDefault>(
"enable-experimental-move-only", llvm::cl::init(llvm::cl::BOU_UNSET),
llvm::cl::desc("Enable experimental move-only semantics."));

llvm::cl::list<std::string> ExperimentalFeatures =
llvm::cl::list<std::string>(
"enable-experimental-feature",
llvm::cl::desc("Enable the given experimental feature."));

llvm::cl::list<std::string> UpcomingFeatures = llvm::cl::list<std::string>(
"enable-upcoming-feature",
llvm::cl::desc("Enable the given upcoming feature."));

llvm::cl::opt<bool> EnableCxxInterop = llvm::cl::opt<bool>(
"enable-experimental-cxx-interop", llvm::cl::desc("Enable C++ interop."),
llvm::cl::init(false));

llvm::cl::opt<bool> EnableObjCInterop = llvm::cl::opt<bool>(
"enable-objc-interop",
llvm::cl::desc("Enable Objective-C interoperability."));

llvm::cl::opt<bool> DisableObjCInterop = llvm::cl::opt<bool>(
"disable-objc-interop",
llvm::cl::desc("Disable Objective-C interoperability."));

// Strict Concurrency
llvm::cl::opt<SILOptStrictConcurrency> StrictConcurrencyLevel =
llvm::cl::opt<SILOptStrictConcurrency>(
"strict-concurrency", llvm::cl::desc("strict concurrency level"),
llvm::cl::init(SILOptStrictConcurrency::None),
llvm::cl::values(
clEnumValN(SILOptStrictConcurrency::Complete, "complete",
"Enable complete strict concurrency"),
clEnumValN(SILOptStrictConcurrency::Targeted, "targeted",
"Enable targeted strict concurrency"),
clEnumValN(SILOptStrictConcurrency::Minimal, "minimal",
"Enable minimal strict concurrency"),
clEnumValN(SILOptStrictConcurrency::None, "disabled",
"Strict concurrency disabled")));
};

static std::optional<bool> toOptionalBool(llvm::cl::boolOrDefault defaultable) {
switch (defaultable) {
case llvm::cl::BOU_TRUE:
return true;
case llvm::cl::BOU_FALSE:
return false;
case llvm::cl::BOU_UNSET:
return std::nullopt;
}
llvm_unreachable("Bad case for llvm::cl::boolOrDefault!");
}

int sil_llvm_gen_main(ArrayRef<const char *> argv, void *MainAddr) {
INITIALIZE_LLVM();

llvm::setBugReportMsg(SWIFT_CRASH_BUG_REPORT_MESSAGE "\n");
llvm::EnablePrettyStackTraceOnSigInfoForThisThread();

SILLLVMGenOptions options;

llvm::cl::ParseCommandLineOptions(argv.size(), argv.data(), "Swift LLVM IR Generator\n");
Expand All @@ -139,6 +247,9 @@ int sil_llvm_gen_main(ArrayRef<const char *> argv, void *MainAddr) {
FramePaths.push_back({path, /*isSystem=*/false});
}
Invocation.setFrameworkSearchPaths(FramePaths);

Invocation.setVFSOverlays(options.VFSOverlays);

// Set the SDK path and target if given.
if (options.SDKPath.getNumOccurrences() == 0) {
const char *SDKROOT = getenv("SDKROOT");
Expand All @@ -151,17 +262,110 @@ int sil_llvm_gen_main(ArrayRef<const char *> argv, void *MainAddr) {
Invocation.setTargetTriple(options.Target);
if (!options.ResourceDir.empty())
Invocation.setRuntimeResourcePath(options.ResourceDir);

Invocation.getFrontendOptions().StrictImplicitModuleContext =
options.StrictImplicitModuleContext;

Invocation.getFrontendOptions().DisableImplicitModules =
options.DisableImplicitModules;
Invocation.getSearchPathOptions().ExplicitSwiftModuleMapPath =
options.ExplicitSwiftModuleMapPath;

// Set the module cache path. If not passed in we use the default swift module
// cache.
Invocation.getClangImporterOptions().ModuleCachePath = options.ModuleCachePath;
Invocation.setParseStdlib();

// Setup the language options
auto &LangOpts = Invocation.getLangOptions();
LangOpts.DisableAvailabilityChecking = true;
LangOpts.EnableAccessControl = false;
LangOpts.EnableObjCAttrRequiresFoundation = false;
LangOpts.EnableObjCInterop = LangOpts.Target.isOSDarwin();
if (options.SwiftVersionString.size()) {
auto vers = VersionParser::parseVersionString(options.SwiftVersionString,
SourceLoc(), nullptr);
bool isValid = false;
if (vers.has_value()) {
if (auto effectiveVers = vers.value().getEffectiveLanguageVersion()) {
Invocation.getLangOptions().EffectiveLanguageVersion =
effectiveVers.value();
isValid = true;
}
}
if (!isValid) {
llvm::errs() << "error: invalid swift version "
<< options.SwiftVersionString << '\n';
exit(-1);
}
}
Invocation.getLangOptions().DisableAvailabilityChecking = true;
Invocation.getLangOptions().EnableAccessControl = false;
Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
Invocation.getLangOptions().EnableDeserializationSafety = false;
Invocation.getLangOptions().EnableExperimentalConcurrency =
options.EnableExperimentalConcurrency;
std::optional<bool> enableExperimentalMoveOnly =
toOptionalBool(options.EnableExperimentalMoveOnly);
if (enableExperimentalMoveOnly && *enableExperimentalMoveOnly) {
// FIXME: drop addition of Feature::MoveOnly once its queries are gone.
Invocation.getLangOptions().enableFeature(Feature::MoveOnly);
Invocation.getLangOptions().enableFeature(Feature::NoImplicitCopy);
Invocation.getLangOptions().enableFeature(
Feature::OldOwnershipOperatorSpellings);
}

for (auto &featureName : options.UpcomingFeatures) {
auto feature = Feature::getUpcomingFeature(featureName);
if (!feature) {
llvm::errs() << "error: unknown upcoming feature "
<< QuotedString(featureName) << "\n";
exit(-1);
}

if (auto firstVersion = feature->getLanguageVersion()) {
if (Invocation.getLangOptions().isSwiftVersionAtLeast(*firstVersion)) {
llvm::errs() << "error: upcoming feature " << QuotedString(featureName)
<< " is already enabled as of Swift version "
<< *firstVersion << '\n';
exit(-1);
}
}
Invocation.getLangOptions().enableFeature(*feature);
}

for (auto &featureName : options.ExperimentalFeatures) {
if (auto feature = Feature::getExperimentalFeature(featureName)) {
Invocation.getLangOptions().enableFeature(*feature);
} else {
llvm::errs() << "error: unknown experimental feature "
<< QuotedString(featureName) << "\n";
exit(-1);
}
}

// Enable strict concurrency if we have the feature specified or if it was
// specified via a command line option to sil-opt.
if (Invocation.getLangOptions().hasFeature(Feature::StrictConcurrency)) {
Invocation.getLangOptions().StrictConcurrencyLevel =
StrictConcurrency::Complete;
} else if (auto level = convertSILOptToRawStrictConcurrencyLevel(
options.StrictConcurrencyLevel)) {
// If strict concurrency was enabled from the cmdline so the feature flag as
// well.
if (*level == StrictConcurrency::Complete)
Invocation.getLangOptions().enableFeature(Feature::StrictConcurrency);
Invocation.getLangOptions().StrictConcurrencyLevel = *level;
}

// If we have strict concurrency set as a feature and were told to turn off
// region-based isolation... do so now.
if (Invocation.getLangOptions().hasFeature(Feature::StrictConcurrency)) {
Invocation.getLangOptions().enableFeature(Feature::RegionBasedIsolation);
}

Invocation.getLangOptions().EnableObjCInterop =
options.EnableObjCInterop ? true
: options.DisableObjCInterop ? false
: llvm::Triple(options.Target).isOSDarwin();

Invocation.getLangOptions().EnableCXXInterop = options.EnableCxxInterop;
Invocation.computeCXXStdlibOptions();

// Setup the IRGen Options.
IRGenOptions &Opts = Invocation.getIRGenOptions();
Expand Down Expand Up @@ -216,16 +420,26 @@ int sil_llvm_gen_main(ArrayRef<const char *> argv, void *MainAddr) {
return IRGenDescriptor::forWholeModule(
mod, Opts, TBDOpts, SILOpts, SILTypes,
/*SILMod*/ nullptr, moduleName, PSPs);
} else {
return IRGenDescriptor::forFile(
mod->getFiles()[0], Opts, TBDOpts, SILOpts, SILTypes,
/*SILMod*/ nullptr, moduleName, PSPs, /*discriminator*/ "");
}

return IRGenDescriptor::forFile(
mod->getFiles()[0], Opts, TBDOpts, SILOpts, SILTypes,
/*SILMod*/ nullptr, moduleName, PSPs, /*discriminator*/ "");
};

auto &eval = CI.getASTContext().evaluator;
auto desc = getDescriptor();
desc.out = &outFile->getOS();

if (options.OutputKind == IRGenOutputKind::LLVMAssemblyBeforeOptimization) {
auto generatedMod = evaluateOrFatal(eval, IRGenRequest{desc});
if (!generatedMod)
return 1;

generatedMod.getModule()->print(*outFile, nullptr);
return 0;
}

auto generatedMod = evaluateOrFatal(eval, OptimizedIRRequest{desc});
if (!generatedMod)
return 1;
Expand Down
14 changes: 7 additions & 7 deletions test/sil-llvm-gen/alloc.sil
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as -target x86_64-apple-macosx10.9 -module-name main %s -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as -target i386-apple-ios7.0 %s -module-name main -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as -target x86_64-apple-ios7.0 %s -module-name main -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as -target armv7-apple-ios7.0 %s -module-name main -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as -target arm64-apple-ios7.0 %s -module-name main -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as -target x86_64-unknown-linux-gnu %s -module-name main -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as-opt -target x86_64-apple-macosx10.9 -module-name main %s -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as-opt -target i386-apple-ios7.0 %s -module-name main -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as-opt -target x86_64-apple-ios7.0 %s -module-name main -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as-opt -target armv7-apple-ios7.0 %s -module-name main -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as-opt -target arm64-apple-ios7.0 %s -module-name main -o - | %FileCheck %s
// RUN: %sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as-opt -target x86_64-unknown-linux-gnu %s -module-name main -o - | %FileCheck %s

// Use this testfile to check if the `swift-frontend -sil-llvm-gen` option works.
// RUN: %swift_frontend_plain -sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as -target x86_64-apple-macosx10.9 -module-name main %s -o - | %FileCheck %s
// RUN: %swift_frontend_plain -sil-llvm-gen -disable-legacy-type-info -output-kind=llvm-as-opt -target x86_64-apple-macosx10.9 -module-name main %s -o - | %FileCheck %s

// REQUIRES: CODEGENERATOR=X86
// REQUIRES: CODEGENERATOR=ARM
Expand Down