//===-- OutputFileMap.cpp - Driver output file map -------------*- C++ -*--===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "swift/Driver/OutputFileMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" #include using namespace swift; using namespace swift::driver; std::unique_ptr OutputFileMap::loadFromPath(StringRef Path) { llvm::ErrorOr> FileBufOrErr = llvm::MemoryBuffer::getFile(Path); if (!FileBufOrErr) return nullptr; return loadFromBuffer(std::move(FileBufOrErr.get())); } std::unique_ptr OutputFileMap::loadFromBuffer(StringRef Data) { std::unique_ptr Buffer{ llvm::MemoryBuffer::getMemBuffer(Data) }; return loadFromBuffer(std::move(Buffer)); } std::unique_ptr OutputFileMap::loadFromBuffer(std::unique_ptr Buffer) { std::unique_ptr OFM(new OutputFileMap()); if (OFM->parse(std::move(Buffer))) return nullptr; return OFM; } const TypeToPathMap *OutputFileMap::getOutputMapForInput(StringRef Input) const{ auto iter = InputToOutputsMap.find(Input); if (iter == InputToOutputsMap.end()) return nullptr; else return &iter->second; } void OutputFileMap::dump(llvm::raw_ostream &os, bool Sort) const { typedef std::pair TypePathPair; auto printOutputPair = [&os] (StringRef InputPath, const TypePathPair &OutputPair) -> void { os << InputPath << " -> " << types::getTypeName(OutputPair.first) << ": \"" << OutputPair.second << "\"\n"; }; if (Sort) { typedef std::pair PathMapPair; std::vector Maps; for (auto &InputPair : InputToOutputsMap) { Maps.emplace_back(InputPair.first(), InputPair.second); } std::sort(Maps.begin(), Maps.end(), [] (const PathMapPair &LHS, const PathMapPair &RHS) -> bool { return LHS.first < RHS.first; }); for (auto &InputPair : Maps) { const TypeToPathMap &Map = InputPair.second; std::vector Pairs; Pairs.insert(Pairs.end(), Map.begin(), Map.end()); std::sort(Pairs.begin(), Pairs.end()); for (auto &OutputPair : Pairs) { printOutputPair(InputPair.first, OutputPair); } } } else { for (auto &InputPair : InputToOutputsMap) { const TypeToPathMap &Map = InputPair.second; for (const TypePathPair &OutputPair : Map) { printOutputPair(InputPair.first(), OutputPair); } } } } bool OutputFileMap::parse(std::unique_ptr Buffer) { llvm::SourceMgr SM; llvm::yaml::Stream YAMLStream(std::move(Buffer), SM); auto I = YAMLStream.begin(); if (I == YAMLStream.end()) return true; auto Root = I->getRoot(); if (!Root) return true; llvm::yaml::MappingNode *Map = dyn_cast(Root); if (!Map) return true; for (auto Pair : *Map) { llvm::yaml::Node *Key = Pair.getKey(); llvm::yaml::Node *Value = Pair.getValue(); if (!Key) return true; if (!Value) return true; llvm::yaml::ScalarNode *InputPath = dyn_cast(Key); if (!InputPath) return true; llvm::yaml::MappingNode *OutputMapNode = dyn_cast(Value); if (!OutputMapNode) return true; TypeToPathMap OutputMap; for (auto OutputPair : *OutputMapNode) { llvm::yaml::Node *Key = OutputPair.getKey(); llvm::yaml::Node *Value = OutputPair.getValue(); llvm::yaml::ScalarNode *KindNode = dyn_cast(Key); if (!KindNode) return true; llvm::yaml::ScalarNode *Path = dyn_cast(Value); if (!Path) return true; llvm::SmallString<16> KindStorage; types::ID Kind = types::lookupTypeForName(KindNode->getValue(KindStorage)); if (Kind == types::TY_INVALID) return true; llvm::SmallString<128> PathStorage; OutputMap.insert( std::pair(Kind, Path->getValue(PathStorage))); } llvm::SmallString<128> InputStorage; InputToOutputsMap[InputPath->getValue(InputStorage)] = std::move(OutputMap); } return false; }