11
22import * as ts from "typescript" ;
33import * as llvm from 'llvm-node' ;
4+ import { CPPMangler } from "./cpp.mangler" ;
45
56export 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
253276class 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
286311export 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