blob: 11fe9c6552ccf063fc3f5f833e884b308822b444 [file] [log] [blame]
//===-- go-llvm-linemap.h - Linemap class public interfaces --------------===//
//
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
//===----------------------------------------------------------------------===//
//
// LLVM/go implementation of Linemap class.
//
//===----------------------------------------------------------------------===//
// Implementation notes:
//
// Line/column pairs are ULEB128-encoded and stored in a large array;
// we then hand out the offset of the encoded pair as a handle for use
// in the Location class. The source file for a range of pairs is
// stored in a separate table. This implementation doesn't hash or
// common line/column pairs, meaning that there can be some redundancy
// in the encodings.
//
#ifndef GO_LLVM_LINEMAP_H
#define GO_LLVM_LINEMAP_H
#include "go-linemap.h"
class Llvm_linemap : public Linemap
{
public:
Llvm_linemap();
~Llvm_linemap();
void
start_file(const char* file_name, unsigned int line_begin);
void
start_line(unsigned int line_number, unsigned int line_size);
Location
get_location(unsigned int column);
void
stop();
std::string
to_string(Location);
std::string statistics();
int
location_line(Location);
std::string
location_file(Location);
unsigned
location_column(Location);
// Return first file mentioned in a returned location. This will
// be the empty string if no files have been started.
std::string
get_initial_file();
Location
get_predeclared_location();
Location
get_unknown_location();
bool
is_predeclared(Location);
bool
is_unknown(Location);
static Llvm_linemap*
instance();
private:
// File/line/column container
struct FLC {
unsigned fidx;
unsigned line;
unsigned column;
FLC(unsigned f, unsigned l, unsigned c)
: fidx(f), line(l), column(c)
{ }
};
// Stores the file ID associated with a range of handle
struct Segment {
// lo/hi handles in this range
unsigned lo, hi;
// file id for this collection of handles
unsigned fidx;
Segment(unsigned low, unsigned high, unsigned fileid)
: lo(low), hi(high), fidx(fileid) { }
static bool cmp(const struct Segment &a1, const struct Segment &a2) {
return a1.hi < a2.hi;
}
};
// Given a file/line/column triple, add an entry to the linemap for
// the triple and return a handle for it.
unsigned add_encoded_location(const FLC &flc);
// Given a handle, return the associated file/line/column triple.
FLC decode_location(unsigned handle);
// Debugging
void dump();
void dumpLocation(Location loc);
void dumpHandle(unsigned handle);
private:
// Source files we've seen so far.
std::vector<std::string> files_;
// Maps source file to index in the files_ array.
std::map<std::string, unsigned> fmap_;
// Sorted table of segments, used to record file id for ranges of handles.
std::vector<Segment> segments_;
// Array of ULEB-encoded line/col pairs.
std::vector<unsigned char> encoded_locations_;
// Predefined "unknown file" file ID.
unsigned unknown_fidx_;
// Predefined file ID for predeclared or builtin locations.
unsigned builtin_fidx_;
// Current file ID (most recent file passed to start_file)
unsigned current_fidx_;
// Current line.
unsigned current_line_;
// Special handle for predeclared location.
unsigned builtin_handle_;
// Special handle for unknown location.
unsigned unknown_handle_;
// First handle in the segment we are building (not yet in segment table).
// May be set to NoHandle if there are no locations in the segment yet.
unsigned firsthandle_;
// Last handle in the segment we are building (not yet in segment table).
// May be set to NoHandle if there are no locations in the segment yet.
unsigned lasthandle_;
// Number of lookups made into the linemap.
unsigned lookups_;
// Whether we are currently reading a file.
bool in_file_;
};
// Main hook for linemap creation
extern Linemap *go_get_linemap();
// For unit testing and error reporting
extern Llvm_linemap *go_get_llvm_linemap();
#endif // !defined(GO_LLVM_LINEMAP_H)