Better Static Properties

This commit is contained in:
TheBrokenRail 2024-05-17 02:52:31 -04:00
parent 603010e3cc
commit fbb9b6d6da
6 changed files with 46 additions and 71 deletions

View File

@ -66,14 +66,7 @@ export function toHex(x: number) {
return '0x' + x.toString(16);
}
export function assertSize(name: string, size: number) {
let out = '';
// Define Size Macro
const macro = toUpperSnakeCase(name) + '_SIZE';
out += `#define ${macro} ${toHex(size)}\n`;
// Check Size
out += `static_assert(sizeof(${name}) == ${macro}, "Invalid Size");\n`;
// Return
return out;
return `static_assert(sizeof(${name}) == ${toHex(size)}, "Invalid Size");\n`;
}
export function safeParseInt(str: string) {
const x = parseInt(str);

View File

@ -1,5 +1,5 @@
import * as fs from 'node:fs';
import { STRUCTURE_FILES, EXTENSION, INDENT } from './common';
import { STRUCTURE_FILES, EXTENSION } from './common';
import { getStructure } from './map';
import { Struct } from './struct';
@ -130,11 +130,7 @@ function makeHeaderPart() {
}
// Return
let result = '';
result += '// Init\n';
result += 'void init_symbols();\n\n';
result += structures;
return result;
return structures;
}
// Create Main Header
@ -180,7 +176,6 @@ function makeCompiledCode(output: string) {
// Generate
let declarations = '';
let init = '';
let isFirst = true;
for (const structure of structureObjects) {
const name = structure.getName();
@ -188,14 +183,11 @@ function makeCompiledCode(output: string) {
isFirst = false;
} else {
declarations += '\n';
init += '\n';
}
declarations += `// ${name}\n`;
init += `${INDENT}// ${name}\n`;
try {
const code = structure.generateCode();
declarations += code.functions;
init += code.init;
declarations += code;
} catch (e) {
console.log(`Error Generating Code: ${name}: ${e instanceof Error ? e.stack : e}`);
process.exit(1);
@ -205,11 +197,7 @@ function makeCompiledCode(output: string) {
// Write
let result = '';
result += `#include "${fs.realpathSync(headerOutput)}"\n`;
result += '\n#include <cstring>\n';
result += '\n// Init\n';
result += 'void init_symbols() {\n';
result += init;
result += '}\n\n';
result += '\n#include <cstring>\n\n';
result += declarations;
fs.writeFileSync(output, result);
}

View File

@ -56,7 +56,7 @@ export class Method {
// Generate Variable Definition
generateDefinition(nameSuffix?: string) {
return `${this.getType()} ${this.getName()}${nameSuffix !== undefined ? nameSuffix : ''};\n`;
return `${this.getType()} ${this.getName()}${nameSuffix !== undefined ? nameSuffix : ''}`;
}
// Generate "New Method" Test

View File

@ -34,8 +34,14 @@ export class Property {
}
return name;
}
#fullName(separator: string) {
return this.#self + separator + this.name();
}
fullName() {
return `${this.#self}_${this.name()}`;
return this.#fullName('_');
}
prettyName() {
return this.#fullName('::');
}
rawType() {
return this.#type;
@ -48,13 +54,8 @@ export class StaticProperty extends Property {
super(address, type, name, self);
}
// Generate Variable Definition
globalPointerDefinition() {
return `${this.type()} *${this.fullName()}_pointer;\n`;
}
// Generate Macro
macro() {
return `#define ${this.fullName()} (*${this.fullName()}_pointer)\n`;
// Reference
referenceDefinition(addSelf: boolean) {
return `${this.type()} &${addSelf ? this.prettyName() : this.name()}`;
}
}

View File

@ -193,16 +193,14 @@ export class Struct {
// Static Properties
for (const property of this.#staticProperties) {
out += property.typedef();
out += `extern ${property.globalPointerDefinition()}`;
out += property.macro();
}
// Methods
for (const method of this.#methods) {
if (!method.isInherited) {
out += method.generateTypedef();
out += `extern ${method.generateDefinition()}`;
out += `extern ${method.generateDefinition(ORIGINAL_SUFFIX)}`;
out += `extern ${method.generateDefinition()};\n`;
out += `extern ${method.generateDefinition(ORIGINAL_SUFFIX)};\n`;
}
}
@ -220,6 +218,10 @@ export class Struct {
out += `struct ${this.#name} {\n`;
out += this.#generateProperties();
out += this.#generateMethods();
for (const property of this.#staticProperties) {
// Static Property References
out += `${INDENT}static ${property.referenceDefinition(false)};\n`;
}
if (this.#size === null) {
// Prevent Manually Copying/Allocating Structure With Undefined
out += `${INDENT}${this.#name}() = delete;\n`;
@ -247,34 +249,29 @@ export class Struct {
// Generate Compiled Code
generateCode() {
let declarations = '';
let init = '';
let out = '';
// Static Properties
for (const property of this.#staticProperties) {
init += `${INDENT}${property.fullName()}_pointer = (${property.type()} *) ${toHex(property.offset)};\n`;
declarations += property.globalPointerDefinition();
out += `${property.referenceDefinition(true)} = *(${property.type()} *) ${toHex(property.offset)};\n`;
}
// Methods
for (const method of this.#methods) {
if (!method.isInherited) {
init += `${INDENT}${method.getName()} = (${method.getType()}) ${toHex(method.address)};\n`;
declarations += method.generateDefinition();
init += `${INDENT}${method.getName()}${ORIGINAL_SUFFIX} = ${method.getName()};\n`;
declarations += method.generateDefinition(ORIGINAL_SUFFIX);
out += `${method.generateDefinition()} = (${method.getType()}) ${toHex(method.address)};\n`;
out += `${method.generateDefinition(ORIGINAL_SUFFIX)} = ${method.getName()};\n`;
}
}
// VTable
if (this.#vtable !== null) {
const vtable = this.#vtable.generateCode();
declarations += vtable.declarations;
init += vtable.init;
out += vtable;
}
// Return
return {functions: declarations, init};
return out;
}
// Set Direct Parent (Used For "New Method" Testing)

View File

@ -133,7 +133,7 @@ export class VTable {
const pointerType = `${type} *`;
out += `extern ${pointerType}${name}_vtable_addr;\n`;
out += info.generateNewMethodTest(directParent, '*', '_vtable_addr');
out += `extern ${info.generateDefinition(ORIGINAL_SUFFIX)}`;
out += `extern ${info.generateDefinition(ORIGINAL_SUFFIX)};\n`;
}
}
}
@ -149,8 +149,7 @@ export class VTable {
// Generate Compiled Code
generateCode() {
let declarations = '';
let init = '';
let out = '';
// Check
this.#check();
@ -158,8 +157,7 @@ export class VTable {
// Pointers
if (this.#address !== null) {
// Base
init += `${INDENT}${this.#getName()}_base = (${this.#getName()} *) ${toHex(this.#address)};\n`;
declarations += `${this.#getName()} *${this.#getName()}_base;\n`;
out += `${this.#getName()} *${this.#getName()}_base = (${this.#getName()} *) ${toHex(this.#address)};\n`;
// Methods
const methods = this.getMethods();
for (let i = 0; i < methods.length; i++) {
@ -169,31 +167,29 @@ export class VTable {
const name = info.getName();
const type = info.getType();
const pointerType = `${type} *`;
init += `${INDENT}${name}_vtable_addr = (${pointerType}) ${toHex(vtableAddress)};\n`;
declarations += `${pointerType}${name}_vtable_addr;\n`;
init += `${INDENT}${name}${ORIGINAL_SUFFIX} = *${name}_vtable_addr;\n`;
declarations += info.generateDefinition(ORIGINAL_SUFFIX);
out += `${pointerType}${name}_vtable_addr = (${pointerType}) ${toHex(vtableAddress)};\n`;
out += `${info.generateDefinition(ORIGINAL_SUFFIX)} = *${name}_vtable_addr;\n`;
}
}
}
// Duplication Method
if (this.#size !== null) {
declarations += `${this.#getName()} *dup_${this.#getName()}(${this.#getName()} *vtable) {\n`;
declarations += `${INDENT}uchar *real_vtable = (uchar *) vtable;\n`;
declarations += `${INDENT}real_vtable -= ${RTTI_SIZE};\n`;
declarations += `${INDENT}size_t real_vtable_size = sizeof(${this.#getName()}) + ${RTTI_SIZE};\n`;
declarations += `${INDENT}uchar *new_vtable = (uchar *) ::operator new(real_vtable_size);\n`;
declarations += `${INDENT}if (new_vtable == NULL) {\n`;
declarations += `${INDENT}${INDENT}return NULL;\n`;
declarations += `${INDENT}}\n`;
declarations += `${INDENT}memcpy((void *) new_vtable, (void *) real_vtable, real_vtable_size);\n`;
declarations += `${INDENT}new_vtable += ${RTTI_SIZE};\n`;
declarations += `${INDENT}return (${this.#getName()} *) new_vtable;\n`;
declarations += '}\n';
out += `${this.#getName()} *dup_${this.#getName()}(${this.#getName()} *vtable) {\n`;
out += `${INDENT}uchar *real_vtable = (uchar *) vtable;\n`;
out += `${INDENT}real_vtable -= ${RTTI_SIZE};\n`;
out += `${INDENT}size_t real_vtable_size = sizeof(${this.#getName()}) + ${RTTI_SIZE};\n`;
out += `${INDENT}uchar *new_vtable = (uchar *) ::operator new(real_vtable_size);\n`;
out += `${INDENT}if (new_vtable == NULL) {\n`;
out += `${INDENT}${INDENT}return NULL;\n`;
out += `${INDENT}}\n`;
out += `${INDENT}memcpy((void *) new_vtable, (void *) real_vtable, real_vtable_size);\n`;
out += `${INDENT}new_vtable += ${RTTI_SIZE};\n`;
out += `${INDENT}return (${this.#getName()} *) new_vtable;\n`;
out += '}\n';
}
// Return
return {declarations, init};
return out;
}
}