mirror of
https://github.com/mrkite/regs.git
synced 2024-11-03 05:04:42 +00:00
144 lines
3.3 KiB
C++
144 lines
3.3 KiB
C++
|
/** @copyright 2020 Sean Kasun */
|
||
|
|
||
|
#include "output.h"
|
||
|
#include <fstream>
|
||
|
|
||
|
void Output::save(const std::map<std::string, Symbol> &symbols,
|
||
|
const std::string &filename) {
|
||
|
std::ofstream f(filename, std::ios::out | std::ios::binary | std::ios::trunc);
|
||
|
if (!f.is_open()) {
|
||
|
std::cerr << "Failed to create " << filename << std::endl;
|
||
|
exit(-1);
|
||
|
}
|
||
|
w32(&f, symbols.size());
|
||
|
uint32_t id = 1;
|
||
|
for (auto it = symbols.begin(); it != symbols.end(); it++) {
|
||
|
w32(&f, id);
|
||
|
w8(&f, it->second.kind);
|
||
|
ws(&f, it->first);
|
||
|
ids[it->first] = id++;
|
||
|
}
|
||
|
for (auto it = symbols.begin(); it != symbols.end(); it++) {
|
||
|
auto symbol = it->second;
|
||
|
w32(&f, lookup(it->first));
|
||
|
w32(&f, symbol.size);
|
||
|
switch (symbol.kind) {
|
||
|
case isIntrinsic:
|
||
|
setIntrinsic(&f, symbol.asIntrinsic);
|
||
|
break;
|
||
|
case isEnum:
|
||
|
setEnum(&f, symbol.asEnum);
|
||
|
break;
|
||
|
case isAlias:
|
||
|
setRef(&f, symbol.asAlias);
|
||
|
break;
|
||
|
case isStruct:
|
||
|
setStruct(&f, symbol.asStruct);
|
||
|
break;
|
||
|
case isUnion:
|
||
|
setStruct(&f, symbol.asStruct);
|
||
|
break;
|
||
|
case isFunction:
|
||
|
setFunction(&f, symbol.asFunction);
|
||
|
break;
|
||
|
default:
|
||
|
std::cerr << "Unknown symbol type" << std::endl;
|
||
|
exit(-1);
|
||
|
}
|
||
|
}
|
||
|
f.close();
|
||
|
}
|
||
|
|
||
|
uint32_t Output::lookup(const std::string &name) const {
|
||
|
return ids.at(name);
|
||
|
}
|
||
|
|
||
|
void Output::w32(std::ostream *f, uint32_t val) {
|
||
|
char buf[4];
|
||
|
buf[0] = val & 0xff;
|
||
|
buf[1] = (val >> 8) & 0xff;
|
||
|
buf[2] = (val >> 16) & 0xff;
|
||
|
buf[3] = (val >> 24) & 0xff;
|
||
|
f->write(buf, 4);
|
||
|
}
|
||
|
|
||
|
void Output::w8(std::ostream *f, uint8_t val) {
|
||
|
char v = val;
|
||
|
f->write(&v, 1);
|
||
|
}
|
||
|
|
||
|
void Output::ws(std::ostream *f, const std::string &val) {
|
||
|
uint8_t len = val.length() > 255 ? 255 : val.length();
|
||
|
char v = len;
|
||
|
f->write(&v, 1);
|
||
|
f->write(val.c_str(), len);
|
||
|
}
|
||
|
|
||
|
void Output::setIntrinsic(std::ostream *f, const Intrinsic i) {
|
||
|
w8(f, i);
|
||
|
}
|
||
|
|
||
|
void Output::setEnum(std::ostream *f, const Enum *e) {
|
||
|
w32(f, lookup(e->type->name));
|
||
|
w32(f, e->entries.size());
|
||
|
for (auto it = e->entries.begin(); it != e->entries.end(); it++) {
|
||
|
w32(f, it->second);
|
||
|
ws(f, it->first);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Output::setRef(std::ostream *f, const Ref *r) {
|
||
|
if (r->symbol == nullptr) {
|
||
|
w32(f, 0);
|
||
|
} else {
|
||
|
w32(f, lookup(r->symbol->name));
|
||
|
w32(f, r->pointer);
|
||
|
w32(f, r->array);
|
||
|
ws(f, r->reg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Output::setStruct(std::ostream *f, const Struct *s) {
|
||
|
w32(f, s->fields.size());
|
||
|
for (auto &field : s->fields) {
|
||
|
setField(f, field);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Output::setFunction(std::ostream *f, const Function *func) {
|
||
|
w32(f, func->arguments.size());
|
||
|
for (auto &arg : func->arguments) {
|
||
|
setArgument(f, arg);
|
||
|
}
|
||
|
setRef(f, &func->retType);
|
||
|
w32(f, func->signature.size());
|
||
|
for (auto sig : func->signature) {
|
||
|
w32(f, sig);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Output::setField(std::ostream *f, const Field &field) {
|
||
|
ws(f, field.key);
|
||
|
w8(f, field.kind);
|
||
|
w32(f, field.size);
|
||
|
switch (field.kind) {
|
||
|
case isRef:
|
||
|
setRef(f, field.ref);
|
||
|
break;
|
||
|
case isStruct:
|
||
|
setStruct(f, field.theStruct);
|
||
|
break;
|
||
|
case isUnion:
|
||
|
setStruct(f, field.theStruct);
|
||
|
break;
|
||
|
default:
|
||
|
std::cerr << "Unknown field type" << std::endl;
|
||
|
exit(-1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Output::setArgument(std::ostream *f, const Argument &a) {
|
||
|
ws(f, a.key);
|
||
|
setRef(f, &a.ref);
|
||
|
}
|