|
55 | 55 | #include "llvm/Support/YAMLParser.h"
|
56 | 56 |
|
57 | 57 | #include <memory>
|
| 58 | +#include <unordered_set> |
58 | 59 |
|
59 | 60 | using namespace swift;
|
60 | 61 |
|
@@ -921,6 +922,68 @@ static bool performCompile(CompilerInstance &Instance,
|
921 | 922 | return false;
|
922 | 923 | }
|
923 | 924 |
|
| 925 | +/// Returns true if an error occurred. |
| 926 | +static bool dumpAPI(Module *Mod, StringRef OutDir) { |
| 927 | + using namespace llvm::sys; |
| 928 | + |
| 929 | + auto getOutPath = [&](SourceFile *SF) -> std::string { |
| 930 | + SmallString<256> Path = OutDir; |
| 931 | + StringRef Filename = SF->getFilename(); |
| 932 | + path::append(Path, path::filename(Filename)); |
| 933 | + return Path.str(); |
| 934 | + }; |
| 935 | + |
| 936 | + std::unordered_set<std::string> Filenames; |
| 937 | + |
| 938 | + auto dumpFile = [&](SourceFile *SF) -> bool { |
| 939 | + SmallString<512> TempBuf; |
| 940 | + llvm::raw_svector_ostream TempOS(TempBuf); |
| 941 | + |
| 942 | + PrintOptions PO = PrintOptions::printInterface(); |
| 943 | + PO.PrintOriginalSourceText = true; |
| 944 | + PO.Indent = 2; |
| 945 | + PO.PrintAccessibility = false; |
| 946 | + PO.SkipUnderscoredStdlibProtocols = true; |
| 947 | + SF->print(TempOS, PO); |
| 948 | + if (TempOS.str().trim().empty()) |
| 949 | + return false; // nothing to show. |
| 950 | + |
| 951 | + std::string OutPath = getOutPath(SF); |
| 952 | + bool WasInserted = Filenames.insert(OutPath).second; |
| 953 | + if (!WasInserted) { |
| 954 | + llvm::errs() << "multiple source files ended up with the same dump API " |
| 955 | + "filename to write to: " << OutPath << '\n'; |
| 956 | + return true; |
| 957 | + } |
| 958 | + |
| 959 | + std::error_code EC; |
| 960 | + llvm::raw_fd_ostream OS(OutPath, EC, fs::OpenFlags::F_RW); |
| 961 | + if (EC) { |
| 962 | + llvm::errs() << "error opening file '" << OutPath << "': " |
| 963 | + << EC.message() << '\n'; |
| 964 | + return true; |
| 965 | + } |
| 966 | + |
| 967 | + OS << TempOS.str(); |
| 968 | + return false; |
| 969 | + }; |
| 970 | + |
| 971 | + std::error_code EC = fs::create_directories(OutDir); |
| 972 | + if (EC) { |
| 973 | + llvm::errs() << "error creating directory '" << OutDir << "': " |
| 974 | + << EC.message() << '\n'; |
| 975 | + return true; |
| 976 | + } |
| 977 | + |
| 978 | + for (auto *FU : Mod->getFiles()) { |
| 979 | + if (SourceFile *SF = dyn_cast<SourceFile>(FU)) |
| 980 | + if (dumpFile(SF)) |
| 981 | + return true; |
| 982 | + } |
| 983 | + |
| 984 | + return false; |
| 985 | +} |
| 986 | + |
924 | 987 | int frontend_main(ArrayRef<const char *>Args,
|
925 | 988 | const char *Argv0, void *MainAddr) {
|
926 | 989 | llvm::InitializeAllTargets();
|
@@ -1045,6 +1108,11 @@ int frontend_main(ArrayRef<const char *>Args,
|
1045 | 1108 | bool HadError = performCompile(Instance, Invocation, Args, ReturnValue) ||
|
1046 | 1109 | Instance.getASTContext().hadError();
|
1047 | 1110 |
|
| 1111 | + if (!HadError && !Invocation.getFrontendOptions().DumpAPIPath.empty()) { |
| 1112 | + HadError = dumpAPI(Instance.getMainModule(), |
| 1113 | + Invocation.getFrontendOptions().DumpAPIPath); |
| 1114 | + } |
| 1115 | + |
1048 | 1116 | if (Invocation.getDiagnosticOptions().VerifyDiagnostics) {
|
1049 | 1117 | HadError = verifyDiagnostics(Instance.getSourceMgr(),
|
1050 | 1118 | Instance.getInputBufferIDs());
|
|
0 commit comments