Files
swift-mirror/lib/DriverTool/modulewrap_main.cpp
Nate Chandler e9e93c1590 [Opaque Values] Address-lower TypeLowerings.
When opaque values are enabled, TypeConverter associates to an
address-only type an OpaqueValueTypeLowering.  That lowering stores a
single lowered SIL type, and its value category is "object".  So long as
the module has not yet been address-lowered, that type has the
appropriate value category.  After the module has been address-lowered,
however, that type has the wrong value category: the type is
address-only, and in an address-lowered module, its lowered type's value
category must be "address".

Code that obtains a lowered type expects the value category to reflect
the state of the module.  So somewhere, it's necessary to fixup that
single lowered type's value category.

One option would be to update all code that uses lowered types.  That
would require many changes across the codebase and all new code that
used lowered types would need to account for this.

Another option would be to update some popular conveniences that call
through to TypeConverter, for example those on SILFunction, and ensure
that all code used those conveniences.  Even if this were done
completely, it would be easy enough for new code to be added which
didn't use the conveniences.

A third option would be to update TypeLowering::getLoweredType to take
in the context necessary to determine whether the stored SILType should
be fixed up.  That would require each callsite to be changed and
potentially to carry around more context than it already had in order to
be able to pass it along.

A fourth option would be to make TypeConverter aware of the
address-loweredness, and to update its state at the end of
AddressLowering.

Updating TypeConverter's state would entail updating all cached
OpaqueValueTypeLowering instances at the end of the AddressLowering
pass.  Additionally, when TypeConverter produces new
OpaqueValueTypeLowerings, they would need to have the "address" value
category from creation.

Of all the options, the last is least invasive and least error-prone, so
it is taken here.
2022-12-01 14:18:17 -08:00

199 lines
7.0 KiB
C++

