Skip to content

Commit b8f11f1

Browse files
committed
Feature: Initial support for CPPMangler
1 parent 3d1bb48 commit b8f11f1

4 files changed

Lines changed: 53 additions & 10 deletions

File tree

runtime/lib.runtime.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ interface Array<T = any> {}
1717

1818
declare function puts(str: string): void;
1919

20-
declare function _Z13number2stringd(value: number): string;
20+
declare function number2string(value: number): string;

sandbox/do-simple-math.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
}
99

1010
puts("hello");
11-
puts(_Z13number2stringd(doMath()));
11+
puts(number2string(doMath()));
1212
}

src/backend/llvm/cpp.mangler.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
import * as ts from 'typescript';
3+
4+
export class CPPMangler {
5+
static getFunctionName(name: string, parameters: ts.NodeArray<ts.ParameterDeclaration>): string {
6+
if (name === 'puts') {
7+
return name;
8+
}
9+
10+
return '_Z13number2stringd';
11+
}
12+
}

src/backend/llvm/index.ts

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
import * as ts from "typescript";
33
import * as llvm from 'llvm-node';
4+
import {CPPMangler} from "./cpp.mangler";
45

56
export function passReturnStatement(parent: ts.ReturnStatement, ctx: Context, builder: llvm.IRBuilder) {
67
if (!parent.expression) {
@@ -140,19 +141,41 @@ function buildFromCallExpression(
140141
);
141142
}
142143

143-
function buildFromIdentifier(block: ts.Identifier, ctx: Context, builder: llvm.IRBuilder): llvm.Value {
144-
const variable = ctx.variables.get(<string>block.escapedText);
144+
function buildFromIdentifier(identifier: ts.Identifier, ctx: Context, builder: llvm.IRBuilder): llvm.Value {
145+
const variable = ctx.variables.get(<string>identifier.escapedText);
145146
if (variable) {
146147
return variable;
147148
}
148149

149-
const fn = ctx.llvmModule.getFunction(<string>block.escapedText);
150+
const fn = ctx.llvmModule.getFunction(<string>identifier.escapedText);
150151
if (fn) {
151152
return fn;
152153
}
153154

155+
const symbol = ctx.typeChecker.getSymbolAtLocation(identifier);
156+
if (symbol && symbol.declarations.length > 0) {
157+
if (symbol.declarations.length > 1) {
158+
throw new Error(
159+
`Multiple declarations are not supported`
160+
);
161+
}
162+
163+
const symbolDeclaration = <ts.FunctionDeclaration>symbol.declarations[0];
164+
if (symbolDeclaration.name) {
165+
const mangledFunctionName = CPPMangler.getFunctionName(
166+
<string>symbolDeclaration.name.escapedText,
167+
symbolDeclaration.parameters
168+
);
169+
170+
const fn = ctx.llvmModule.getFunction(mangledFunctionName);
171+
if (fn) {
172+
return fn;
173+
}
174+
}
175+
}
176+
154177
throw new Error(
155-
`Unknown Identifier: "${<string>block.escapedText}"`
178+
`Unknown Identifier: "${<string>identifier.escapedText}"`
156179
);
157180
}
158181

@@ -251,11 +274,13 @@ class SymbolTable extends Map<string, llvm.Value> {
251274
}
252275

253276
class Context {
277+
public typeChecker: ts.TypeChecker;
254278
public llvmContext: llvm.LLVMContext;
255279
public llvmModule: llvm.Module;
256280
public variables: SymbolTable = new SymbolTable();
257281

258-
public constructor() {
282+
public constructor(typeChecker: ts.TypeChecker) {
283+
this.typeChecker = typeChecker;
259284
this.llvmContext = new llvm.LLVMContext();
260285
this.llvmModule = new llvm.Module("test", this.llvmContext);
261286
}
@@ -284,7 +309,9 @@ export function initializeLLVM() {
284309
}
285310

286311
export function generateModuleFromProgram(program: ts.Program): llvm.Module {
287-
const ctx = new Context();
312+
const ctx = new Context(
313+
program.getTypeChecker()
314+
);
288315

289316
let putsFnType = llvm.FunctionType.get(llvm.Type.getInt32Ty(ctx.llvmContext), [
290317
llvm.Type.getInt8PtrTy(ctx.llvmContext)
@@ -294,8 +321,12 @@ export function generateModuleFromProgram(program: ts.Program): llvm.Module {
294321
let number2stringFnType = llvm.FunctionType.get(llvm.Type.getInt8PtrTy(ctx.llvmContext), [
295322
llvm.Type.getDoubleTy(ctx.llvmContext)
296323
], false);
297-
llvm.Function.create(number2stringFnType, llvm.LinkageTypes.ExternalLinkage, "_Z13number2stringd", ctx.llvmModule);
298-
// ctx.llvmModule.getOrInsertFunction();
324+
llvm.Function.create(
325+
number2stringFnType,
326+
llvm.LinkageTypes.ExternalLinkage,
327+
CPPMangler.getFunctionName("number2string", <any>[]),
328+
ctx.llvmModule
329+
);
299330

300331
let mainFnType = llvm.FunctionType.get(llvm.Type.getVoidTy(ctx.llvmContext), false);
301332
let mainFn = llvm.Function.create(mainFnType, llvm.LinkageTypes.ExternalLinkage, "main", ctx.llvmModule);

0 commit comments

Comments
 (0)