blob: a5345406c7b75c6acaaba291ebba0ad316d83739 [file] [log] [blame]
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "compiler/Serialization/VMSourceMapBuilder.h"
#include "flatbuffers/flatbuffers.h"
#include "schemas/source_map_def_generated.h"
#include "llvm/Support/raw_ostream.h"
#include "mlir/IR/Identifier.h"
#include "mlir/IR/Location.h"
namespace mlir {
namespace iree_compiler {
VMSourceMapBuilder::VMSourceMapBuilder(::flatbuffers::FlatBufferBuilder *fbb)
: fbb_(fbb) {}
int VMSourceMapBuilder::GetUniqueString(std::string value) {
auto it = stringTableMap_.find(value);
if (it != stringTableMap_.end()) {
return it->second;
}
int stringIndex = stringTable_.size();
stringTableMap_.insert({value, stringIndex});
stringTable_.push_back(std::move(value));
return stringIndex;
}
LogicalResult VMSourceMapBuilder::AddFunction(
int functionOrdinal, VMFunctionSourceMap functionSourceMap) {
if (functionMaps_.size() <= functionOrdinal) {
functionMaps_.resize(functionOrdinal + 1);
}
functionMaps_[functionOrdinal] = std::move(functionSourceMap);
return success();
}
::flatbuffers::Offset<iree::SourceMapDef> VMSourceMapBuilder::Finish(
int maxFunctionOrdinal) {
// NOTE: we always ensure the source map table is the same size as the
// function table so that lookups at runtime can be validated once at load
// time (ensuring the tables match up) instead of on each lookup.
if (maxFunctionOrdinal < functionMaps_.size()) {
llvm::errs() << "Max function ordinal defined as " << maxFunctionOrdinal
<< " but there are " << functionMaps_.size()
<< " function source maps present";
return {};
}
functionMaps_.resize(maxFunctionOrdinal);
std::vector<::flatbuffers::Offset<iree::FunctionSourceMapDef>> functionDefs;
functionDefs.resize(maxFunctionOrdinal);
for (int i = 0; i < functionMaps_.size(); ++i) {
const auto &functionMap = functionMaps_[i];
functionDefs[i] = SerializeVMFunctionSourceMap(functionMap);
if (functionDefs[i].IsNull()) return {};
}
auto functionTableOffset = fbb_->CreateVector(functionDefs);
auto stringTableOffset = fbb_->CreateVectorOfStrings(stringTable_);
iree::SourceMapDefBuilder smdb(*fbb_);
smdb.add_function_table(functionTableOffset);
smdb.add_string_table(stringTableOffset);
return smdb.Finish();
}
::flatbuffers::Offset<iree::FunctionSourceMapDef>
VMSourceMapBuilder::SerializeVMFunctionSourceMap(
const VMFunctionSourceMap &functionMap) {
if (functionMap.locations.empty()) {
// Empty table. This ensures that we still have a non-null value in the
// function table but doesn't waste much space.
iree::FunctionSourceMapDefBuilder fsmdb(*fbb_);
return fsmdb.Finish();
}
LocationOffsetTable locationOffsetTable;
std::vector<iree::BytecodeSourceLocation> bytecodeMap;
for (const auto &offset_location : functionMap.locations) {
int locationIndex =
SerializeLocation(offset_location.second, &locationOffsetTable);
bytecodeMap.push_back({offset_location.first, locationIndex});
}
auto locationTableOffset =
fbb_->CreateVector(locationOffsetTable.locationDefs);
auto bytecodeMapOffset = fbb_->CreateVectorOfStructs(bytecodeMap);
iree::FunctionSourceMapDefBuilder fsmdb(*fbb_);
fsmdb.add_location_table(locationTableOffset);
fsmdb.add_bytecode_map(bytecodeMapOffset);
return fsmdb.Finish();
}
int VMSourceMapBuilder::SerializeLocation(
const Location &location, LocationOffsetTable *locationOffsetTable) {
auto existingIt = locationOffsetTable->locationMap.find(location);
if (existingIt != locationOffsetTable->locationMap.end()) {
return existingIt->getSecond();
}
iree::LocationDefUnion locationUnionType;
::flatbuffers::Offset<void> locationUnionOffset;
if (auto fileLoc = location.dyn_cast<FileLineColLoc>()) {
locationUnionType = iree::LocationDefUnion::FileLocationDef;
int filenameIndex = GetUniqueString(fileLoc.getFilename().str());
iree::FileLocationDefBuilder lb(*fbb_);
lb.add_filename(filenameIndex);
lb.add_line(fileLoc.getLine());
lb.add_column(fileLoc.getColumn());
locationUnionOffset = lb.Finish().Union();
} else if (auto nameLoc = location.dyn_cast<NameLoc>()) {
locationUnionType = iree::LocationDefUnion::NameLocationDef;
int nameIndex = GetUniqueString(nameLoc.getName().str());
iree::NameLocationDefBuilder lb(*fbb_);
lb.add_name(nameIndex);
locationUnionOffset = lb.Finish().Union();
} else if (auto callSiteLoc = location.dyn_cast<CallSiteLoc>()) {
locationUnionType = iree::LocationDefUnion::CallSiteLocationDef;
int calleeIndex =
SerializeLocation(callSiteLoc.getCallee(), locationOffsetTable);
int callerIndex =
SerializeLocation(callSiteLoc.getCaller(), locationOffsetTable);
iree::CallSiteLocationDefBuilder lb(*fbb_);
lb.add_callee_location(calleeIndex);
lb.add_caller_location(callerIndex);
locationUnionOffset = lb.Finish().Union();
} else if (auto fusedLoc = location.dyn_cast<FusedLoc>()) {
locationUnionType = iree::LocationDefUnion::FusedLocationDef;
std::vector<int> locationIndices;
locationIndices.reserve(fusedLoc.getLocations().size());
for (const auto &child_loc : fusedLoc.getLocations()) {
int child_index = SerializeLocation(child_loc, locationOffsetTable);
locationIndices.push_back(child_index);
}
auto locationIndicesOffset = fbb_->CreateVector(locationIndices);
iree::FusedLocationDefBuilder lb(*fbb_);
lb.add_locations(locationIndicesOffset);
locationUnionOffset = lb.Finish().Union();
} else {
llvm_unreachable("Unimplemented location kind");
}
iree::LocationDefBuilder ldb(*fbb_);
ldb.add_location_union_type(locationUnionType);
ldb.add_location_union(locationUnionOffset);
int locationIndex = locationOffsetTable->locationDefs.size();
locationOffsetTable->locationDefs.push_back(ldb.Finish());
locationOffsetTable->locationMap.insert({location, locationIndex});
return locationIndex;
}
} // namespace iree_compiler
} // namespace mlir