/// HSAILTargetMachine ctor - /// HSAILTargetMachine::HSAILTargetMachine(const Target &T, StringRef TT, StringRef CPU, StringRef FS,const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,CodeGenOpt::Level OL, bool is64bitTarget ) : LLVMTargetMachine(T, TT, CPU, FS,Options, RM, CM,OL), Subtarget(TT, CPU, FS, is64bitTarget), // DLInfo(Subtarget.getDataLayout()), FrameLowering(TargetFrameLowering::StackGrowsUp, Subtarget.getStackAlignment(), 0), // InstrInfo(*this), // TLInfo(*this), IntrinsicInfo(this) { if (FileType == CGFT_AssemblyFile) { if (FileType.getNumOccurrences() == 0) { // LLVM's default is CGFT_AssemblyFile. HSAIL default is binary BRIG, // thus we need to change output to CGFT_AssemblyFile, unless text // assembly was explicitly requested by the command line switch. HSAILFileType = FileType = CGFT_ObjectFile; } } setAsmVerbosityDefault(true); // disable use of the .loc directive, because only by // setting this to false does DwarfDebug generate the .debug_line // section // setMCUseLoc(false); }
CompilationDatabase *autoDetectCompilations(std::string &ErrorMessage) { // Auto-detect a compilation database from BuildPath. if (BuildPath.getNumOccurrences() > 0) return CompilationDatabase::autoDetectFromDirectory(BuildPath, ErrorMessage); // Try to auto-detect a compilation database from the first source. if (!SourcePaths.empty()) { if (CompilationDatabase *Compilations = CompilationDatabase::autoDetectFromSource(SourcePaths[0], ErrorMessage)) { // FIXME: just pass SourcePaths[0] once getCompileCommands supports // non-absolute paths. SmallString<64> Path(SourcePaths[0]); llvm::sys::fs::make_absolute(Path); std::vector<CompileCommand> Commands = Compilations->getCompileCommands(Path); // Ignore a detected compilation database that doesn't contain source0 // since it is probably an unrelated compilation database. if (!Commands.empty()) return Compilations; } // Reset ErrorMessage since a fix compilation database will be created if // it fails to detect one from source. ErrorMessage = ""; // If no compilation database can be detected from source then we create a // fixed compilation database with c++11 support. std::string CommandLine[] = { "-std=c++11" }; return new FixedCompilationDatabase(".", CommandLine); } ErrorMessage = "Could not determine sources to transform"; return 0; }
void updateArgIfSet(llvm::cl::opt<T> &argValue, const llvm::Optional<T> &configValue) { if (configValue.hasValue() && argValue.getNumOccurrences() == 0) { argValue.setValue(configValue.getValue()); } }
/// \brief Extract the minimum compiler versions as requested on the command /// line by the switch \c -for-compilers. /// /// \param ProgName The name of the program, \c argv[0], used to print errors. /// \param Error If an error occur while parsing the versions this parameter is /// set to \c true, otherwise it will be left untouched. static CompilerVersions handleSupportedCompilers(const char *ProgName, bool &Error) { if (SupportedCompilers.getNumOccurrences() == 0) return CompilerVersions(); CompilerVersions RequiredVersions; llvm::SmallVector<llvm::StringRef, 4> Compilers; llvm::StringRef(SupportedCompilers).split(Compilers, ","); for (llvm::SmallVectorImpl<llvm::StringRef>::iterator I = Compilers.begin(), E = Compilers.end(); I != E; ++I) { llvm::StringRef Compiler, VersionStr; std::tie(Compiler, VersionStr) = I->split('-'); Version *V = llvm::StringSwitch<Version *>(Compiler) .Case("clang", &RequiredVersions.Clang) .Case("gcc", &RequiredVersions.Gcc).Case("icc", &RequiredVersions.Icc) .Case("msvc", &RequiredVersions.Msvc).Default(NULL); if (V == NULL) { llvm::errs() << ProgName << ": " << Compiler << ": unsupported platform\n"; Error = true; continue; } if (VersionStr.empty()) { llvm::errs() << ProgName << ": " << *I << ": missing version number in platform\n"; Error = true; continue; } Version Version = Version::getFromString(VersionStr); if (Version.isNull()) { llvm::errs() << ProgName << ": " << *I << ": invalid version, please use \"<major>[.<minor>]\" instead of \"" << VersionStr << "\"\n"; Error = true; continue; } // support the lowest version given if (V->isNull() || Version < *V) *V = Version; } return RequiredVersions; }
static void addMscrtLibs(std::vector<std::string> &args) { llvm::StringRef mscrtlibName = mscrtlib; if (mscrtlibName.empty()) { // default to static release variant mscrtlibName = staticFlag || staticFlag.getNumOccurrences() == 0 ? "libcmt" : "msvcrt"; } args.push_back(("/DEFAULTLIB:" + mscrtlibName).str()); const bool isStatic = mscrtlibName.startswith_lower("libcmt"); const bool isDebug = mscrtlibName.endswith_lower("d") || mscrtlibName.endswith_lower("d.lib"); const llvm::StringRef prefix = isStatic ? "lib" : ""; const llvm::StringRef suffix = isDebug ? "d" : ""; args.push_back(("/DEFAULTLIB:" + prefix + "vcruntime" + suffix).str()); }
int main(int argc, char **argv) { INITIALIZE_LLVM(argc, argv); llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL optimizer\n"); if (PrintStats) llvm::EnableStatistics(); CompilerInvocation Invocation; Invocation.setMainExecutablePath( llvm::sys::fs::getMainExecutable(argv[0], reinterpret_cast<void *>(&anchorForGetMainExecutable))); // Give the context the list of search paths to use for modules. Invocation.setImportSearchPaths(ImportPaths); std::vector<SearchPathOptions::FrameworkSearchPath> FramePaths; for (const auto &path : FrameworkPaths) { FramePaths.push_back({path, /*isSystem=*/false}); } Invocation.setFrameworkSearchPaths(FramePaths); // Set the SDK path and target if given. if (SDKPath.getNumOccurrences() == 0) { const char *SDKROOT = getenv("SDKROOT"); if (SDKROOT) SDKPath = SDKROOT; } if (!SDKPath.empty()) Invocation.setSDKPath(SDKPath); if (!Target.empty()) Invocation.setTargetTriple(Target); if (!ResourceDir.empty()) Invocation.setRuntimeResourcePath(ResourceDir); Invocation.getFrontendOptions().EnableResilience = EnableResilience; // Set the module cache path. If not passed in we use the default swift module // cache. Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath; Invocation.setParseStdlib(); Invocation.getLangOptions().DisableAvailabilityChecking = true; Invocation.getLangOptions().EnableAccessControl = false; Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false; Invocation.getLangOptions().EnableObjCInterop = llvm::Triple(Target).isOSDarwin(); Invocation.getLangOptions().ASTVerifierProcessCount = ASTVerifierProcessCount; Invocation.getLangOptions().ASTVerifierProcessId = ASTVerifierProcessId; Invocation.getLangOptions().EnableSILOpaqueValues = EnableSILOpaqueValues; // Setup the SIL Options. SILOptions &SILOpts = Invocation.getSILOptions(); SILOpts.InlineThreshold = SILInlineThreshold; SILOpts.VerifyAll = EnableSILVerifyAll; SILOpts.RemoveRuntimeAsserts = RemoveRuntimeAsserts; SILOpts.AssertConfig = AssertConfId; if (OptimizationGroup != OptGroup::Diagnostics) SILOpts.Optimization = SILOptions::SILOptMode::Optimize; SILOpts.EnableSILOwnership = EnableSILOwnershipOpt; SILOpts.AssumeUnqualifiedOwnershipWhenParsing = AssumeUnqualifiedOwnershipWhenParsing; switch (EnforceExclusivity) { case EnforceExclusivityMode::Unchecked: // This option is analogous to the -Ounchecked optimization setting. // It will disable dynamic checking but still diagnose statically. SILOpts.EnforceExclusivityStatic = true; SILOpts.EnforceExclusivityDynamic = false; break; case EnforceExclusivityMode::Checked: SILOpts.EnforceExclusivityStatic = true; SILOpts.EnforceExclusivityDynamic = true; break; case EnforceExclusivityMode::DynamicOnly: // This option is intended for staging purposes. The intent is that // it will eventually be removed. SILOpts.EnforceExclusivityStatic = false; SILOpts.EnforceExclusivityDynamic = true; break; case EnforceExclusivityMode::None: // This option is for staging purposes. SILOpts.EnforceExclusivityStatic = false; SILOpts.EnforceExclusivityDynamic = false; break; } // Load the input file. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(InputFilename); if (!FileBufOrErr) { fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str()); exit(-1); } // If it looks like we have an AST, set the source file kind to SIL and the // name of the module to the file's name. Invocation.addInputBuffer(FileBufOrErr.get().get()); serialization::ExtendedValidationInfo extendedInfo; auto result = serialization::validateSerializedAST( FileBufOrErr.get()->getBuffer(), &extendedInfo); bool HasSerializedAST = result.status == serialization::Status::Valid; if (HasSerializedAST) { const StringRef Stem = ModuleName.size() ? StringRef(ModuleName) : llvm::sys::path::stem(InputFilename); Invocation.setModuleName(Stem); Invocation.setInputKind(InputFileKind::IFK_Swift_Library); } else { const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main"; Invocation.setModuleName(Name); Invocation.setInputKind(InputFileKind::IFK_SIL); } CompilerInstance CI; PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); if (!PerformWMO) { auto &FrontendOpts = Invocation.getFrontendOptions(); if (!InputFilename.empty() && InputFilename != "-") { FrontendOpts.PrimaryInput = SelectedInput( FrontendOpts.InputFilenames.size()); } else { FrontendOpts.PrimaryInput = SelectedInput( FrontendOpts.InputBuffers.size(), SelectedInput::InputKind::Buffer); } } if (CI.setup(Invocation)) return 1; CI.performSema(); // If parsing produced an error, don't run any passes. if (CI.getASTContext().hadError()) return 1; // Load the SIL if we have a module. We have to do this after SILParse // creating the unfortunate double if statement. if (HasSerializedAST) { assert(!CI.hasSILModule() && "performSema() should not create a SILModule."); CI.setSILModule(SILModule::createEmptyModule( CI.getMainModule(), CI.getSILOptions(), PerformWMO)); std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create( CI.getASTContext(), CI.getSILModule(), nullptr); if (extendedInfo.isSIB() || DisableSILLinking) SL->getAllForModule(CI.getMainModule()->getName(), nullptr); else SL->getAll(); } // If we're in verify mode, install a custom diagnostic handling for // SourceMgr. if (VerifyMode) enableDiagnosticVerifier(CI.getSourceMgr()); if (OptimizationGroup == OptGroup::Diagnostics) { runSILDiagnosticPasses(*CI.getSILModule()); } else if (OptimizationGroup == OptGroup::Performance) { runSILOptimizationPasses(*CI.getSILModule()); } else if (OptimizationGroup == OptGroup::Lowering) { runSILLoweringPasses(*CI.getSILModule()); } else { auto *SILMod = CI.getSILModule(); { auto T = irgen::createIRGenModule(SILMod, getGlobalLLVMContext()); runCommandLineSelectedPasses(SILMod, T.second); irgen::deleteIRGenModule(T); } } if (EmitSIB) { llvm::SmallString<128> OutputFile; if (OutputFilename.size()) { OutputFile = OutputFilename; } else if (ModuleName.size()) { OutputFile = ModuleName; llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION); } else { OutputFile = CI.getMainModule()->getName().str(); llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION); } SerializationOptions serializationOpts; serializationOpts.OutputPath = OutputFile.c_str(); serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; serialize(CI.getMainModule(), serializationOpts, CI.getSILModule()); } else { const StringRef OutputFile = OutputFilename.size() ? StringRef(OutputFilename) : "-"; if (OutputFile == "-") { CI.getSILModule()->print(llvm::outs(), EmitVerboseSIL, CI.getMainModule(), EnableSILSortOutput, !DisableASTDump); } else { std::error_code EC; llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None); if (EC) { llvm::errs() << "while opening '" << OutputFile << "': " << EC.message() << '\n'; return 1; } CI.getSILModule()->print(OS, EmitVerboseSIL, CI.getMainModule(), EnableSILSortOutput, !DisableASTDump); } } bool HadError = CI.getASTContext().hadError(); // If we're in -verify mode, we've buffered up all of the generated // diagnostics. Check now to ensure that they meet our expectations. if (VerifyMode) { HadError = verifyDiagnostics(CI.getSourceMgr(), CI.getInputBufferIDs(), /*autoApplyFixes*/false, /*ignoreUnknown*/false); DiagnosticEngine &diags = CI.getDiags(); if (diags.hasFatalErrorOccurred() && !Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) { diags.resetHadAnyError(); diags.diagnose(SourceLoc(), diag::verify_encountered_fatal); HadError = true; } } return HadError; }
int main(int argc, char **argv) { INITIALIZE_LLVM(argc, argv); llvm::cl::ParseCommandLineOptions(argc, argv, "Swift LLVM IR Generator\n"); if (PrintStats) llvm::EnableStatistics(); CompilerInvocation Invocation; Invocation.setMainExecutablePath(llvm::sys::fs::getMainExecutable( argv[0], reinterpret_cast<void *>(&anchorForGetMainExecutable))); // Give the context the list of search paths to use for modules. Invocation.setImportSearchPaths(ImportPaths); Invocation.setFrameworkSearchPaths(FrameworkPaths); // Set the SDK path and target if given. if (SDKPath.getNumOccurrences() == 0) { const char *SDKROOT = getenv("SDKROOT"); if (SDKROOT) SDKPath = SDKROOT; } if (!SDKPath.empty()) Invocation.setSDKPath(SDKPath); if (!Target.empty()) Invocation.setTargetTriple(Target); if (!ResourceDir.empty()) Invocation.setRuntimeResourcePath(ResourceDir); // Set the module cache path. If not passed in we use the default swift module // cache. Invocation.getClangImporterOptions().ModuleCachePath = 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(); // Setup the SIL Options. SILOptions &SILOpts = Invocation.getSILOptions(); SILOpts.AssumeUnqualifiedOwnershipWhenParsing = AssumeUnqualifiedOwnershipWhenParsing; // Setup the IRGen Options. IRGenOptions &Opts = Invocation.getIRGenOptions(); Opts.MainInputFilename = InputFilename; Opts.OutputFilenames.push_back(OutputFilename); Opts.OutputKind = OutputKind; // Load the input file. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(InputFilename); if (!FileBufOrErr) { fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str()); exit(-1); } // If it looks like we have an AST, set the source file kind to SIL and the // name of the module to the file's name. Invocation.addInputBuffer(FileBufOrErr.get().get()); serialization::ExtendedValidationInfo extendedInfo; auto result = serialization::validateSerializedAST( FileBufOrErr.get()->getBuffer(), &extendedInfo); bool HasSerializedAST = result.status == serialization::Status::Valid; if (HasSerializedAST) { const StringRef Stem = ModuleName.size() ? StringRef(ModuleName) : llvm::sys::path::stem(InputFilename); Invocation.setModuleName(Stem); Invocation.setInputKind(InputFileKind::IFK_Swift_Library); } else { const StringRef Name = ModuleName.size() ? StringRef(ModuleName) : "main"; Invocation.setModuleName(Name); Invocation.setInputKind(InputFileKind::IFK_SIL); } CompilerInstance CI; PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); if (!PerformWMO) { auto &FrontendOpts = Invocation.getFrontendOptions(); if (!InputFilename.empty() && InputFilename != "-") { FrontendOpts.PrimaryInput = SelectedInput(FrontendOpts.InputFilenames.size()); } else { FrontendOpts.PrimaryInput = SelectedInput( FrontendOpts.InputBuffers.size(), SelectedInput::InputKind::Buffer); } } if (CI.setup(Invocation)) return 1; CI.performSema(); // If parsing produced an error, don't run any passes. if (CI.getASTContext().hadError()) return 1; // Load the SIL if we have a module. We have to do this after SILParse // creating the unfortunate double if statement. if (HasSerializedAST) { assert(!CI.hasSILModule() && "performSema() should not create a SILModule."); CI.setSILModule(SILModule::createEmptyModule( CI.getMainModule(), CI.getSILOptions(), PerformWMO)); std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create( CI.getASTContext(), CI.getSILModule(), nullptr); if (extendedInfo.isSIB()) SL->getAllForModule(CI.getMainModule()->getName(), nullptr); else SL->getAll(); } std::unique_ptr<llvm::Module> Mod = performIRGeneration( Opts, CI.getMainModule(), CI.takeSILModule(), CI.getMainModule()->getName().str(), getGlobalLLVMContext()); return CI.getASTContext().hadError(); }
int main(int argc, const char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(); Transforms TransformManager; ReplacementHandling ReplacementHandler; TransformManager.registerTransforms(); // Hide all options we don't define ourselves. Move pre-defined 'help', // 'help-list', and 'version' to our general category. llvm::StringMap<cl::Option*> Options; cl::getRegisteredOptions(Options); const cl::OptionCategory **CategoryEnd = VisibleCategories + llvm::array_lengthof(VisibleCategories); for (llvm::StringMap<cl::Option *>::iterator I = Options.begin(), E = Options.end(); I != E; ++I) { if (I->first() == "help" || I->first() == "version" || I->first() == "help-list") I->second->setCategory(GeneralCategory); else if (std::find(VisibleCategories, CategoryEnd, I->second->Category) == CategoryEnd) I->second->setHiddenFlag(cl::ReallyHidden); } cl::SetVersionPrinter(&printVersion); // Parse options and generate compilations. std::unique_ptr<CompilationDatabase> Compilations( FixedCompilationDatabase::loadFromCommandLine(argc, argv)); cl::ParseCommandLineOptions(argc, argv); // Populate the ModifiableFiles structure. GlobalOptions.ModifiableFiles.readListFromString(IncludePaths, ExcludePaths); GlobalOptions.ModifiableFiles.readListFromFile(IncludeFromFile, ExcludeFromFile); if (!Compilations) { std::string ErrorMessage; Compilations.reset(autoDetectCompilations(ErrorMessage)); if (!Compilations) { llvm::errs() << llvm::sys::path::filename(argv[0]) << ": " << ErrorMessage << "\n"; return 1; } } // Populate source files. std::vector<std::string> Sources; if (!SourcePaths.empty()) { // Use only files that are not explicitly excluded. std::remove_copy_if(SourcePaths.begin(), SourcePaths.end(), std::back_inserter(Sources), isFileExplicitlyExcludedPredicate); } else { if (GlobalOptions.ModifiableFiles.isIncludeListEmpty()) { llvm::errs() << llvm::sys::path::filename(argv[0]) << ": Use -include to indicate which files of " << "the compilatiion database to transform.\n"; return 1; } // Use source paths from the compilation database. // We only transform files that are explicitly included. Sources = Compilations->getAllFiles(); std::vector<std::string>::iterator E = std::remove_if( Sources.begin(), Sources.end(), isFileNotIncludedPredicate); Sources.erase(E, Sources.end()); } // check if line ranges are just applyed to single files if ( !LineRanges.empty() && Sources.size() > 1 ){ llvm::errs() << "error: -line can only be used for single file.\n"; return 1; } // add the line ranges to the sources if ( !LineRanges.empty() ){ } if (Sources.empty()) { llvm::errs() << llvm::sys::path::filename(argv[0]) << ": Could not determine sources to transform.\n"; return 1; } // Enable timming. GlobalOptions.EnableTiming = TimingDirectoryName.getNumOccurrences() > 0; bool CmdSwitchError = false; CompilerVersions RequiredVersions = handleSupportedCompilers(argv[0], CmdSwitchError); if (CmdSwitchError) return 1; TransformManager.createSelectedTransforms(GlobalOptions, RequiredVersions); if (TransformManager.begin() == TransformManager.end()) { if (SupportedCompilers.empty()) llvm::errs() << llvm::sys::path::filename(argv[0]) << ": no selected transforms\n"; else llvm::errs() << llvm::sys::path::filename(argv[0]) << ": no transforms available for specified compilers\n"; return 1; } llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts( new DiagnosticOptions()); DiagnosticsEngine Diagnostics( llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), DiagOpts.getPtr()); // FIXME: Make this DiagnosticsEngine available to all Transforms probably via // GlobalOptions. // If SerializeReplacements is requested, then code reformatting must be // turned off and only one transform should be requested. if (SerializeOnly && (std::distance(TransformManager.begin(), TransformManager.end()) > 1 || DoFormat)) { llvm::errs() << "Serialization of replacements requested for multiple " "transforms.\nChanges from only one transform can be " "serialized.\n"; return 1; } // If we're asked to apply changes to files on disk, need to locate // clang-apply-replacements. if (!SerializeOnly) { if (!ReplacementHandler.findClangApplyReplacements(argv[0])) { llvm::errs() << "Could not find clang-apply-replacements\n"; return 1; } if (DoFormat) ReplacementHandler.enableFormatting(FormatStyleOpt, FormatStyleConfig); } StringRef TempDestinationDir; if (SerializeLocation.getNumOccurrences() > 0) ReplacementHandler.setDestinationDir(SerializeLocation); else TempDestinationDir = ReplacementHandler.useTempDestinationDir(); SourcePerfData PerfData; for (Transforms::const_iterator I = TransformManager.begin(), E = TransformManager.end(); I != E; ++I) { Transform *T = *I; if (T->apply(*Compilations, Sources,LineRanges) != 0) { // FIXME: Improve ClangTool to not abort if just one file fails. return 1; } if (GlobalOptions.EnableTiming) collectSourcePerfData(*T, PerfData); if (SummaryMode) { llvm::outs() << "Transform: " << T->getName() << " - Accepted: " << T->getAcceptedChanges(); if (T->getChangesNotMade()) { llvm::outs() << " - Rejected: " << T->getRejectedChanges() << " - Deferred: " << T->getDeferredChanges(); } llvm::outs() << "\n"; } if (!ReplacementHandler.serializeReplacements(T->getAllReplacements())) return 1; if (!SerializeOnly) if (!ReplacementHandler.applyReplacements()) return 1; } // Let the user know which temporary directory the replacements got written // to. if (SerializeOnly && !TempDestinationDir.empty()) llvm::errs() << "Replacements serialized to: " << TempDestinationDir << "\n"; if (FinalSyntaxCheck) { ClangTool SyntaxTool(*Compilations, SourcePaths); if (SyntaxTool.run(newFrontendActionFactory<SyntaxOnlyAction>().get()) != 0) return 1; } // Report execution times. if (GlobalOptions.EnableTiming && !PerfData.empty()) { std::string DirectoryName = TimingDirectoryName; // Use default directory name. if (DirectoryName.empty()) DirectoryName = "./migrate_perf"; writePerfDataJSON(DirectoryName, PerfData); } return 0; }
int main(int argc, char **argv) { INITIALIZE_LLVM(argc, argv); llvm::cl::ParseCommandLineOptions(argc, argv, "Swift SIL Extractor\n"); CompilerInvocation Invocation; Invocation.setMainExecutablePath(llvm::sys::fs::getMainExecutable( argv[0], reinterpret_cast<void *>(&anchorForGetMainExecutable))); // Give the context the list of search paths to use for modules. Invocation.setImportSearchPaths(ImportPaths); // Set the SDK path and target if given. if (SDKPath.getNumOccurrences() == 0) { const char *SDKROOT = getenv("SDKROOT"); if (SDKROOT) SDKPath = SDKROOT; } if (!SDKPath.empty()) Invocation.setSDKPath(SDKPath); if (!Triple.empty()) Invocation.setTargetTriple(Triple); if (!ResourceDir.empty()) Invocation.setRuntimeResourcePath(ResourceDir); Invocation.getClangImporterOptions().ModuleCachePath = ModuleCachePath; Invocation.setParseStdlib(); Invocation.getLangOptions().DisableAvailabilityChecking = true; Invocation.getLangOptions().EnableAccessControl = false; Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false; // Load the input file. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = llvm::MemoryBuffer::getFileOrSTDIN(InputFilename); if (!FileBufOrErr) { fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str()); exit(-1); } // If it looks like we have an AST, set the source file kind to SIL and the // name of the module to the file's name. Invocation.addInputBuffer(FileBufOrErr.get().get()); serialization::ExtendedValidationInfo extendedInfo; auto result = serialization::validateSerializedAST( FileBufOrErr.get()->getBuffer(), &extendedInfo); bool HasSerializedAST = result.status == serialization::Status::Valid; if (HasSerializedAST) { const StringRef Stem = ModuleName.size() ? StringRef(ModuleName) : llvm::sys::path::stem(InputFilename); Invocation.setModuleName(Stem); Invocation.setInputKind(InputFileKind::IFK_Swift_Library); } else { Invocation.setModuleName("main"); Invocation.setInputKind(InputFileKind::IFK_SIL); } SILOptions &SILOpts = Invocation.getSILOptions(); SILOpts.AssumeUnqualifiedOwnershipWhenParsing = AssumeUnqualifiedOwnershipWhenParsing; CompilerInstance CI; PrintingDiagnosticConsumer PrintDiags; CI.addDiagnosticConsumer(&PrintDiags); if (CI.setup(Invocation)) return 1; CI.performSema(); // If parsing produced an error, don't run any passes. if (CI.getASTContext().hadError()) return 1; // Load the SIL if we have a module. We have to do this after SILParse // creating the unfortunate double if statement. if (HasSerializedAST) { assert(!CI.hasSILModule() && "performSema() should not create a SILModule."); CI.setSILModule( SILModule::createEmptyModule(CI.getMainModule(), CI.getSILOptions())); std::unique_ptr<SerializedSILLoader> SL = SerializedSILLoader::create( CI.getASTContext(), CI.getSILModule(), nullptr); if (extendedInfo.isSIB()) SL->getAllForModule(CI.getMainModule()->getName(), nullptr); else SL->getAll(); } if (CommandLineFunctionNames.empty() && FunctionNameFile.empty()) return CI.getASTContext().hadError(); // For efficient usage, we separate our names into two separate sorted // lists, one of managled names, and one of unmangled names. std::vector<std::string> Names; getFunctionNames(Names); // First partition our function names into mangled/demangled arrays. auto FirstDemangledName = std::partition( Names.begin(), Names.end(), [](const std::string &Name) -> bool { StringRef NameRef(Name); return NameRef.startswith("_T") || NameRef.startswith(MANGLING_PREFIX_STR); }); // Then grab offsets to avoid any issues with iterator invalidation when we // sort. unsigned NumMangled = std::distance(Names.begin(), FirstDemangledName); unsigned NumNames = Names.size(); // Then sort the two partitioned arrays. std::sort(Names.begin(), FirstDemangledName); std::sort(FirstDemangledName, Names.end()); // Finally construct our ArrayRefs into the sorted std::vector for our // mangled and demangled names. ArrayRef<std::string> MangledNames(&*Names.begin(), NumMangled); ArrayRef<std::string> DemangledNames(&*std::next(Names.begin(), NumMangled), NumNames - NumMangled); DEBUG(llvm::errs() << "MangledNames to keep:\n"; std::for_each(MangledNames.begin(), MangledNames.end(), [](const std::string &str) { llvm::errs() << " " << str << '\n'; })); DEBUG(llvm::errs() << "DemangledNames to keep:\n"; std::for_each(DemangledNames.begin(), DemangledNames.end(), [](const std::string &str) { llvm::errs() << " " << str << '\n'; })); removeUnwantedFunctions(CI.getSILModule(), MangledNames, DemangledNames); if (EmitSIB) { llvm::SmallString<128> OutputFile; if (OutputFilename.size()) { OutputFile = OutputFilename; } else if (ModuleName.size()) { OutputFile = ModuleName; llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION); } else { OutputFile = CI.getMainModule()->getName().str(); llvm::sys::path::replace_extension(OutputFile, SIB_EXTENSION); } SerializationOptions serializationOpts; serializationOpts.OutputPath = OutputFile.c_str(); serializationOpts.SerializeAllSIL = true; serializationOpts.IsSIB = true; serialize(CI.getMainModule(), serializationOpts, CI.getSILModule()); } else { const StringRef OutputFile = OutputFilename.size() ? StringRef(OutputFilename) : "-"; if (OutputFile == "-") { CI.getSILModule()->print(llvm::outs(), EmitVerboseSIL, CI.getMainModule(), EnableSILSortOutput, !DisableASTDump); } else { std::error_code EC; llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None); if (EC) { llvm::errs() << "while opening '" << OutputFile << "': " << EC.message() << '\n'; return 1; } CI.getSILModule()->print(OS, EmitVerboseSIL, CI.getMainModule(), EnableSILSortOutput, !DisableASTDump); } } }
int main(int argc, const char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(); Transforms TransformManager; ReplacementHandling ReplacementHandler; TransformManager.registerTransforms(); // Hide all options we don't define ourselves. Move pre-defined 'help', // 'help-list', and 'version' to our general category. llvm::StringMap<cl::Option*> Options; cl::getRegisteredOptions(Options); const cl::OptionCategory **CategoryEnd = VisibleCategories + llvm::array_lengthof(VisibleCategories); for (llvm::StringMap<cl::Option *>::iterator I = Options.begin(), E = Options.end(); I != E; ++I) { if (I->first() == "help" || I->first() == "version" || I->first() == "help-list") I->second->setCategory(GeneralCategory); else if (std::find(VisibleCategories, CategoryEnd, I->second->Category) == CategoryEnd) I->second->setHiddenFlag(cl::ReallyHidden); } cl::SetVersionPrinter(&printVersion); // Parse options and generate compilations. std::unique_ptr<CompilationDatabase> Compilations( FixedCompilationDatabase::loadFromCommandLine(argc, argv)); cl::ParseCommandLineOptions(argc, argv); // Populate the ModifiableFiles structure. GlobalOptions.ModifiableFiles.readListFromString(IncludePaths, ExcludePaths); GlobalOptions.ModifiableFiles.readListFromFile(IncludeFromFile, ExcludeFromFile); if (!Compilations) { std::string ErrorMessage; Compilations = autoDetectCompilations(ErrorMessage); if (!Compilations) { llvm::errs() << llvm::sys::path::filename(argv[0]) << ": " << ErrorMessage << "\n"; return 1; } } // Populate source files. std::vector<std::string> Sources; if (!SourcePaths.empty()) { // Use only files that are not explicitly excluded. std::remove_copy_if(SourcePaths.begin(), SourcePaths.end(), std::back_inserter(Sources), isFileExplicitlyExcludedPredicate); } else { if (GlobalOptions.ModifiableFiles.isIncludeListEmpty()) { llvm::errs() << llvm::sys::path::filename(argv[0]) << ": Use -include to indicate which files of " << "the compilatiion database to transform.\n"; return 1; } // Use source paths from the compilation database. // We only transform files that are explicitly included. Sources = Compilations->getAllFiles(); std::vector<std::string>::iterator E = std::remove_if( Sources.begin(), Sources.end(), isFileNotIncludedPredicate); Sources.erase(E, Sources.end()); } // check if line ranges are just applyed to single files if ( !LineRanges.empty() && Sources.size() > 1 ) { llvm::errs() << "error: -line can only be used for single file.\n"; return 1; } // add the line ranges to the sources if ( !LineRanges.empty() ) { } std::string filename; int line_begin, column_begin; int line_end, column_end; if ( Target.getNumOccurrences() ) { // TODO parse the target data std::stringstream sstr(Target); char separator; sstr >> line_begin >> separator >> column_begin >> separator >> line_end >> separator >> column_end >> separator >> filename; llvm::errs() << filename << " " << line_begin << "-" << column_begin << ":" << line_end << "-" << column_end << "\n"; // store it in the Transform object }