Add debug info tables to smxbuilder.
This commit is contained in:
parent
c4056aea5d
commit
98ec07a419
@ -22,7 +22,16 @@
|
||||
#include <am-utility.h>
|
||||
#include "smx-builder.h"
|
||||
|
||||
class MemoryBuffer : public ke::ISmxBuffer
|
||||
// Interface for SmxBuilder to blit bytes.
|
||||
class ISmxBuffer
|
||||
{
|
||||
public:
|
||||
virtual bool write(const void *bytes, size_t len) = 0;
|
||||
virtual size_t pos() const = 0;
|
||||
};
|
||||
|
||||
// An in-memory buffer for SmxBuilder.
|
||||
class MemoryBuffer : public ISmxBuffer
|
||||
{
|
||||
static const size_t kDefaultSize = 4096;
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
||||
using namespace sp;
|
||||
using namespace ke;
|
||||
|
||||
static void append_dbginfo(void *fout);
|
||||
static void append_debug_Tables(SmxBuilder *builder);
|
||||
|
||||
typedef cell (*OPCODE_PROC)(Vector<cell> *buffer, char *params, cell opcode);
|
||||
|
||||
@ -615,10 +615,173 @@ static int sort_by_addr(const void *a1, const void *a2)
|
||||
return s1->addr - s2->addr;
|
||||
}
|
||||
|
||||
// Helper for parsing a debug string. Debug strings look like this:
|
||||
// L:40 10
|
||||
class DebugString
|
||||
{
|
||||
public:
|
||||
DebugString() : kind_('\0'), str_(nullptr)
|
||||
{ }
|
||||
DebugString(char *str)
|
||||
: kind_(str[0]),
|
||||
str_(str)
|
||||
{
|
||||
assert(str_[1] == ':');
|
||||
str_ += 2;
|
||||
}
|
||||
char kind() const {
|
||||
return kind_;
|
||||
}
|
||||
ucell parse() {
|
||||
return hex2long(str_, &str_);
|
||||
}
|
||||
char *skipspaces() {
|
||||
str_ = ::skipwhitespace(str_);
|
||||
return str_;
|
||||
}
|
||||
void expect(char c) {
|
||||
assert(*str_ == c);
|
||||
str_++;
|
||||
}
|
||||
char *skipto(char c) {
|
||||
str_ = strchr(str_, c);
|
||||
return str_;
|
||||
}
|
||||
char getc() {
|
||||
return *str_++;
|
||||
}
|
||||
|
||||
private:
|
||||
char kind_;
|
||||
char *str_;
|
||||
};
|
||||
|
||||
typedef SmxBlobSection<sp_fdbg_info_t> SmxDebugInfoSection;
|
||||
typedef SmxListSection<sp_fdbg_line_t> SmxDebugLineSection;
|
||||
typedef SmxListSection<sp_fdbg_file_t> SmxDebugFileSection;
|
||||
typedef SmxListSection<sp_file_tag_t> SmxTagSection;
|
||||
typedef SmxBlobSection<void> SmxDebugSymbolsSection;
|
||||
|
||||
static void append_debug_tables(SmxBuilder *builder, StringPool &pool)
|
||||
{
|
||||
// We use a separate name table for historical reasons that are no longer
|
||||
// necessary. In the future we should just alias this to ".names".
|
||||
Ref<SmxNameTable> names = new SmxNameTable(".dbg.strings");
|
||||
Ref<SmxDebugInfoSection> info = new SmxDebugInfoSection(".dbg.info");
|
||||
Ref<SmxDebugLineSection> lines = new SmxDebugLineSection(".dbg.lines");
|
||||
Ref<SmxDebugFileSection> files = new SmxDebugFileSection(".dbg.files");
|
||||
Ref<SmxDebugSymbolsSection> symbols = new SmxDebugSymbolsSection(".dbg.symbols");
|
||||
Ref<SmxTagSection> tags = new SmxTagSection(".tags");
|
||||
|
||||
stringlist *dbgstrs = get_dbgstrings();
|
||||
|
||||
// State for tracking which file we're on. We replicate the original AMXDBG
|
||||
// behavior here which excludes duplicate addresses.
|
||||
ucell prev_file_addr = 0;
|
||||
const char *prev_file_name = nullptr;
|
||||
|
||||
// Add debug data.
|
||||
for (stringlist *iter = dbgstrs; iter; iter = iter->next) {
|
||||
if (iter->line[0] == '\0')
|
||||
continue;
|
||||
|
||||
DebugString str(iter->line);
|
||||
switch (str.kind()) {
|
||||
case 'F':
|
||||
{
|
||||
ucell codeidx = str.parse();
|
||||
if (codeidx != prev_file_addr) {
|
||||
if (prev_file_name) {
|
||||
sp_fdbg_file_t &entry = files->add();
|
||||
entry.addr = prev_file_addr;
|
||||
entry.name = names->add(pool, prev_file_name);
|
||||
}
|
||||
prev_file_addr = codeidx;
|
||||
}
|
||||
prev_file_name = str.skipspaces();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'L':
|
||||
{
|
||||
sp_fdbg_line_t &entry = lines->add();
|
||||
entry.addr = str.parse();
|
||||
entry.line = str.parse();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'S':
|
||||
{
|
||||
sp_fdbg_symbol_t sym;
|
||||
sp_fdbg_arraydim_t dims[sDIMEN_MAX];
|
||||
|
||||
sym.addr = str.parse();
|
||||
sym.tagid = str.parse();
|
||||
|
||||
str.skipspaces();
|
||||
str.expect(':');
|
||||
char *name = str.skipspaces();
|
||||
char *nameend = str.skipto(' ');
|
||||
Atom *atom = pool.add(name, nameend - name);
|
||||
|
||||
sym.codestart = str.parse();
|
||||
sym.codeend = str.parse();
|
||||
sym.ident = (char)str.parse();
|
||||
sym.vclass = (char)str.parse();
|
||||
sym.dimcount = 0;
|
||||
sym.name = names->add(atom);
|
||||
|
||||
info->header().num_syms++;
|
||||
|
||||
str.skipspaces();
|
||||
if (str.getc() == '[') {
|
||||
info->header().num_arrays++;
|
||||
for (char *ptr = str.skipspaces(); *ptr != ']'; ptr = str.skipspaces()) {
|
||||
dims[sym.dimcount].tagid = str.parse();
|
||||
str.skipspaces();
|
||||
str.expect(':');
|
||||
dims[sym.dimcount].size = str.parse();
|
||||
sym.dimcount++;
|
||||
}
|
||||
}
|
||||
|
||||
symbols->add(&sym, sizeof(sym));
|
||||
symbols->add(dims, sizeof(dims[0]) * sym.dimcount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the last file.
|
||||
if (prev_file_name) {
|
||||
sp_fdbg_file_t &entry = files->add();
|
||||
entry.addr = prev_file_addr;
|
||||
entry.name = names->add(pool, prev_file_name);
|
||||
}
|
||||
|
||||
// Build the tags table.
|
||||
for (constvalue *constptr = tagname_tab.next; constptr; constptr = constptr->next) {
|
||||
assert(strlen(constptr->name)>0);
|
||||
|
||||
sp_file_tag_t &tag = tags->add();
|
||||
tag.tag_id = constptr->value;
|
||||
tag.name = names->add(pool, constptr->name);
|
||||
}
|
||||
|
||||
info->header().num_files = files->count();
|
||||
info->header().num_lines = lines->count();
|
||||
|
||||
builder->add(files);
|
||||
builder->add(symbols);
|
||||
builder->add(lines);
|
||||
builder->add(names);
|
||||
builder->add(info);
|
||||
builder->add(tags);
|
||||
}
|
||||
|
||||
typedef SmxListSection<sp_file_natives_t> SmxNativeSection;
|
||||
typedef SmxListSection<sp_file_publics_t> SmxPublicSection;
|
||||
typedef SmxListSection<sp_file_pubvars_t> SmxPubvarSection;
|
||||
typedef SmxListSection<sp_file_tag_t> SmxTagSection;
|
||||
typedef SmxBlobSection<sp_file_data_t> SmxDataSection;
|
||||
typedef SmxBlobSection<sp_file_code_t> SmxCodeSection;
|
||||
|
||||
@ -629,7 +792,6 @@ static void assemble_to_buffer(MemoryBuffer *buffer, void *fin)
|
||||
Ref<SmxNativeSection> natives = new SmxNativeSection(".natives");
|
||||
Ref<SmxPublicSection> publics = new SmxPublicSection(".publics");
|
||||
Ref<SmxPubvarSection> pubvars = new SmxPubvarSection(".pubvars");
|
||||
Ref<SmxTagSection> tags = new SmxTagSection(".tags");
|
||||
Ref<SmxDataSection> data = new SmxDataSection(".data");
|
||||
Ref<SmxCodeSection> code = new SmxCodeSection(".code");
|
||||
Ref<SmxNameTable> names = new SmxNameTable(".names");
|
||||
@ -656,15 +818,6 @@ static void assemble_to_buffer(MemoryBuffer *buffer, void *fin)
|
||||
}
|
||||
}
|
||||
|
||||
// Build the tags table.
|
||||
for (constvalue *constptr = tagname_tab.next; constptr; constptr = constptr->next) {
|
||||
assert(strlen(constptr->name)>0);
|
||||
|
||||
sp_file_tag_t &tag = tags->add();
|
||||
tag.tag_id = constptr->value;
|
||||
tag.name = names->add(pool, constptr->name);
|
||||
}
|
||||
|
||||
// Shuffle natives to be in address order.
|
||||
qsort(nativeList.buffer(), nativeList.length(), sizeof(symbol *), sort_by_addr);
|
||||
for (size_t i = 0; i < nativeList.length(); i++) {
|
||||
@ -719,7 +872,8 @@ static void assemble_to_buffer(MemoryBuffer *buffer, void *fin)
|
||||
builder.add(pubvars);
|
||||
builder.add(natives);
|
||||
builder.add(names);
|
||||
builder.add(tags);
|
||||
append_debug_tables(&builder, pool);
|
||||
|
||||
builder.write(buffer);
|
||||
}
|
||||
|
||||
@ -775,225 +929,3 @@ void assemble(const char *binfname, void *fin)
|
||||
|
||||
splat_to_binary(binfname, buffer.bytes(), buffer.size());
|
||||
}
|
||||
|
||||
int pc_writebin(void *handle,void *buffer,int size) {
|
||||
assert(false);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void append_dbginfo(void *fout)
|
||||
{
|
||||
AMX_DBG_HDR dbghdr;
|
||||
AMX_DBG_LINE dbgline;
|
||||
AMX_DBG_SYMBOL dbgsym;
|
||||
AMX_DBG_SYMDIM dbgidxtag[sDIMEN_MAX];
|
||||
int dim,dbgsymdim;
|
||||
char *str,*prevstr,*name,*prevname;
|
||||
ucell codeidx,previdx;
|
||||
constvalue *constptr;
|
||||
char symname[2*sNAMEMAX+16];
|
||||
int16_t id1,id2;
|
||||
ucell address;
|
||||
stringlist *dbgstrs = get_dbgstrings();
|
||||
stringlist *iter;
|
||||
|
||||
/* header with general information */
|
||||
memset(&dbghdr, 0, sizeof dbghdr);
|
||||
dbghdr.size=sizeof dbghdr;
|
||||
dbghdr.magic=AMX_DBG_MAGIC;
|
||||
dbghdr.file_version=CUR_FILE_VERSION;
|
||||
dbghdr.amx_version=MIN_AMX_VERSION;
|
||||
|
||||
dbgstrs=dbgstrs->next;
|
||||
|
||||
/* first pass: collect the number of items in various tables */
|
||||
|
||||
/* file table */
|
||||
previdx=0;
|
||||
prevstr=NULL;
|
||||
prevname=NULL;
|
||||
for (iter=dbgstrs; iter!=NULL; iter=iter->next) {
|
||||
str = iter->line;
|
||||
assert(str!=NULL);
|
||||
assert(str[0]!='\0' && str[1]==':');
|
||||
if (str[0]=='F') {
|
||||
codeidx=hex2long(str+2,&name);
|
||||
if (codeidx!=previdx) {
|
||||
if (prevstr!=NULL) {
|
||||
assert(prevname!=NULL);
|
||||
dbghdr.files++;
|
||||
dbghdr.size+=sizeof(cell)+strlen(prevname)+1;
|
||||
} /* if */
|
||||
previdx=codeidx;
|
||||
} /* if */
|
||||
prevstr=str;
|
||||
prevname=skipwhitespace(name);
|
||||
} /* if */
|
||||
} /* for */
|
||||
if (prevstr!=NULL) {
|
||||
assert(prevname!=NULL);
|
||||
dbghdr.files++;
|
||||
dbghdr.size+=sizeof(cell)+strlen(prevname)+1;
|
||||
} /* if */
|
||||
|
||||
/* line number table */
|
||||
for (iter=dbgstrs; iter!=NULL; iter=iter->next) {
|
||||
str = iter->line;
|
||||
assert(str!=NULL);
|
||||
assert(str[0]!='\0' && str[1]==':');
|
||||
if (str[0]=='L') {
|
||||
dbghdr.lines++;
|
||||
dbghdr.size+=sizeof(AMX_DBG_LINE);
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
/* symbol table */
|
||||
for (iter=dbgstrs; iter!=NULL; iter=iter->next) {
|
||||
str = iter->line;
|
||||
assert(str!=NULL);
|
||||
assert(str[0]!='\0' && str[1]==':');
|
||||
if (str[0]=='S') {
|
||||
dbghdr.symbols++;
|
||||
name=strchr(str+2,':');
|
||||
assert(name!=NULL);
|
||||
dbghdr.size+=sizeof(AMX_DBG_SYMBOL)+strlen(skipwhitespace(name+1));
|
||||
if ((prevstr=strchr(name,'['))!=NULL)
|
||||
while ((prevstr=strchr(prevstr+1,':'))!=NULL)
|
||||
dbghdr.size+=sizeof(AMX_DBG_SYMDIM);
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
/* tag table */
|
||||
for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
|
||||
assert(strlen(constptr->name)>0);
|
||||
dbghdr.tags++;
|
||||
dbghdr.size+=sizeof(AMX_DBG_TAG)+strlen(constptr->name);
|
||||
} /* for */
|
||||
|
||||
/* automaton table */
|
||||
for (constptr=sc_automaton_tab.next; constptr!=NULL; constptr=constptr->next) {
|
||||
assert((constptr->index==0 && strlen(constptr->name)==0) || strlen(constptr->name)>0);
|
||||
dbghdr.automatons++;
|
||||
dbghdr.size+=sizeof(AMX_DBG_MACHINE)+strlen(constptr->name);
|
||||
} /* for */
|
||||
|
||||
/* state table */
|
||||
for (constptr=sc_state_tab.next; constptr!=NULL; constptr=constptr->next) {
|
||||
assert(strlen(constptr->name)>0);
|
||||
dbghdr.states++;
|
||||
dbghdr.size+=sizeof(AMX_DBG_STATE)+strlen(constptr->name);
|
||||
} /* for */
|
||||
|
||||
|
||||
/* pass 2: generate the tables */
|
||||
writeerror |= !pc_writebin(fout,&dbghdr,sizeof dbghdr);
|
||||
|
||||
/* file table */
|
||||
previdx=0;
|
||||
prevstr=NULL;
|
||||
prevname=NULL;
|
||||
for (iter=dbgstrs; iter!=NULL; iter=iter->next) {
|
||||
str = iter->line;
|
||||
assert(str[0]!='\0' && str[1]==':');
|
||||
if (str[0]=='F') {
|
||||
codeidx=hex2long(str+2,&name);
|
||||
if (codeidx!=previdx) {
|
||||
if (prevstr!=NULL) {
|
||||
assert(prevname!=NULL);
|
||||
writeerror |= !pc_writebin(fout,&previdx,sizeof previdx);
|
||||
writeerror |= !pc_writebin(fout,prevname,strlen(prevname)+1);
|
||||
} /* if */
|
||||
previdx=codeidx;
|
||||
} /* if */
|
||||
prevstr=str;
|
||||
prevname=skipwhitespace(name);
|
||||
} /* if */
|
||||
} /* for */
|
||||
if (prevstr!=NULL) {
|
||||
assert(prevname!=NULL);
|
||||
writeerror |= !pc_writebin(fout,&previdx,sizeof previdx);
|
||||
writeerror |= !pc_writebin(fout,prevname,strlen(prevname)+1);
|
||||
} /* if */
|
||||
|
||||
/* line number table */
|
||||
for (iter=dbgstrs; iter!=NULL; iter=iter->next) {
|
||||
str = iter->line;
|
||||
assert(str!=NULL);
|
||||
assert(str[0]!='\0' && str[1]==':');
|
||||
if (str[0]=='L') {
|
||||
dbgline.address=hex2long(str+2,&str);
|
||||
dbgline.line=(int32_t)hex2long(str,NULL);
|
||||
writeerror |= !pc_writebin(fout,&dbgline,sizeof dbgline);
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
/* symbol table */
|
||||
for (iter=dbgstrs; iter!=NULL; iter=iter->next) {
|
||||
str = iter->line;
|
||||
assert(str!=NULL);
|
||||
assert(str[0]!='\0' && str[1]==':');
|
||||
if (str[0]=='S') {
|
||||
dbgsym.address=hex2long(str+2,&str);
|
||||
dbgsym.tag=(int16_t)hex2long(str,&str);
|
||||
str=skipwhitespace(str);
|
||||
assert(*str==':');
|
||||
name=skipwhitespace(str+1);
|
||||
str=strchr(name,' ');
|
||||
assert(str!=NULL);
|
||||
assert((int)(str-name)<sizeof symname);
|
||||
strlcpy(symname,name,(int)(str-name)+1);
|
||||
dbgsym.codestart=hex2long(str,&str);
|
||||
dbgsym.codeend=hex2long(str,&str);
|
||||
dbgsym.ident=(char)hex2long(str,&str);
|
||||
dbgsym.vclass=(char)hex2long(str,&str);
|
||||
dbgsym.dim=0;
|
||||
str=skipwhitespace(str);
|
||||
if (*str=='[') {
|
||||
while (*(str=skipwhitespace(str+1))!=']') {
|
||||
dbgidxtag[dbgsym.dim].tag=(int16_t)hex2long(str,&str);
|
||||
str=skipwhitespace(str);
|
||||
assert(*str==':');
|
||||
dbgidxtag[dbgsym.dim].size=hex2long(str+1,&str);
|
||||
dbgsym.dim++;
|
||||
} /* while */
|
||||
} /* if */
|
||||
dbgsymdim = dbgsym.dim;
|
||||
writeerror |= !pc_writebin(fout,&dbgsym,offsetof(AMX_DBG_SYMBOL, name));
|
||||
writeerror |= !pc_writebin(fout,symname,strlen(symname)+1);
|
||||
for (dim=0; dim<dbgsymdim; dim++) {
|
||||
writeerror |= !pc_writebin(fout,&dbgidxtag[dim],sizeof dbgidxtag[dim]);
|
||||
} /* for */
|
||||
} /* if */
|
||||
} /* for */
|
||||
|
||||
/* tag table */
|
||||
for (constptr=tagname_tab.next; constptr!=NULL; constptr=constptr->next) {
|
||||
assert(strlen(constptr->name)>0);
|
||||
id1=(int16_t)(constptr->value & TAGMASK);
|
||||
writeerror |= !pc_writebin(fout,&id1,sizeof id1);
|
||||
writeerror |= !pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
|
||||
} /* for */
|
||||
|
||||
/* automaton table */
|
||||
for (constptr=sc_automaton_tab.next; constptr!=NULL; constptr=constptr->next) {
|
||||
assert((constptr->index==0 && strlen(constptr->name)==0) || strlen(constptr->name)>0);
|
||||
id1=(int16_t)constptr->index;
|
||||
address=(ucell)constptr->value;
|
||||
writeerror |= !pc_writebin(fout,&id1,sizeof id1);
|
||||
writeerror |= !pc_writebin(fout,&address,sizeof address);
|
||||
writeerror |= !pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
|
||||
} /* for */
|
||||
|
||||
/* state table */
|
||||
for (constptr=sc_state_tab.next; constptr!=NULL; constptr=constptr->next) {
|
||||
assert(strlen(constptr->name)>0);
|
||||
id1=(int16_t)constptr->value;
|
||||
id2=(int16_t)constptr->index;
|
||||
address=(ucell)constptr->value;
|
||||
writeerror |= !pc_writebin(fout,&id1,sizeof id1);
|
||||
writeerror |= !pc_writebin(fout,&id2,sizeof id2);
|
||||
writeerror |= !pc_writebin(fout,constptr->name,strlen(constptr->name)+1);
|
||||
} /* for */
|
||||
|
||||
delete_dbgstringtable();
|
||||
}
|
||||
|
@ -24,16 +24,11 @@
|
||||
#include <am-refcounting.h>
|
||||
#include <smx/smx-headers.h>
|
||||
#include "string-pool.h"
|
||||
#include "memory-buffer.h"
|
||||
|
||||
namespace ke {
|
||||
|
||||
class ISmxBuffer
|
||||
{
|
||||
public:
|
||||
virtual bool write(const void *bytes, size_t len) = 0;
|
||||
virtual size_t pos() const = 0;
|
||||
};
|
||||
|
||||
// An SmxSection is a named blob of data.
|
||||
class SmxSection : public Refcounted<SmxSection>
|
||||
{
|
||||
public:
|
||||
@ -53,13 +48,19 @@ class SmxSection : public Refcounted<SmxSection>
|
||||
AString name_;
|
||||
};
|
||||
|
||||
// An SmxBlobSection is a section that has some kind of header structure
|
||||
// (specified as a template parameter), and then an arbitrary run of bytes
|
||||
// immediately after.
|
||||
template <typename T>
|
||||
class SmxBlobSection : public SmxSection
|
||||
{
|
||||
public:
|
||||
SmxBlobSection(const char *name)
|
||||
: SmxSection(name)
|
||||
: SmxSection(name),
|
||||
extra_(nullptr),
|
||||
extra_len_(0)
|
||||
{
|
||||
memset(&t_, 0, sizeof(t_));
|
||||
}
|
||||
|
||||
T &header() {
|
||||
@ -72,6 +73,8 @@ class SmxBlobSection : public SmxSection
|
||||
bool write(ISmxBuffer *buf) KE_OVERRIDE {
|
||||
if (!buf->write(&t_, sizeof(t_)))
|
||||
return false;
|
||||
if (!extra_len_)
|
||||
return true;
|
||||
return buf->write(extra_, extra_len_);
|
||||
}
|
||||
size_t length() const KE_OVERRIDE {
|
||||
@ -84,6 +87,32 @@ class SmxBlobSection : public SmxSection
|
||||
size_t extra_len_;
|
||||
};
|
||||
|
||||
// An SmxBlobSection without headers.
|
||||
template <>
|
||||
class SmxBlobSection<void> : public SmxSection
|
||||
{
|
||||
public:
|
||||
SmxBlobSection(const char *name)
|
||||
: SmxSection(name)
|
||||
{
|
||||
}
|
||||
|
||||
void add(void *bytes, size_t len) {
|
||||
buffer_.write(bytes, len);
|
||||
}
|
||||
bool write(ISmxBuffer *buf) KE_OVERRIDE {
|
||||
return buf->write(buffer_.bytes(), buffer_.size());
|
||||
}
|
||||
size_t length() const KE_OVERRIDE {
|
||||
return buffer_.size();
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryBuffer buffer_;
|
||||
};
|
||||
|
||||
// An SmxListSection is a section that is a simple table of uniformly-sized
|
||||
// structures. It has no header of its own.
|
||||
template <typename T>
|
||||
class SmxListSection : public SmxSection
|
||||
{
|
||||
@ -104,18 +133,23 @@ class SmxListSection : public SmxSection
|
||||
return buf->write(list_.buffer(), list_.length() * sizeof(T));
|
||||
}
|
||||
size_t length() const KE_OVERRIDE {
|
||||
return list_.length() * sizeof(T);
|
||||
return count() * sizeof(T);
|
||||
}
|
||||
size_t count() const {
|
||||
return list_.length();
|
||||
}
|
||||
|
||||
private:
|
||||
Vector<T> list_;
|
||||
};
|
||||
|
||||
// A name table is a blob of zero-terminated strings. Strings are entered
|
||||
// into the table as atoms, so duplicate stings are not emitted.
|
||||
class SmxNameTable : public SmxSection
|
||||
{
|
||||
public:
|
||||
SmxNameTable(const char *name)
|
||||
: SmxSection(".names"),
|
||||
: SmxSection(name),
|
||||
buffer_size_(0)
|
||||
{
|
||||
name_table_.init(64);
|
||||
|
@ -19,14 +19,19 @@
|
||||
#ifndef _include_jitcraft_string_pool_h_
|
||||
#define _include_jitcraft_string_pool_h_
|
||||
|
||||
// string-pool is a collection of helpers to atomize/internalize strings. The
|
||||
// StringPool class provides Atom objects which can be used for efficiently
|
||||
// handling string sets or dictionaries.
|
||||
|
||||
#include <am-hashtable.h>
|
||||
#include <am-string.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace ke {
|
||||
|
||||
// Wrapper around AString, since we might want to remove charfs() in a GC-safe
|
||||
// implementation.
|
||||
// An Atom is a string that has a unique instance. That is, any Atom("a") is
|
||||
// guaranteed to be pointer-equivalent to another Atom("a"), as long as they
|
||||
// originated from the same StringPool.
|
||||
class Atom
|
||||
{
|
||||
friend class StringPool;
|
||||
@ -49,6 +54,7 @@ class Atom
|
||||
AString str_;
|
||||
};
|
||||
|
||||
// Helper class to use as a key for hash table lookups.
|
||||
class CharsAndLength
|
||||
{
|
||||
public:
|
||||
@ -76,6 +82,7 @@ class CharsAndLength
|
||||
size_t length_;
|
||||
};
|
||||
|
||||
// Atom dictionary.
|
||||
class StringPool
|
||||
{
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user