-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Glowman554
committed
Jan 21, 2024
1 parent
263798f
commit c01c883
Showing
8 changed files
with
263 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,6 @@ | |
"mode": "flbb" | ||
}, | ||
"dependencies": [ | ||
"vm@1.0.0-x64" | ||
"vm@1.0.1-x64" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
deno run -A gen.ts | ||
gcc native.c -o native.so -fpic --shared |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { structGen } from "../../src/tools/structgen.ts"; | ||
import { functionGen, addDatatype, finish } from "../../src/tools/bindgen.ts"; | ||
|
||
const struct = ` | ||
struct vm_instance { | ||
void* code; | ||
int64_t* stack; | ||
int stack_ptr; | ||
int max_stack; | ||
int64_t* global_variables; | ||
uint8_t* global_variable_types; | ||
int global_variable_size; | ||
int64_t spark; | ||
}; | ||
`; | ||
|
||
|
||
const struct_bind = await structGen(struct, "struct vm_instance", [ | ||
"code", | ||
"stack", | ||
"stack_ptr", | ||
"max_stack", | ||
"global_variables", | ||
"global_variable_types", | ||
"global_variable_size", | ||
"spark" | ||
]); | ||
|
||
addDatatype("struct vm_instance*", "int"); | ||
addDatatype("vm_instance*", "int"); | ||
addDatatype("int64_t", "int"); | ||
addDatatype("uint64_t", "int"); | ||
|
||
functionGen(48327, "void stack_push(struct vm_instance* vm, int64_t value);"); | ||
functionGen(48328, "int64_t stack_pop(struct vm_instance* vm);"); | ||
functionGen(48329, "void invoke(struct vm_instance* vm, uint64_t location);"); | ||
functionGen(48330, "struct vm_instance* vm_load(const char* file);"); | ||
functionGen(48331, "void vm_destroy(struct vm_instance* vm);"); | ||
|
||
|
||
const [ fl, c ] = finish(`#include "../../src/flvm/vm.h"\n`); | ||
|
||
Deno.writeTextFileSync("vm.fl", struct_bind + fl); | ||
Deno.writeTextFileSync("native.c", c); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"name": "vm", | ||
"version": "1.0.0-x64", | ||
"version": "1.0.1-x64", | ||
"type": "module" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,24 @@ | ||
$define struct vm_instance_offset_code 0 | ||
$define struct vm_instance_offset_stack 8 | ||
$define struct vm_instance_offset_stack_ptr 16 | ||
$define struct vm_instance_offset_max_stack 20 | ||
$define struct vm_instance_offset_global_variables 24 | ||
$define struct vm_instance_offset_global_variable_types 32 | ||
$define struct vm_instance_offset_global_variable_size 40 | ||
$define struct vm_instance_offset_spark 48 | ||
$define vm_instance_offset_code 0 | ||
$define vm_instance_offset_stack 8 | ||
$define vm_instance_offset_stack_ptr 16 | ||
$define vm_instance_offset_max_stack 20 | ||
$define vm_instance_offset_global_variables 24 | ||
$define vm_instance_offset_global_variable_types 32 | ||
$define vm_instance_offset_global_variable_size 40 | ||
$define vm_instance_offset_spark 48 | ||
$define struct vm_instance_size 56 | ||
|
||
function(assembly) stack_push(int vm, int value) -> void { | ||
"48327" | ||
} | ||
|
||
function(assembly) stack_pop(int vm) -> int { | ||
"48328" | ||
} | ||
|
||
function(assembly) invoke(int vm, int location) -> void { | ||
"48329" | ||
} | ||
|
||
function(assembly) vm_load(str file) -> int { | ||
"48330" | ||
} | ||
|
||
function(assembly) vm_destroy(int vm) -> void { | ||
"48331" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
function split_c_signature(signature: string) { | ||
let return_type = signature.split("(", 1)[0]; | ||
let function_name; | ||
let attributes; | ||
|
||
if (return_type.split(" ").length == 1) { | ||
function_name = return_type; | ||
return_type = " "; | ||
} else { | ||
const ret_array = return_type.split(" "); | ||
let len = ret_array.length; | ||
|
||
function_name = ret_array[len - 1].trim(); | ||
|
||
ret_array.pop(); | ||
len--; | ||
|
||
return_type = ret_array[len - 1]; | ||
attributes = ""; | ||
|
||
// loop over the reversed array | ||
let is_ret = true; | ||
for (let i = len - 2; i >= 0; i--) { | ||
const _allowed_return_types = ['short', 'long', 'signed', 'unsigned', 'const', 'restrict', 'restrict', 'mutable']; | ||
if (_allowed_return_types.includes(ret_array[i]) && is_ret) { | ||
return_type = ret_array[i] + " " + return_type; | ||
} else { | ||
is_ret = false; | ||
attributes = ret_array[i] + " " + attributes; | ||
} | ||
} | ||
|
||
return_type = return_type.trim(); | ||
attributes = attributes.trim(); | ||
} | ||
|
||
let class_name = ""; | ||
if (function_name.split("::", 1).length != 1) { | ||
class_name = function_name.split("::", 1)[0]; | ||
function_name = function_name.split("::", 1)[1]; | ||
} | ||
|
||
if (function_name.startsWith("*")) { | ||
function_name = function_name.substring(1); | ||
return_type = "*"; | ||
} | ||
|
||
let params = signature.split("(")[1].split(")")[0].split(",").map(p => p.trim()); | ||
if (params[0] == "") { | ||
params = []; | ||
} | ||
|
||
return { | ||
"return_type": return_type, | ||
"class_name": class_name, | ||
"function_name": function_name, | ||
"attributes": attributes, | ||
"params": params, | ||
"signature": signature | ||
}; | ||
} | ||
|
||
const datatype_lookup: { [key: string]: string } = { | ||
"void": "void", | ||
"char": "chr", | ||
"const char*": "str", | ||
"uint32_t": "int", | ||
"bool": "int" | ||
}; | ||
|
||
|
||
const translations: {id: number, translation: string}[] = []; | ||
let outfl = ""; | ||
let outc = "" | ||
|
||
function getDatatype(dt: string) { | ||
if (!datatype_lookup[dt]) { | ||
const newDt = prompt(`No datatype translation found for ${dt}! Translation? `); | ||
datatype_lookup[dt] = newDt as string; | ||
} | ||
return datatype_lookup[dt]; | ||
} | ||
|
||
export function addDatatype(dt: string, translation: string) { | ||
datatype_lookup[dt] = translation; | ||
} | ||
|
||
export function functionGen(id: number, sigStr: string) { | ||
const sig = split_c_signature(sigStr); | ||
|
||
let fl = `function(assembly) ${sig.function_name}(`; | ||
for (const param of sig.params) { | ||
const datatype = param.substring(0, param.lastIndexOf(" ")).trim(); | ||
const name = param.substring(param.lastIndexOf(" ")).trim(); | ||
|
||
|
||
|
||
fl += getDatatype(datatype); | ||
fl += " " | ||
fl += name; | ||
fl += ", "; | ||
} | ||
|
||
if (sig.params.length != 0) fl = fl.substring(0, fl.length - 2); | ||
fl += `) -> ${getDatatype(sig.return_type)} {\n "${id}"\n}`; | ||
|
||
outfl += fl + "\n"; | ||
|
||
let c = `void native_${sig.function_name}(struct vm_instance* vm) {\n`; | ||
for (let i = sig.params.length; i--; i > 0) { | ||
|
||
const datatype = sig.params[i].substring(0, sig.params[i].lastIndexOf(" ")).trim(); | ||
let name = sig.params[i].substring(sig.params[i].lastIndexOf(" ")).trim(); | ||
name = name == "vm" ? "vm2" : name; | ||
|
||
c += ` ${datatype} ${name} = (${datatype}) stack_pop(vm);\n`; | ||
} | ||
|
||
if (sig.return_type != "void") { | ||
c += ` stack_push(vm, ${sig.function_name}(`; | ||
} else { | ||
c += ` ${sig.function_name}(`; | ||
} | ||
|
||
for (const param of sig.params) { | ||
let name = param.substring(param.lastIndexOf(" ")).trim(); | ||
name = name == "vm" ? "vm2" : name; | ||
|
||
c += `${name}, `; | ||
} | ||
|
||
if (sig.params.length != 0) c = c.substring(0, c.length - 2); | ||
|
||
if (sig.return_type != "void") { | ||
c += `));\n}`; | ||
} else { | ||
c += `);\n stack_push(vm, 0);\n}`; | ||
} | ||
|
||
|
||
outc += c + "\n"; | ||
|
||
translations.push({ | ||
id: id, | ||
translation: "native_" + sig.function_name | ||
}); | ||
} | ||
|
||
export function finish(include: string) { | ||
let finalc = include + outc; | ||
|
||
|
||
finalc += "void init() {\n"; | ||
for (const translation of translations) { | ||
finalc += ` vm_native_register(${translation.id}, ${translation.translation});\n`; | ||
} | ||
finalc += "}"; | ||
|
||
return [outfl, finalc]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
async function runCommand(command: string) { | ||
// console.log("cmd: " + command); | ||
const proc = Deno.run({ | ||
cmd: command.split(" ").filter(v => v != ""), | ||
stderr: "inherit", | ||
stdout: "piped" | ||
}); | ||
|
||
const status = await proc.status(); | ||
const stdout = new TextDecoder().decode(await proc.output()); | ||
proc.close(); | ||
if (!status.success) { | ||
throw new Error("Could not execute: " + command); | ||
} | ||
|
||
return stdout; | ||
} | ||
function genCode(structDefinition: string, structName: string, members: string[]) { | ||
let code = ""; | ||
|
||
code += "#include <stdbool.h>\n"; | ||
code += "#include <stdint.h>\n"; | ||
code += "#include <stdio.h>\n"; | ||
|
||
code += structDefinition + "\n"; | ||
|
||
code += "int main() {\n"; | ||
for (const member of members) { | ||
const name = structName.startsWith("struct ") ? structName.replace("struct ", "") : structName; | ||
code += `\tprintf("$define ${name}_offset_${member} %ld\\n", __builtin_offsetof(${structName}, ${member}));\n`; | ||
} | ||
|
||
code += `\tprintf("$define ${structName}_size %ld\\n", sizeof(${structName}));\n`; | ||
|
||
code += "}\n"; | ||
|
||
return code; | ||
} | ||
|
||
export async function structGen(structDefinition: string, structName: string, members: string[]) { | ||
Deno.writeTextFileSync("/tmp/struct.c", genCode(structDefinition, structName, members)); | ||
await runCommand("gcc /tmp/struct.c -o /tmp/struct.elf"); | ||
return await runCommand("/tmp/struct.elf"); | ||
} |