From eba22d5ab9dfec699abfbc2679f44d08e54c89f4 Mon Sep 17 00:00:00 2001 From: Chad Smith Date: Wed, 18 Feb 2026 23:25:54 -0800 Subject: [PATCH] add IR builder methods to BaseGenerator and IGeneratorContext --- src/codegen/infrastructure/base-generator.ts | 42 ++++++++++++++++ .../infrastructure/generator-context.ts | 50 +++++++++++++++++++ src/codegen/stdlib/date.ts | 19 +++---- 3 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/codegen/infrastructure/base-generator.ts b/src/codegen/infrastructure/base-generator.ts index 007dde6e..083d600d 100644 --- a/src/codegen/infrastructure/base-generator.ts +++ b/src/codegen/infrastructure/base-generator.ts @@ -460,6 +460,48 @@ export class BaseGenerator { this.emit(`${name}:`); } + emitCall(retType: string, func: string, args: string): string { + const temp = this.nextTemp(); + this.emit(`${temp} = call ${retType} ${func}(${args})`); + this.setVariableType(temp, retType); + return temp; + } + + emitCallVoid(func: string, args: string): void { + this.emit(`call void ${func}(${args})`); + } + + emitLoad(type: string, ptr: string): string { + const temp = this.nextTemp(); + this.emit(`${temp} = load ${type}, ${type}* ${ptr}`); + this.setVariableType(temp, type); + return temp; + } + + emitStore(type: string, value: string, ptr: string): void { + this.emit(`store ${type} ${value}, ${type}* ${ptr}`); + } + + emitGep(baseType: string, ptr: string, indices: string): string { + const temp = this.nextTemp(); + this.emit(`${temp} = getelementptr ${baseType}, ${baseType}* ${ptr}, ${indices}`); + return temp; + } + + emitIcmp(pred: string, type: string, lhs: string, rhs: string): string { + const temp = this.nextTemp(); + this.emit(`${temp} = icmp ${pred} ${type} ${lhs}, ${rhs}`); + this.setVariableType(temp, 'i1'); + return temp; + } + + emitBitcast(value: string, fromType: string, toType: string): string { + const temp = this.nextTemp(); + this.emit(`${temp} = bitcast ${fromType} ${value} to ${toType}`); + this.setVariableType(temp, toType); + return temp; + } + // ============================================ // Symbol table convenience methods // ============================================ diff --git a/src/codegen/infrastructure/generator-context.ts b/src/codegen/infrastructure/generator-context.ts index 722f9e45..b74221b0 100644 --- a/src/codegen/infrastructure/generator-context.ts +++ b/src/codegen/infrastructure/generator-context.ts @@ -555,6 +555,14 @@ export interface IGeneratorContext { emitUnreachable(): void; emitLabel(name: string): void; + emitCall(retType: string, func: string, args: string): string; + emitCallVoid(func: string, args: string): void; + emitLoad(type: string, ptr: string): string; + emitStore(type: string, value: string, ptr: string): void; + emitGep(baseType: string, ptr: string, indices: string): string; + emitIcmp(pred: string, type: string, lhs: string, rhs: string): string; + emitBitcast(value: string, fromType: string, toType: string): string; + getOutput(): string[]; clearOutput(): void; pushOutput(line: string): void; @@ -1200,6 +1208,48 @@ export class MockGeneratorContext implements IGeneratorContext { this.emit(`${name}:`); } + emitCall(retType: string, func: string, args: string): string { + const temp = this.nextTemp(); + this.emit(`${temp} = call ${retType} ${func}(${args})`); + this.setVariableType(temp, retType); + return temp; + } + + emitCallVoid(func: string, args: string): void { + this.emit(`call void ${func}(${args})`); + } + + emitLoad(type: string, ptr: string): string { + const temp = this.nextTemp(); + this.emit(`${temp} = load ${type}, ${type}* ${ptr}`); + this.setVariableType(temp, type); + return temp; + } + + emitStore(type: string, value: string, ptr: string): void { + this.emit(`store ${type} ${value}, ${type}* ${ptr}`); + } + + emitGep(baseType: string, ptr: string, indices: string): string { + const temp = this.nextTemp(); + this.emit(`${temp} = getelementptr ${baseType}, ${baseType}* ${ptr}, ${indices}`); + return temp; + } + + emitIcmp(pred: string, type: string, lhs: string, rhs: string): string { + const temp = this.nextTemp(); + this.emit(`${temp} = icmp ${pred} ${type} ${lhs}, ${rhs}`); + this.setVariableType(temp, 'i1'); + return temp; + } + + emitBitcast(value: string, fromType: string, toType: string): string { + const temp = this.nextTemp(); + this.emit(`${temp} = bitcast ${fromType} ${value} to ${toType}`); + this.setVariableType(temp, toType); + return temp; + } + getOutput(): string[] { return this.output; } diff --git a/src/codegen/stdlib/date.ts b/src/codegen/stdlib/date.ts index b9f7e419..79174130 100644 --- a/src/codegen/stdlib/date.ts +++ b/src/codegen/stdlib/date.ts @@ -19,18 +19,13 @@ export class DateGenerator { const tvAlloca = this.ctx.nextTemp(); this.ctx.emit(`${tvAlloca} = alloca %struct.timeval`); - const callResult = this.ctx.nextTemp(); - this.ctx.emit(`${callResult} = call i32 @gettimeofday(%struct.timeval* ${tvAlloca}, i8* null)`); - - const secPtr = this.ctx.nextTemp(); - this.ctx.emit(`${secPtr} = getelementptr %struct.timeval, %struct.timeval* ${tvAlloca}, i32 0, i32 0`); - const secVal = this.ctx.nextTemp(); - this.ctx.emit(`${secVal} = load i64, i64* ${secPtr}`); - - const usecPtr = this.ctx.nextTemp(); - this.ctx.emit(`${usecPtr} = getelementptr %struct.timeval, %struct.timeval* ${tvAlloca}, i32 0, i32 1`); - const usecVal = this.ctx.nextTemp(); - this.ctx.emit(`${usecVal} = load i64, i64* ${usecPtr}`); + this.ctx.emitCall('i32', '@gettimeofday', `%struct.timeval* ${tvAlloca}, i8* null`); + + const secPtr = this.ctx.emitGep('%struct.timeval', tvAlloca, 'i32 0, i32 0'); + const secVal = this.ctx.emitLoad('i64', secPtr); + + const usecPtr = this.ctx.emitGep('%struct.timeval', tvAlloca, 'i32 0, i32 1'); + const usecVal = this.ctx.emitLoad('i64', usecPtr); const secDouble = this.ctx.nextTemp(); this.ctx.emit(`${secDouble} = sitofp i64 ${secVal} to double`);