Make Destructor Offset Code Less Dumb

This commit is contained in:
TheBrokenRail 2024-05-03 01:13:51 -04:00
parent 83b7e6db98
commit dcc35de95c
2 changed files with 43 additions and 28 deletions

View File

@ -12,7 +12,6 @@ export class Struct {
readonly #dependencies: string[];
readonly #staticProperties: StaticProperty[];
#directParent: string | null;
#vtableDestructorOffset: number;
// Constructor
constructor(name: string) {
@ -24,7 +23,6 @@ export class Struct {
this.#dependencies = [];
this.#staticProperties = [];
this.#directParent = null;
this.#vtableDestructorOffset = 0;
}
// Dependencies
@ -38,17 +36,15 @@ export class Struct {
// Ensure VTable Exists
ensureVTable() {
if (this.#vtable === null) {
this.#vtable = new VTable(this.#name, this.#vtableDestructorOffset);
this.#vtable = new VTable(this.#name);
this.addProperty(this.#vtable.property);
}
}
// Set VTable Destructor Offset
setVTableDestructorOffset(offset: number) {
if (this.#vtable) {
throw new Error('VTable Already Created');
}
this.#vtableDestructorOffset = offset;
this.ensureVTable();
this.#vtable!.setDestructorOffset(offset);
}
// Setters

View File

@ -3,25 +3,22 @@ import { Method } from './method';
import { Property } from './property';
export class VTable {
readonly #name: string;
readonly #self: string;
#address: number | null;
#size: number | null;
readonly #methods: Method[];
readonly property: Property;
#destructorOffset: number;
// Constructor
constructor(name: string, destructorOffset: number) {
this.#name = name;
constructor(self: string) {
this.#self = self;
this.#address = null;
this.#size = null;
this.#methods = [];
// Add Destructors (https://stackoverflow.com/a/17960941)
const destructor_return = `${name} *`;
const destructor_args = `(${getSelfArg(name)})`;
this.add(new Method(name, 'destructor_complete', destructor_return, destructor_args, 0x0 + destructorOffset, false));
this.add(new Method(name, 'destructor_deleting', destructor_return, destructor_args, 0x4 + destructorOffset, false));
this.#destructorOffset = 0;
// Create Property
this.property = new Property(0, this.#getName() + ' *', 'vtable', this.#name);
this.property = new Property(0, this.#getName() + ' *', 'vtable', this.#self);
}
// Setters
@ -31,9 +28,12 @@ export class VTable {
setSize(size: number) {
this.#size = size;
}
setDestructorOffset(destructorOffset: number) {
this.#destructorOffset = destructorOffset;
}
// Add To VTable
add(method: Method) {
#add(target: Method[], method: Method) {
// Check Offset
const offset = method.address;
if ((offset % POINTER_SIZE) !== 0) {
@ -41,15 +41,18 @@ export class VTable {
}
// Add
const index = offset / POINTER_SIZE;
if (this.#methods[index]) {
if (target[index]) {
throw new Error(`Duplicate Virtual Method At Offset: ${toHex(offset)}`);
}
this.#methods[index] = method;
target[index] = method;
}
add(method: Method) {
this.#add(this.#methods, method);
}
// Get Structure Name
#getName() {
return this.#name + '_vtable';
return this.#self + '_vtable';
}
// Check
@ -67,6 +70,20 @@ export class VTable {
}
}
// Get Full Methods Table
#getMethods() {
// Copy Array
const out = [];
out.push(...this.#methods);
// Add Destructors (https://stackoverflow.com/a/17960941)
const destructor_return = `${this.#self} *`;
const destructor_args = `(${getSelfArg(this.#self)})`;
this.#add(out, new Method(this.#self, 'destructor_complete', destructor_return, destructor_args, 0x0 + this.#destructorOffset, false));
this.#add(out, new Method(this.#self, 'destructor_deleting', destructor_return, destructor_args, 0x4 + this.#destructorOffset, false));
// Return
return out;
}
// Generate Header Code
generate(directParent: string | null) {
let out = '';
@ -75,8 +92,9 @@ export class VTable {
this.#check();
// Method Prototypes
for (let i = 0; i < this.#methods.length; i++) {
const info = this.#methods[i];
const methods = this.#getMethods();
for (let i = 0; i < methods.length; i++) {
const info = methods[i];
if (info) {
out += info.generateTypedef();
}
@ -85,10 +103,10 @@ export class VTable {
// Structure
out += `typedef struct ${this.#getName()} ${this.#getName()};\n`;
out += `struct ${this.#getName()} {\n`;
for (let i = 0; i < this.#methods.length; i++) {
for (let i = 0; i < methods.length; i++) {
let name = `unknown${i}`;
let type = 'void *';
const info = this.#methods[i];
const info = methods[i];
if (info) {
name = info.shortName;
type = info.getType() + ' ';
@ -107,8 +125,8 @@ export class VTable {
// Base
out += `extern ${this.#getName()} *${this.#getName()}_base;\n`;
// Methods
for (let i = 0; i < this.#methods.length; i++) {
const info = this.#methods[i];
for (let i = 0; i < methods.length; i++) {
const info = methods[i];
if (info) {
const type = `${info.getType()} *`;
out += `extern ${type}${info.getName()}_vtable_addr;\n`;
@ -140,8 +158,9 @@ export class VTable {
init += `${INDENT}${this.#getName()}_base = (${this.#getName()} *) ${toHex(this.#address)};\n`;
declarations += `${this.#getName()} *${this.#getName()}_base;\n`;
// Methods
for (let i = 0; i < this.#methods.length; i++) {
const info = this.#methods[i];
const methods = this.#getMethods();
for (let i = 0; i < methods.length; i++) {
const info = methods[i];
if (info) {
const vtableAddress = this.#address + (i * POINTER_SIZE);
const type = `${info.getType()} *`;