blob: 747e3abc8aa129b69c66dee53e264f3ab639ff0a [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 "third_party/mlir_edge/iree/vm/source_map.h"
#include <sstream>
#include "third_party/mlir_edge/iree/base/flatbuffer_util.h"
#include "third_party/mlir_edge/iree/base/status.h"
namespace iree {
namespace vm {
namespace {
Status PrintLocation(const SourceMap& source_map,
const FunctionSourceMapDef& function_source_map,
const LocationDef& location, std::ostream* stream);
Status PrintFileLocation(const SourceMap& source_map,
const FunctionSourceMapDef& function_source_map,
const FileLocationDef& location,
std::ostream* stream) {
ASSIGN_OR_RETURN(auto filename,
source_map.GetUniqueString(location.filename()));
*stream << filename << ":" << location.line() << ":" << location.column();
return OkStatus();
}
Status PrintNameLocation(const SourceMap& source_map,
const FunctionSourceMapDef& function_source_map,
const NameLocationDef& location,
std::ostream* stream) {
ASSIGN_OR_RETURN(auto name, source_map.GetUniqueString(location.name()));
*stream << "\"" << name << "\"";
return OkStatus();
}
Status PrintCallSiteLocation(const SourceMap& source_map,
const FunctionSourceMapDef& function_source_map,
const CallSiteLocationDef& location,
std::ostream* stream) {
*stream << "(callsites todo)";
return OkStatus();
}
Status PrintFusedLocation(const SourceMap& source_map,
const FunctionSourceMapDef& function_source_map,
const FusedLocationDef& location,
std::ostream* stream) {
*stream << "fused[";
if (location.locations()) {
for (int i = 0; i < location.locations()->size(); ++i) {
if (i > 0) *stream << ", ";
int location_ordinal = location.locations()->Get(i);
const auto& child_location =
*function_source_map.location_table()->Get(location_ordinal);
RETURN_IF_ERROR(PrintLocation(source_map, function_source_map,
child_location, stream));
}
}
*stream << "]";
return OkStatus();
}
Status PrintLocation(const SourceMap& source_map,
const FunctionSourceMapDef& function_source_map,
const LocationDef& location, std::ostream* stream) {
switch (location.location_union_type()) {
case LocationDefUnion::FileLocationDef:
return PrintFileLocation(source_map, function_source_map,
*location.location_union_as_FileLocationDef(),
stream);
case LocationDefUnion::NameLocationDef:
return PrintNameLocation(source_map, function_source_map,
*location.location_union_as_NameLocationDef(),
stream);
case LocationDefUnion::CallSiteLocationDef:
return PrintCallSiteLocation(
source_map, function_source_map,
*location.location_union_as_CallSiteLocationDef(), stream);
case LocationDefUnion::FusedLocationDef:
return PrintFusedLocation(source_map, function_source_map,
*location.location_union_as_FusedLocationDef(),
stream);
default:
return UnimplementedErrorBuilder(ABSL_LOC)
<< "Unhandled location type "
<< static_cast<int>(location.location_union_type());
}
}
} // namespace
// static
bool SourceLocation::Equal(const SourceLocation& a, const SourceLocation& b) {
return a.source_map_def_ == b.source_map_def_ &&
a.function_source_map_ == b.function_source_map_ &&
a.location_ordinal_ == b.location_ordinal_;
}
std::string SourceLocation::DebugStringShort() const {
if (empty()) {
return "<unknown>";
}
std::ostringstream stream;
const auto& location =
*function_source_map_->location_table()->Get(location_ordinal_);
auto status = PrintLocation(SourceMap(*source_map_def_),
*function_source_map_, location, &stream);
if (!status.ok()) {
stream << status;
}
return stream.str();
}
// static
SourceMap SourceMap::FromModule(const ModuleDef& module_def) {
if (module_def.source_map()) {
return SourceMap{*module_def.source_map()};
}
return {};
}
StatusOr<absl::string_view> SourceMap::GetUniqueString(int string_index) const {
if (empty()) {
return NotFoundErrorBuilder(ABSL_LOC) << "No source map present";
}
const auto* string_table = source_map_def_->string_table();
if (string_table && string_table->size() > string_index) {
return WrapString(string_table->Get(string_index));
}
return NotFoundErrorBuilder(ABSL_LOC)
<< "String index " << string_index << " not present in string table";
}
StatusOr<const FunctionSourceMapDef*> SourceMap::GetFunctionSourceMap(
int function_ordinal) const {
if (empty()) {
return NotFoundErrorBuilder(ABSL_LOC) << "No source map present";
}
const auto* function_table = source_map_def_->function_table();
if (function_table && function_table->size() > function_ordinal) {
const auto* function_source_map = function_table->Get(function_ordinal);
if (function_source_map && function_source_map->location_table() &&
function_source_map->bytecode_map()) {
return function_source_map;
}
}
return NotFoundErrorBuilder(ABSL_LOC)
<< "Function ordinal " << function_ordinal
<< " source map not present in function table";
}
// static
SourceMapResolver SourceMapResolver::FromFunction(const ModuleDef& module_def,
int function_ordinal) {
auto source_map = SourceMap::FromModule(module_def);
if (source_map.empty()) {
return {};
}
auto function_source_map_or =
source_map.GetFunctionSourceMap(function_ordinal);
if (!function_source_map_or.ok()) {
return {};
}
return SourceMapResolver(source_map, *function_source_map_or.ValueOrDie());
}
absl::optional<SourceLocation> SourceMapResolver::ResolveBytecodeOffset(
int offset) const {
if (!function_source_map_) {
return {};
}
const auto* bytecode_map = function_source_map_->bytecode_map();
// TODO(benvanik): allow fuzzy offset matching/table sparsity.
int location_ordinal = -1;
for (const auto* map_loc : *bytecode_map) {
if (map_loc->offset() == offset) {
location_ordinal = map_loc->location();
break;
}
}
if (location_ordinal == -1) {
return {};
}
return SourceLocation(*source_map_.def(), *function_source_map_,
location_ordinal);
}
} // namespace vm
} // namespace iree