//===--- modulewrap_main.cpp - module wrapping utility --------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Wraps .swiftmodule files inside an object file container so they
// can be passed to the linker directly. Mostly useful for platforms
// where the debug info typically stays in the executable.
// (ie. ELF-based platforms).
//
//===----------------------------------------------------------------------===//
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Frontend/Frontend.h"
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
#include "swift/Option/Options.h"
#include "swift/Serialization/Validation.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/TypeLowering.h"
#include "swift/Subsystems.h"
#include "swift/SymbolGraphGen/SymbolGraphOptions.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Bitstream/BitstreamReader.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TargetSelect.h"
using namespace llvm::opt;
using namespace swift;
class ModuleWrapInvocation {
private:
std::string MainExecutablePath;
std::string OutputFilename = "-";
llvm::Triple TargetTriple;
std::vector<std::string> InputFilenames;
bool UseSharedResourceFolder = true;
public:
bool hasSingleInput() const { return InputFilenames.size() == 1; }
const std::string &getFilenameOfFirstInput() const {
return InputFilenames[0];
}
void setMainExecutablePath(const std::string &Path) {
MainExecutablePath = Path;
}
const std::string &getOutputFilename() { return OutputFilename; }
const std::vector<std::string> &getInputFilenames() { return InputFilenames; }
llvm::Triple &getTargetTriple() { return TargetTriple; }
bool useSharedResourceFolder() { return UseSharedResourceFolder; }
int parseArgs(llvm::ArrayRef<const char *> Args, DiagnosticEngine &Diags) {
using namespace options;
// Parse frontend command line options using Swift's option table.
std::unique_ptr<llvm::opt::OptTable> Table = createSwiftOptTable();
unsigned MissingIndex;
unsigned MissingCount;
llvm::opt::InputArgList ParsedArgs =
Table->ParseArgs(Args, MissingIndex, MissingCount,
ModuleWrapOption);
if (MissingCount) {
Diags.diagnose(SourceLoc(), diag::error_missing_arg_value,
ParsedArgs.getArgString(MissingIndex), MissingCount);
return 1;
}
if (const Arg *A = ParsedArgs.getLastArg(options::OPT_target))
TargetTriple = llvm::Triple(llvm::Triple::normalize(A->getValue()));
else
TargetTriple = llvm::Triple(llvm::sys::getDefaultTargetTriple());
if (ParsedArgs.hasArg(OPT_UNKNOWN)) {
for (const Arg *A : ParsedArgs.filtered(OPT_UNKNOWN)) {
Diags.diagnose(SourceLoc(), diag::error_unknown_arg,
A->getAsString(ParsedArgs));
}
return true;
}
if (ParsedArgs.getLastArg(OPT_help)) {
std::string ExecutableName =
llvm::sys::path::stem(MainExecutablePath).str();
Table->printHelp(llvm::outs(), ExecutableName.c_str(),
"Swift Module Wrapper", options::ModuleWrapOption, 0,
/*ShowAllAliases*/false);
return 1;
}
for (const Arg *A : ParsedArgs.filtered(OPT_INPUT)) {
InputFilenames.push_back(A->getValue());
}
if (InputFilenames.empty()) {
Diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
return 1;
}
if (const Arg *A = ParsedArgs.getLastArg(OPT_o)) {
OutputFilename = A->getValue();
}
if (ParsedArgs.hasFlag(OPT_static_executable, OPT_no_static_executable,
false) ||
ParsedArgs.hasFlag(OPT_static_stdlib, OPT_no_static_stdlib, false) ||
ParsedArgs.hasArg(OPT_static)) {
UseSharedResourceFolder = false;
}
return 0;
}
};
int modulewrap_main(ArrayRef<const char *> Args, const char *Argv0,
void *MainAddr) {
INITIALIZE_LLVM();
CompilerInstance Instance;
PrintingDiagnosticConsumer PDC;
Instance.addDiagnosticConsumer(&PDC);
ModuleWrapInvocation Invocation;
std::string MainExecutablePath =
llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
Invocation.setMainExecutablePath(MainExecutablePath);
// Parse arguments.
if (Invocation.parseArgs(Args, Instance.getDiags()) != 0) {
return 1;
}
if (!Invocation.hasSingleInput()) {
Instance.getDiags().diagnose(SourceLoc(),
diag::error_mode_requires_one_input_file);
return 1;
}
StringRef Filename = Invocation.getFilenameOfFirstInput();
auto ErrOrBuf = llvm::MemoryBuffer::getFile(Filename);
if (!ErrOrBuf) {
Instance.getDiags().diagnose(
SourceLoc(), diag::error_no_such_file_or_directory, Filename);
return 1;
}
// Superficially verify that the input is a swift module file.
if (!serialization::isSerializedAST(ErrOrBuf.get()->getBuffer())) {
Instance.getDiags().diagnose(SourceLoc(), diag::error_parse_input_file,
Filename, "signature mismatch");
return 1;
}
// Wrap the bitstream in a module object file. To use the ClangImporter to
// create the module loader, we need to properly set the runtime library path.
SearchPathOptions SearchPathOpts;
SmallString<128> RuntimeResourcePath;
CompilerInvocation::computeRuntimeResourcePathFromExecutablePath(
MainExecutablePath, Invocation.useSharedResourceFolder(),
RuntimeResourcePath);
SearchPathOpts.RuntimeResourcePath = std::string(RuntimeResourcePath.str());
SourceManager SrcMgr;
SILOptions SILOpts;
TypeCheckerOptions TypeCheckOpts;
LangOptions LangOpts;
ClangImporterOptions ClangImporterOpts;
symbolgraphgen::SymbolGraphOptions SymbolGraphOpts;
LangOpts.Target = Invocation.getTargetTriple();
ASTContext &ASTCtx = *ASTContext::get(
LangOpts, TypeCheckOpts, SILOpts, SearchPathOpts, ClangImporterOpts,
SymbolGraphOpts, SrcMgr, Instance.getDiags());
registerParseRequestFunctions(ASTCtx.evaluator);
registerTypeCheckerRequestFunctions(ASTCtx.evaluator);
ASTCtx.addModuleLoader(ClangImporter::create(ASTCtx, ""), true);
ModuleDecl *M = ModuleDecl::create(ASTCtx.getIdentifier("swiftmodule"), ASTCtx);
std::unique_ptr<Lowering::TypeConverter> TC(
new Lowering::TypeConverter(*M, ASTCtx.SILOpts.EnableSILOpaqueValues));
std::unique_ptr<SILModule> SM = SILModule::createEmptyModule(M, *TC, SILOpts);
createSwiftModuleObjectFile(*SM, (*ErrOrBuf)->getBuffer(),
Invocation.getOutputFilename());
return 0;
}