Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/codegen/infrastructure/function-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export interface FunctionGeneratorContext {
getTargetOS(): string;
setRawInterfaceType(name: string, type: string): void;
getUsesMathRandom(): boolean;
getUsesGC(): boolean;
}

export class FunctionGenerator {
Expand Down Expand Up @@ -1026,7 +1027,9 @@ export class FunctionGenerator {
" {\n";
ir += "entry:\n";

ir += " call void @GC_init()\n";
if (this.ctx.getUsesGC()) {
ir += " call void @GC_init()\n";
}
if (this.ctx.getUsesMathRandom()) {
ir += " %__seed_time = call i64 @time(i8* null)\n";
ir += " call void @srand48(i64 %__seed_time)\n";
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/infrastructure/generator-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,7 @@ export interface IGeneratorContext {
setUsesGC(value: boolean): void;
getUsesMathRandom(): boolean;
setUsesMathRandom(value: boolean): void;
setUsesOs(value: boolean): void;

currentDeclaredInterfaceType: string | undefined;
setCurrentDeclaredInterfaceType(type: string | undefined): void;
Expand Down Expand Up @@ -1248,6 +1249,7 @@ export class MockGeneratorContext implements IGeneratorContext {
return false;
}
setUsesMathRandom(_value: boolean): void {}
setUsesOs(_value: boolean): void {}
setCurrentDeclaredInterfaceType(type: string | undefined): void {
this.currentDeclaredInterfaceType = type;
}
Expand Down
19 changes: 11 additions & 8 deletions src/codegen/infrastructure/llvm-declarations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export interface DeclConfig {
gc?: boolean;
curl?: boolean;
crypto?: boolean;
sqlite?: boolean;
Expand All @@ -25,14 +26,16 @@ export function getLLVMDeclarations(config?: DeclConfig): string {
ir += "declare i8* @calloc(i64, i64)\n";
ir += "declare void @free(i8*)\n";

ir += "; Boehm GC - automatic garbage collection\n";
ir += "declare void @GC_init()\n";
ir += "declare noalias i8* @GC_malloc(i64)\n";
ir += "declare noalias i8* @GC_malloc_atomic(i64)\n";
ir += "declare noalias i8* @GC_malloc_uncollectable(i64)\n";
ir += "declare i8* @GC_realloc(i8*, i64)\n";
ir += "declare void @GC_disable()\n";
ir += "declare void @GC_enable()\n";
if (config?.gc) {
ir += "; Boehm GC - automatic garbage collection\n";
ir += "declare void @GC_init()\n";
ir += "declare noalias i8* @GC_malloc(i64)\n";
ir += "declare noalias i8* @GC_malloc_atomic(i64)\n";
ir += "declare noalias i8* @GC_malloc_uncollectable(i64)\n";
ir += "declare i8* @GC_realloc(i8*, i64)\n";
ir += "declare void @GC_disable()\n";
ir += "declare void @GC_enable()\n";
}
ir += "declare i8* @strcpy(i8*, i8*)\n";
ir += "declare i8* @strncpy(i8*, i8*, i64)\n";
ir += "declare i8* @strcat(i8*, i8*)\n";
Expand Down
149 changes: 139 additions & 10 deletions src/codegen/llvm-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,13 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {

public usesGC: number = 0;
public usesMathRandom: number = 0;
public usesOs: number = 0;
public usesDoubleToString: number = 0;
public usesPath: number = 0;
public usesFs: number = 0;
public usesBase64Bridge: number = 0;
public usesUrlBridge: number = 0;
public usesUriBridge: number = 0;

private dbgAlloc(): number {
const id = this.dbgNextId;
Expand Down Expand Up @@ -1102,6 +1109,21 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {
public setUsesMathRandom(value: boolean): void {
this.usesMathRandom = value ? 1 : 0;
}
public setUsesOs(value: boolean): void {
this.usesOs = value ? 1 : 0;
}
public getUsesOs(): boolean {
return this.usesOs !== 0;
}
public getUsesBase64Bridge(): boolean {
return this.usesBase64Bridge !== 0;
}
public getUsesUrlBridge(): boolean {
return this.usesUrlBridge !== 0;
}
public getUsesUriBridge(): boolean {
return this.usesUriBridge !== 0;
}
public setCurrentDeclaredInterfaceType(type: string | undefined): void {
this.currentDeclaredInterfaceType = type;
}
Expand Down Expand Up @@ -1499,6 +1521,13 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {
this.usesAsyncFs = 0;
this.usesGC = 0;
this.usesMathRandom = 0;
this.usesOs = 0;
this.usesDoubleToString = 0;
this.usesPath = 0;
this.usesFs = 0;
this.usesBase64Bridge = 0;
this.usesUrlBridge = 0;
this.usesUriBridge = 0;

this.ast = ast;

Expand Down Expand Up @@ -1770,6 +1799,40 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {
this.stringBuilderScap.clear();
}

emit(instruction: string): void {
if (!this.usesGC && instruction.includes("@GC_")) {
this.usesGC = 1;
}
if (!this.usesDoubleToString && instruction.includes("@__double_to_string(")) {
this.usesDoubleToString = 1;
}
if (!this.usesPath && instruction.includes("@__path_")) {
this.usesPath = 1;
}
if (!this.usesFs && instruction.includes("@__fs_")) {
this.usesFs = 1;
}
if (
!this.usesBase64Bridge &&
(instruction.includes("@cs_btoa(") ||
instruction.includes("@cs_atob(") ||
instruction.includes("@cs_base64_decode("))
) {
this.usesBase64Bridge = 1;
}
if (!this.usesUrlBridge && instruction.includes("@cs_url_")) {
this.usesUrlBridge = 1;
}
if (
!this.usesUriBridge &&
(instruction.includes("@cs_encode_uri_component(") ||
instruction.includes("@cs_decode_uri_component("))
) {
this.usesUriBridge = 1;
}
super.emit(instruction);
}

getThisPointer(): string | null {
return this.thisPointer;
}
Expand Down Expand Up @@ -2506,21 +2569,11 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {
if (safeStr) {
irParts.push(safeStr);
}
const dblToStr = getDoubleToStringHelper();
if (dblToStr) {
irParts.push(dblToStr);
}
const strHash = getStringHashHelper();
if (strHash) {
irParts.push(strHash);
}

irParts.push(this.fsGen.generateReaddirSyncHelper());
irParts.push(this.fsGen.generateStatSyncHelper());
irParts.push(this.pathGen.generateNormalizeHelper());
irParts.push(this.pathGen.generateRelativeHelper());
irParts.push(this.pathGen.generateParseHelper());

const globalVars = getGlobalVariables();
if (globalVars) {
irParts.push(globalVars);
Expand Down Expand Up @@ -2552,6 +2605,23 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {
}
}

if (!this.usesGC) {
for (let i = 0; i < irParts.length; i++) {
if (irParts[i].includes("@GC_")) {
this.usesGC = 1;
break;
}
}
}
if (!this.usesGC) {
for (let i = 0; i < this.globalStrings.length; i++) {
if (this.globalStrings[i].includes("@GC_")) {
this.usesGC = 1;
break;
}
}
}

const mainIr = this.generateMain();

const liftedFunctions = this.exprGen.arrowFunctionGen.getLiftedFunctions();
Expand Down Expand Up @@ -2715,6 +2785,60 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {
irParts.push(this.embedGen.generateLengthLookupFunction());
}

for (let psi = 0; psi < irParts.length; psi++) {
const part = irParts[psi];
if (!this.usesGC && part.includes("@GC_")) {
this.usesGC = 1;
}
if (!this.usesDoubleToString && part.includes("@__double_to_string(")) {
this.usesDoubleToString = 1;
}
if (!this.usesPath && part.includes("@__path_")) {
this.usesPath = 1;
}
if (!this.usesFs && part.includes("@__fs_")) {
this.usesFs = 1;
}
if (
!this.usesBase64Bridge &&
(part.includes("@cs_btoa(") ||
part.includes("@cs_atob(") ||
part.includes("@cs_base64_decode("))
) {
this.usesBase64Bridge = 1;
}
if (!this.usesUrlBridge && part.includes("@cs_url_")) {
this.usesUrlBridge = 1;
}
if (
!this.usesUriBridge &&
(part.includes("@cs_encode_uri_component(") || part.includes("@cs_decode_uri_component("))
) {
this.usesUriBridge = 1;
}
}
for (let gsi = 0; gsi < this.globalStrings.length; gsi++) {
if (!this.usesGC && this.globalStrings[gsi].includes("@GC_")) {
this.usesGC = 1;
}
}

if (this.usesDoubleToString) {
this.usesGC = 1;
irParts.push(getDoubleToStringHelper());
}
if (this.usesFs) {
this.usesGC = 1;
irParts.push(this.fsGen.generateReaddirSyncHelper());
irParts.push(this.fsGen.generateStatSyncHelper());
}
if (this.usesPath) {
this.usesGC = 1;
irParts.push(this.pathGen.generateNormalizeHelper());
irParts.push(this.pathGen.generateRelativeHelper());
irParts.push(this.pathGen.generateParseHelper());
}

const needsLibuv =
this.usesTimers ||
this.usesPromises ||
Expand Down Expand Up @@ -2763,9 +2887,14 @@ export class LLVMGenerator extends BaseGenerator implements IGeneratorContext {
finalParts.push("\n");
}

if (this.usesStringBuilder || this.usesCurl) {
this.usesGC = 1;
}

finalParts.push(
this.filterDuplicateDeclarations(
getLLVMDeclarations({
gc: this.usesGC !== 0,
curl: this.usesCurl !== 0,
crypto: this.usesCrypto !== 0,
sqlite: this.usesSqlite !== 0,
Expand Down
1 change: 1 addition & 0 deletions src/codegen/stdlib/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ export class JsonGenerator {
return;
}

this.ctx.setUsesGC(true);
const fieldCount = this.ctx.interfaceStructGenGetFieldCount(typeName);

for (let fi = 0; fi < fieldCount; fi++) {
Expand Down
14 changes: 10 additions & 4 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,13 @@ export function compile(
const treeSitterPath = sdk ? sdk.vendorPath : TREESITTER_LIB_PATH;

const platformLibs = targetIsMac ? "" : " -lm -ldl -lrt -lpthread";
let linkLibs = `-L${gcPath} -lgc` + platformLibs;
const needsGcLib =
generator.usesGC ||
generator.usesBase64Bridge ||
generator.usesUrlBridge ||
generator.usesUriBridge ||
generator.usesStringBuilder;
let linkLibs = needsGcLib ? `-L${gcPath} -lgc` + platformLibs : platformLibs.trimStart();
if (generator.usesJson) {
linkLibs += ` -L${yyjsonPath} -lyyjson`;
}
Expand Down Expand Up @@ -404,9 +410,9 @@ export function compile(
const cpBridgeObj = generator.usesChildProcess ? `${bridgePath}/child-process-bridge.o` : "";
const osBridgeObj = `${bridgePath}/os-bridge.o`;
const timeBridgeObj = `${bridgePath}/time-bridge.o`;
const base64BridgeObj = `${bridgePath}/base64-bridge.o`;
const urlBridgeObj = `${bridgePath}/url-bridge.o`;
const uriBridgeObj = `${bridgePath}/uri-bridge.o`;
const base64BridgeObj = generator.usesBase64Bridge ? `${bridgePath}/base64-bridge.o` : "";
const urlBridgeObj = generator.usesUrlBridge ? `${bridgePath}/url-bridge.o` : "";
const uriBridgeObj = generator.usesUriBridge ? `${bridgePath}/uri-bridge.o` : "";
const dotenvBridgeObj = fs.existsSync(`${bridgePath}/dotenv-bridge.o`)
? `${bridgePath}/dotenv-bridge.o`
: "";
Expand Down
18 changes: 14 additions & 4 deletions src/native-compiler-lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,15 @@ export function compileNative(inputFile: string, outputFile: string): void {
: "./vendor/tree-sitter/libtree-sitter.a";
}
}
let linkLibs = "-L" + effectiveGcPath + " -lgc" + platformLibs;
const needsGcLib =
generator.getUsesGC() ||
generator.getUsesBase64Bridge() ||
generator.getUsesUrlBridge() ||
generator.getUsesUriBridge() ||
generator.usesStringBuilder !== 0;
let linkLibs = needsGcLib
? "-L" + effectiveGcPath + " -lgc" + platformLibs
: platformLibs.trimStart();
if (tsLibPath) {
linkLibs = linkLibs + " " + tsLibPath;
}
Expand Down Expand Up @@ -507,9 +515,11 @@ export function compileNative(inputFile: string, outputFile: string): void {
: "";
const osBridgeObj = effectiveBridgePath + "/os-bridge.o";
const timeBridgeObj = effectiveBridgePath + "/time-bridge.o";
const base64BridgeObj = effectiveBridgePath + "/base64-bridge.o";
const urlBridgeObj = effectiveBridgePath + "/url-bridge.o";
const uriBridgeObj = effectiveBridgePath + "/uri-bridge.o";
const base64BridgeObj = generator.getUsesBase64Bridge()
? effectiveBridgePath + "/base64-bridge.o"
: "";
const urlBridgeObj = generator.getUsesUrlBridge() ? effectiveBridgePath + "/url-bridge.o" : "";
const uriBridgeObj = generator.getUsesUriBridge() ? effectiveBridgePath + "/uri-bridge.o" : "";
const dotenvBridgePath = effectiveBridgePath + "/dotenv-bridge.o";
const dotenvBridgeObj = fs.existsSync(dotenvBridgePath) ? dotenvBridgePath : "";
const watchBridgeObj = effectiveBridgePath + "/watch-bridge.o";
Expand Down
Loading