418 lines
11 KiB
C++
418 lines
11 KiB
C++
// export.h -- Export declarations in Go frontend. -*- C++ -*-
|
|
|
|
// Copyright 2009 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.
|
|
|
|
#ifndef GO_EXPORT_H
|
|
#define GO_EXPORT_H
|
|
|
|
#include "string-dump.h"
|
|
|
|
class Go_sha1_helper;
|
|
class Gogo;
|
|
class Named_object;
|
|
class Export_function_body;
|
|
class Import_init;
|
|
class Named_object;
|
|
class Bindings;
|
|
class Type;
|
|
class Package;
|
|
class Import_init_set;
|
|
class Backend;
|
|
class Temporary_statement;
|
|
class Unnamed_label;
|
|
struct Export_impl;
|
|
|
|
// Codes used for the builtin types. These are all negative to make
|
|
// them easily distinct from the codes assigned by Export::write_type.
|
|
// Note that these codes may not be changed! Changing them would
|
|
// break existing export data.
|
|
|
|
enum Builtin_code
|
|
{
|
|
BUILTIN_INT8 = -1,
|
|
BUILTIN_INT16 = -2,
|
|
BUILTIN_INT32 = -3,
|
|
BUILTIN_INT64 = -4,
|
|
BUILTIN_UINT8 = -5,
|
|
BUILTIN_UINT16 = -6,
|
|
BUILTIN_UINT32 = -7,
|
|
BUILTIN_UINT64 = -8,
|
|
BUILTIN_FLOAT32 = -9,
|
|
BUILTIN_FLOAT64 = -10,
|
|
BUILTIN_INT = -11,
|
|
BUILTIN_UINT = -12,
|
|
BUILTIN_UINTPTR = -13,
|
|
BUILTIN_BOOL = -15,
|
|
BUILTIN_STRING = -16,
|
|
BUILTIN_COMPLEX64 = -17,
|
|
BUILTIN_COMPLEX128 = -18,
|
|
BUILTIN_ERROR = -19,
|
|
BUILTIN_BYTE = -20,
|
|
BUILTIN_RUNE = -21,
|
|
|
|
SMALLEST_BUILTIN_CODE = -21
|
|
};
|
|
|
|
// Export data version number. New export data is written with the
|
|
// "current" version, but there is support for reading files with
|
|
// older version export data (at least for now).
|
|
|
|
enum Export_data_version {
|
|
EXPORT_FORMAT_UNKNOWN = 0,
|
|
EXPORT_FORMAT_V1 = 1,
|
|
EXPORT_FORMAT_V2 = 2,
|
|
EXPORT_FORMAT_V3 = 3,
|
|
EXPORT_FORMAT_CURRENT = EXPORT_FORMAT_V3
|
|
};
|
|
|
|
// This class manages exporting Go declarations. It handles the main
|
|
// loop of exporting. A pointer to this class is also passed to the
|
|
// various specific export implementations.
|
|
|
|
class Export : public String_dump
|
|
{
|
|
public:
|
|
// The Stream class is an interface used to output the exported
|
|
// information. The caller should instantiate a child of this
|
|
// class.
|
|
class Stream
|
|
{
|
|
public:
|
|
Stream();
|
|
virtual ~Stream();
|
|
|
|
// Write a string. Implements the String_dump interface.
|
|
void
|
|
write_string(const std::string& s)
|
|
{ this->write_and_sum_bytes(s.data(), s.length()); }
|
|
|
|
// Write a nul terminated string. Implements the String_dump interface.
|
|
void
|
|
write_c_string(const char* s)
|
|
{ this->write_and_sum_bytes(s, strlen(s)); }
|
|
|
|
// Write some bytes.
|
|
void
|
|
write_bytes(const char* bytes, size_t length)
|
|
{ this->write_and_sum_bytes(bytes, length); }
|
|
|
|
// Return the raw bytes of the checksum data.
|
|
std::string
|
|
checksum();
|
|
|
|
// Write a checksum string to the stream. This will be called at
|
|
// the end of the other output.
|
|
void
|
|
write_checksum(const std::string&);
|
|
|
|
protected:
|
|
// This function is called with data to export. This data must be
|
|
// made available as a contiguous stream for the importer.
|
|
virtual void
|
|
do_write(const char* bytes, size_t length) = 0;
|
|
|
|
private:
|
|
void
|
|
write_and_sum_bytes(const char*, size_t);
|
|
|
|
// The checksum helper.
|
|
Go_sha1_helper* sha1_helper_;
|
|
};
|
|
|
|
Export(Stream*);
|
|
~Export();
|
|
|
|
// Size of export data magic string (which includes version number).
|
|
static const int magic_len = 4;
|
|
|
|
// Magic strings (current version and older versions).
|
|
static const char cur_magic[magic_len];
|
|
static const char v1_magic[magic_len];
|
|
static const char v2_magic[magic_len];
|
|
|
|
// The length of the checksum string.
|
|
static const int checksum_len = 20;
|
|
|
|
// Register the builtin types.
|
|
void
|
|
register_builtin_types(Gogo*);
|
|
|
|
// Export the identifiers in BINDINGS which are marked for export.
|
|
// The exporting is done via a series of calls to THIS->STREAM_. If
|
|
// is nothing to export, this->stream_->write will not be called.
|
|
// PREFIX is the package prefix. PKGPATH is the package path.
|
|
// Only one of PREFIX and PKGPATH will be non-empty.
|
|
// PACKAGES is all the packages we have seen.
|
|
// IMPORTS is the explicitly imported packages.
|
|
// IMPORT_INIT_FN is the name of the import initialization function
|
|
// for this package; it will be empty if none is needed.
|
|
// IMPORTED_INIT_FNS is the list of initialization functions for
|
|
// imported packages.
|
|
void
|
|
export_globals(const std::string& package_name,
|
|
const std::string& prefix,
|
|
const std::string& pkgpath,
|
|
const std::map<std::string, Package*>& packages,
|
|
const std::map<std::string, Package*>& imports,
|
|
const std::string& import_init_fn,
|
|
const Import_init_set& imported_init_fns,
|
|
const Bindings* bindings,
|
|
Unordered_set(Named_object*)* marked_inline_functions);
|
|
|
|
// Record a type that is mentioned in export data. Return value is
|
|
// TRUE for newly visited types, FALSE for types that have been seen
|
|
// previously.
|
|
bool
|
|
record_type(Type*);
|
|
|
|
// Assign type indices to types mentioned in export data.
|
|
int
|
|
assign_type_indices(const std::vector<Named_object*>& sorted_exports);
|
|
|
|
// Write a string to the export stream.
|
|
void
|
|
write_string(const std::string& s)
|
|
{ this->stream_->write_string(s); }
|
|
|
|
// Write a nul terminated string to the export stream.
|
|
void
|
|
write_c_string(const char* s)
|
|
{ this->stream_->write_c_string(s); }
|
|
|
|
// Write some bytes to the export stream.
|
|
void
|
|
write_bytes(const char* bytes, size_t length)
|
|
{ this->stream_->write_bytes(bytes, length); }
|
|
|
|
// Write a name to the export stream. If NAME is empty, write "?".
|
|
void
|
|
write_name(const std::string& name);
|
|
|
|
// Write out a type. This handles references back to previous
|
|
// definitions.
|
|
void
|
|
write_type(const Type*);
|
|
|
|
// Write a type to an exported function body.
|
|
void
|
|
write_type_to(const Type*, Export_function_body*);
|
|
|
|
// Write the escape note to the export stream. If NOTE is NULL, write
|
|
// nothing.
|
|
void
|
|
write_escape(std::string* note);
|
|
|
|
// Write an integer value.
|
|
void
|
|
write_int(int);
|
|
|
|
// Write an unsigned value.
|
|
void
|
|
write_unsigned(unsigned);
|
|
|
|
// Return the index of a package.
|
|
int
|
|
package_index(const Package* p) const;
|
|
|
|
private:
|
|
Export(const Export&);
|
|
Export& operator=(const Export&);
|
|
|
|
// Write out all known packages.
|
|
void
|
|
write_packages(const std::map<std::string, Package*>& packages);
|
|
|
|
typedef std::map<unsigned, std::set<unsigned> > Init_graph;
|
|
|
|
static void
|
|
add_init_graph_edge(Init_graph* init_graph, unsigned src, unsigned sink);
|
|
|
|
static void
|
|
populate_init_graph(Init_graph* init_graph,
|
|
const Import_init_set& imported_init_fns,
|
|
const std::map<std::string, unsigned>& init_idx);
|
|
|
|
// Write out the imported packages.
|
|
void
|
|
write_imports(const std::map<std::string, Package*>& imports,
|
|
const Unordered_set(const Package*)& type_imports);
|
|
|
|
// Write out the imported initialization functions and init graph.
|
|
void
|
|
write_imported_init_fns(const std::string& package_name,
|
|
const std::string&, const Import_init_set&);
|
|
|
|
// Write out all types.
|
|
void
|
|
write_types(int unexported_type_index);
|
|
|
|
// Write out one type definition.
|
|
void
|
|
write_type_definition(const Type* type, int index);
|
|
|
|
// Register one builtin type.
|
|
void
|
|
register_builtin_type(Gogo*, const char* name, Builtin_code);
|
|
|
|
// Return the index of a type in the export data.
|
|
int
|
|
type_index(const Type*);
|
|
|
|
// Set the index of a type.
|
|
void
|
|
set_type_index(const Type*);
|
|
|
|
// The stream to which we are writing data.
|
|
Stream* stream_;
|
|
// Index number of next type.
|
|
int type_index_;
|
|
// Packages we have written out.
|
|
Unordered_map(const Package*, int) packages_;
|
|
// Hidden implementation-specific state.
|
|
Export_impl* impl_;
|
|
};
|
|
|
|
// An export streamer that puts the export stream in a named section.
|
|
|
|
class Stream_to_section : public Export::Stream
|
|
{
|
|
public:
|
|
Stream_to_section(Backend*);
|
|
|
|
protected:
|
|
void
|
|
do_write(const char*, size_t);
|
|
|
|
private:
|
|
Backend* backend_;
|
|
};
|
|
|
|
// An export streamer that puts the export stream in a string.
|
|
|
|
class Stream_to_string : public Export::Stream
|
|
{
|
|
public:
|
|
Stream_to_string()
|
|
: string_()
|
|
{}
|
|
|
|
const std::string&
|
|
string() const
|
|
{ return this->string_; }
|
|
|
|
protected:
|
|
void
|
|
do_write(const char* s, size_t len)
|
|
{ this->string_.append(s, len); }
|
|
|
|
private:
|
|
std::string string_;
|
|
};
|
|
|
|
// Class to manage exporting a function body. This is passed around
|
|
// to Statements and Expressions. It builds up the export data for
|
|
// the function.
|
|
|
|
class Export_function_body : public String_dump
|
|
{
|
|
public:
|
|
Export_function_body(Export* exp, int indent)
|
|
: exp_(exp), body_(), type_context_(NULL), next_temporary_index_(0),
|
|
temporary_indexes_(), next_label_index_(0), label_indexes_(),
|
|
indent_(indent)
|
|
{ }
|
|
|
|
// Write a character to the body.
|
|
void
|
|
write_char(char c)
|
|
{ this->body_.append(1, c); }
|
|
|
|
// Write a NUL terminated string to the body.
|
|
void
|
|
write_c_string(const char* str)
|
|
{ this->body_.append(str); }
|
|
|
|
// Write a string to the body.
|
|
void
|
|
write_string(const std::string& str)
|
|
{ this->body_.append(str); }
|
|
|
|
// Write a type reference to the body.
|
|
void
|
|
write_type(const Type* type)
|
|
{ this->exp_->write_type_to(type, this); }
|
|
|
|
// Return the current type context.
|
|
Type*
|
|
type_context() const
|
|
{ return this->type_context_; }
|
|
|
|
// Set the current type context.
|
|
void
|
|
set_type_context(Type* type)
|
|
{ this->type_context_ = type; }
|
|
|
|
// Append as many spaces as the current indentation level.
|
|
void
|
|
indent()
|
|
{
|
|
for (int i = this->indent_; i > 0; i--)
|
|
this->write_char(' ');
|
|
}
|
|
|
|
// Increment the indentation level.
|
|
void
|
|
increment_indent()
|
|
{ ++this->indent_; }
|
|
|
|
// Decrement the indentation level.
|
|
void
|
|
decrement_indent()
|
|
{ --this->indent_; }
|
|
|
|
// Return the index of a package.
|
|
int
|
|
package_index(const Package* p) const
|
|
{ return this->exp_->package_index(p); }
|
|
|
|
// Record a temporary statement and return its index.
|
|
unsigned int
|
|
record_temporary(const Temporary_statement*);
|
|
|
|
// Return the index of a temporary statement.
|
|
unsigned int
|
|
temporary_index(const Temporary_statement*);
|
|
|
|
// Return the index of an unnamed label. If it doesn't already have
|
|
// an index, give it one.
|
|
unsigned int
|
|
unnamed_label_index(const Unnamed_label*);
|
|
|
|
// Return a reference to the completed body.
|
|
const std::string&
|
|
body() const
|
|
{ return this->body_; }
|
|
|
|
private:
|
|
// The overall export data.
|
|
Export* exp_;
|
|
// The body we are building.
|
|
std::string body_;
|
|
// Current type context. Used to avoid duplicate type conversions.
|
|
Type* type_context_;
|
|
// Index to give to next temporary statement.
|
|
unsigned int next_temporary_index_;
|
|
// Map temporary statements to indexes.
|
|
Unordered_map(const Temporary_statement*, unsigned int) temporary_indexes_;
|
|
// Index to give to the next unnamed label.
|
|
unsigned int next_label_index_;
|
|
// Map unnamed labels to indexes.
|
|
Unordered_map(const Unnamed_label*, unsigned int) label_indexes_;
|
|
// Current indentation level: the number of spaces before each statement.
|
|
int indent_;
|
|
};
|
|
|
|
#endif // !defined(GO_EXPORT_H)
|