Skip to content

Commit

Permalink
[frontend] Introduce a new frontend option '-dump-api-path', which ou…
Browse files Browse the repository at this point in the history
…tputs a swift interface file for each compiled source file.

This is primarily intended for use with the stdlib.
  • Loading branch information
akyrtzi committed Dec 3, 2015
1 parent 717b017 commit 8d9ef80
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 1 deletion.
3 changes: 3 additions & 0 deletions include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ class FrontendOptions {
/// should only be used for debugging and experimental features.
std::vector<std::string> LLVMArgs;

/// The path to output swift interface files for the compiled source files.
std::string DumpAPIPath;

enum ActionType {
NoneAction, ///< No specific action
Parse, ///< Parse and type-check only
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,9 @@ def dump_interface_hash : Flag<["-"], "dump-interface-hash">,
HelpText<"Parse input file(s) and dump interface token hash(es)">,
ModeOpt;

def dump_api_path : Separate<["-"], "dump-api-path">,
HelpText<"The path to output swift interface files for the compiled source files">;

def enable_resilience : Flag<["-"], "enable-resilience">,
HelpText<"Treat all types as resilient by default">;

Expand Down
8 changes: 7 additions & 1 deletion lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,8 @@ bool Decl::isPrivateStdlibDecl(bool whitelistProtocols) const {
if (!FU)
return false;
// Check for Swift module and overlays.
if (FU->getKind() != FileUnitKind::SerializedAST)
if (!DC->getParentModule()->isStdlibModule() &&
FU->getKind() != FileUnitKind::SerializedAST)
return false;

auto hasInternalParameter = [](ArrayRef<const Pattern *> Pats) -> bool {
Expand Down Expand Up @@ -436,6 +437,11 @@ bool Decl::isPrivateStdlibDecl(bool whitelistProtocols) const {
return false;
}

if (auto ImportD = dyn_cast<ImportDecl>(D)) {
if (ImportD->getModule()->isSwiftShimsModule())
return true;
}

auto VD = dyn_cast<ValueDecl>(D);
if (!VD || !VD->hasName())
return false;
Expand Down
6 changes: 6 additions & 0 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
}
}

if (const Arg *A = Args.getLastArg(OPT_dump_api_path)) {
Opts.DumpAPIPath = A->getValue();
}

Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);
Opts.EmitSortedSIL |= Args.hasArg(OPT_emit_sorted_sil);

Expand Down Expand Up @@ -650,6 +654,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
DiagnosticEngine &Diags, bool isImmediate) {
using namespace options;

Opts.AttachCommentsToDecls |= Args.hasArg(OPT_dump_api_path);

Opts.UseMalloc |= Args.hasArg(OPT_use_malloc);

Opts.EnableExperimentalPatterns |=
Expand Down
68 changes: 68 additions & 0 deletions tools/driver/frontend_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "llvm/Support/YAMLParser.h"

#include <memory>
#include <unordered_set>

using namespace swift;

Expand Down Expand Up @@ -921,6 +922,68 @@ static bool performCompile(CompilerInstance &Instance,
return false;
}

/// Returns true if an error occurred.
static bool dumpAPI(Module *Mod, StringRef OutDir) {
using namespace llvm::sys;

auto getOutPath = [&](SourceFile *SF) -> std::string {
SmallString<256> Path = OutDir;
StringRef Filename = SF->getFilename();
path::append(Path, path::filename(Filename));
return Path.str();
};

std::unordered_set<std::string> Filenames;

auto dumpFile = [&](SourceFile *SF) -> bool {
SmallString<512> TempBuf;
llvm::raw_svector_ostream TempOS(TempBuf);

PrintOptions PO = PrintOptions::printInterface();
PO.PrintOriginalSourceText = true;
PO.Indent = 2;
PO.PrintAccessibility = false;
PO.SkipUnderscoredStdlibProtocols = true;
SF->print(TempOS, PO);
if (TempOS.str().trim().empty())
return false; // nothing to show.

std::string OutPath = getOutPath(SF);
bool WasInserted = Filenames.insert(OutPath).second;
if (!WasInserted) {
llvm::errs() << "multiple source files ended up with the same dump API "
"filename to write to: " << OutPath << '\n';
return true;
}

std::error_code EC;
llvm::raw_fd_ostream OS(OutPath, EC, fs::OpenFlags::F_RW);
if (EC) {
llvm::errs() << "error opening file '" << OutPath << "': "
<< EC.message() << '\n';
return true;
}

OS << TempOS.str();
return false;
};

std::error_code EC = fs::create_directories(OutDir);
if (EC) {
llvm::errs() << "error creating directory '" << OutDir << "': "
<< EC.message() << '\n';
return true;
}

for (auto *FU : Mod->getFiles()) {
if (SourceFile *SF = dyn_cast<SourceFile>(FU))
if (dumpFile(SF))
return true;
}

return false;
}

int frontend_main(ArrayRef<const char *>Args,
const char *Argv0, void *MainAddr) {
llvm::InitializeAllTargets();
Expand Down Expand Up @@ -1045,6 +1108,11 @@ int frontend_main(ArrayRef<const char *>Args,
bool HadError = performCompile(Instance, Invocation, Args, ReturnValue) ||
Instance.getASTContext().hadError();

if (!HadError && !Invocation.getFrontendOptions().DumpAPIPath.empty()) {
HadError = dumpAPI(Instance.getMainModule(),
Invocation.getFrontendOptions().DumpAPIPath);
}

if (Invocation.getDiagnosticOptions().VerifyDiagnostics) {
HadError = verifyDiagnostics(Instance.getSourceMgr(),
Instance.getInputBufferIDs());
Expand Down

0 comments on commit 8d9ef80

Please sign in to comment.