blob: 980e715450733bbbe0b3a68ec891546b4972b9d7 [file] [log] [blame]
//===--- OutputFileMap.cpp - Driver output file map -----------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "swift/Driver/OutputFileMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <system_error>
using namespace swift;
using namespace swift::driver;
std::unique_ptr<OutputFileMap> OutputFileMap::loadFromPath(StringRef Path) {
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
llvm::MemoryBuffer::getFile(Path);
if (!FileBufOrErr)
return nullptr;
return loadFromBuffer(std::move(FileBufOrErr.get()));
}
std::unique_ptr<OutputFileMap> OutputFileMap::loadFromBuffer(StringRef Data) {
std::unique_ptr<llvm::MemoryBuffer> Buffer{
llvm::MemoryBuffer::getMemBuffer(Data)
};
return loadFromBuffer(std::move(Buffer));
}
std::unique_ptr<OutputFileMap>
OutputFileMap::loadFromBuffer(std::unique_ptr<llvm::MemoryBuffer> Buffer) {
std::unique_ptr<OutputFileMap> 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;
}
const TypeToPathMap *OutputFileMap::getOutputMapForSingleOutput() const {
return getOutputMapForInput(StringRef());
}
void OutputFileMap::dump(llvm::raw_ostream &os, bool Sort) const {
typedef std::pair<types::ID, std::string> TypePathPair;
auto printOutputPair = [&os] (StringRef InputPath,
const TypePathPair &OutputPair) -> void {
os << InputPath << " -> " << types::getTypeName(OutputPair.first) << ": \""
<< OutputPair.second << "\"\n";
};
if (Sort) {
typedef std::pair<StringRef, TypeToPathMap> PathMapPair;
std::vector<PathMapPair> 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<TypePathPair> 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<llvm::MemoryBuffer> Buffer) {
llvm::SourceMgr SM;
llvm::yaml::Stream YAMLStream(Buffer->getMemBufferRef(), SM);
auto I = YAMLStream.begin();
if (I == YAMLStream.end())
return true;
auto Root = I->getRoot();
if (!Root)
return true;
auto *Map = dyn_cast<llvm::yaml::MappingNode>(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;
auto *InputPath = dyn_cast<llvm::yaml::ScalarNode>(Key);
if (!InputPath)
return true;
llvm::yaml::MappingNode *OutputMapNode =
dyn_cast<llvm::yaml::MappingNode>(Value);
if (!OutputMapNode)
return true;
TypeToPathMap OutputMap;
for (auto OutputPair : *OutputMapNode) {
llvm::yaml::Node *Key = OutputPair.getKey();
llvm::yaml::Node *Value = OutputPair.getValue();
auto *KindNode = dyn_cast<llvm::yaml::ScalarNode>(Key);
if (!KindNode)
return true;
auto *Path = dyn_cast<llvm::yaml::ScalarNode>(Value);
if (!Path)
return true;
llvm::SmallString<16> KindStorage;
types::ID Kind =
types::lookupTypeForName(KindNode->getValue(KindStorage));
// Ignore unknown types, so that an older swiftc can be used with a newer
// build system.
if (Kind == types::TY_INVALID)
continue;
llvm::SmallString<128> PathStorage;
OutputMap.insert(
std::pair<types::ID, std::string>(Kind, Path->getValue(PathStorage)));
}
llvm::SmallString<128> InputStorage;
InputToOutputsMap[InputPath->getValue(InputStorage)] = std::move(OutputMap);
}
return false;
}