From 98be3bf7ddc753540a269856e773d6f3fdef94b1 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Thu, 4 May 2017 10:18:46 -0400 Subject: [PATCH 01/23] Finish setting up the module's data layout --- src/backends/llvm.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backends/llvm.ts b/src/backends/llvm.ts index 60f5e50..74f1986 100644 --- a/src/backends/llvm.ts +++ b/src/backends/llvm.ts @@ -536,14 +536,14 @@ export function codegen(ir: CompilerIR): llvm.Module { let builder = llvm.Builder.create(); // Create a module. This is where all the generated code will go. let mod: llvm.Module = llvm.Module.create("braidprogram"); - + // Set the target triple and data layout let target_triple: string = llvm.TargetMachine.getDefaultTargetTriple(); let target = llvm.Target.getFromTriple(target_triple); let target_machine = llvm.TargetMachine.create(target, target_triple); - let data_layout = target_machine.getTargetMachineTarget().toString(); - - mod.setDataLayout(data_layout); + let data_layout = target_machine.getTargetMachineData().toString(); + mod.setTarget(target_triple); + mod.setDataLayout(data_layout); let emitter: LLVMEmitter = { ir: ir, From c3f191b81eb6252537ab22e312047381feb62f86 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Thu, 4 May 2017 10:19:39 -0400 Subject: [PATCH 02/23] Write more methods for 'getting' and calling useful opengl funcs --- src/backends/opengl.ts | 131 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index ebd562a..8bdf9c4 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -3,6 +3,137 @@ import * as llvm from '../../node_modules/llvmc/src/wrapped'; import { ASTVisit, ast_visit, compose_visit } from '../visit'; import * as ast from '../ast'; +////////////////////////////////////////// +// useful openGL bindings +////////////////////////////////////////// + +/** + * Methods for getting various openGL types + */ +function glchar() {return llvm.IntType.int8();} +function glstring() {return llvm.PointerType.create(glchar(), 0);} +function glint() {return llvm.IntType.int32();} +function gluint() {return llvm.IntType.int32();} +function glsizei() {return llvm.IntType.int32();} +function glenum() {return llvm.IntType.int32();} + +/* + * GLuint glCreateShader(GLenum shaderType) + */ +function glCreateShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glCreateShader"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = gluint(); + let arg_types: llvm.Type[] = [glenum()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glCreateShader", func_type); + } + return emitter.builder.buildCall(func, [shader_type], ""); +} + +/* + * void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length) + */ +function glShaderSource(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, count: llvm.Value, sources: llvm.Value, length: llvm.Value) { + let func: llvm.Function = emitter.mod.getFunction("glShaderSource"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [gluint(), glsizei(), llvm.PointerType.create(glstring(), 0), llvm.PointerType.create(glint(), 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glShaderSource", func_type); + } + return emitter.builder.buildCall(func, [shader, count, sources, length], ""); +} + +/* + * void glCompileShader( GLuint shader) + */ +function glCompileShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value) { + let func: llvm.Function = emitter.mod.getFunction("glCompileShader"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [gluint()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glCompileShader", func_type); + } + return emitter.builder.buildCall(func, [shader_type], ""); +} + +function glGetShaderParameter(emitter: llvm_be.LLVMEmitter) { + throw "not implemented yet"; +} + +function glGetShaderInfoLog(emitter: llvm_be.LLVMEmitter) { + throw "not implemented yet"; +} + +/* + * GLuint glCreateProgram(void) + */ +function glCreateProgram(emitter: llvm_be.LLVMEmitter) { + let func: llvm.Function = emitter.mod.getFunction("glCreateProgram"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = gluint(); + let arg_types: llvm.Type[] = []; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glCreateProgram", func_type); + } + return emitter.builder.buildCall(func, [], ""); +} + +/* + * void glAttachShader(GLuint program, GLuint shader) + */ +function glAttachShader(emitter: llvm_be.LLVMEmitter, program: llvm.Value, shader: llvm.Value) { + let func: llvm.Function = emitter.mod.getFunction("glAttachShader"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [gluint(), gluint()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glAttachShader", func_type); + } + return emitter.builder.buildCall(func, [program, shader], ""); +} + +/* + * void glLinkProgram(GLuint program) + */ +function glLinkProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value) { + let func: llvm.Function = emitter.mod.getFunction("glLinkProgram"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [gluint()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glLinkProgram", func_type); + } + return emitter.builder.buildCall(func, [program], ""); +} + +function glGetProgramParameter(emitter: llvm_be.LLVMEmitter) { + throw "not implemented yet"; +} + +/* + * void glGetProgramInfoLog( GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog) + */ +function glGetProgramInfoLog(emitter: llvm_be.LLVMEmitter, program: llvm.Value, max_length: llvm.Value, length: llvm.Value, info_log: llvm.Value) { + let func: llvm.Function = emitter.mod.getFunction("glGetProgramInfoLog"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [gluint(), glsizei(), llvm.PointerType.create(glsizei(),0), glstring()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glGetProgramInfoLog", func_type); + } + return emitter.builder.buildCall(func, [program, max_length, length, info_log], ""); +} + +////////////////////////////////////////// + +function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, src) { + // let shader: llvm.Value = glCreateShader(emitter, llvm.ConstInt.create(shader_type, llvm.IntType.int32())); + throw "not implemented yet"; +} + // Extend the JavaScript compiler with some WebGL specifics. let compile_rules: ASTVisit = compose_visit(llvm_be.compile_rules, { From d6741d44c7f6a1105367ff91ad665b3de0865e06 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Thu, 4 May 2017 12:30:55 -0400 Subject: [PATCH 03/23] Add method for declaring/calling printf --- src/backends/opengl.ts | 62 ++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 8bdf9c4..9d9c055 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -10,12 +10,12 @@ import * as ast from '../ast'; /** * Methods for getting various openGL types */ -function glchar() {return llvm.IntType.int8();} -function glstring() {return llvm.PointerType.create(glchar(), 0);} -function glint() {return llvm.IntType.int32();} -function gluint() {return llvm.IntType.int32();} -function glsizei() {return llvm.IntType.int32();} -function glenum() {return llvm.IntType.int32();} +function glchar(): llvm.Type {return llvm.IntType.int8();} +function glstring(): llvm.Type {return llvm.PointerType.create(glchar(), 0);} +function glint(): llvm.Type {return llvm.IntType.int32();} +function gluint(): llvm.Type {return llvm.IntType.int32();} +function glsizei(): llvm.Type {return llvm.IntType.int32();} +function glenum(): llvm.Type {return llvm.IntType.int32();} /* * GLuint glCreateShader(GLenum shaderType) @@ -34,7 +34,7 @@ function glCreateShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): /* * void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length) */ -function glShaderSource(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, count: llvm.Value, sources: llvm.Value, length: llvm.Value) { +function glShaderSource(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, count: llvm.Value, sources: llvm.Value, lengths: llvm.Value): llvm.Value { let func: llvm.Function = emitter.mod.getFunction("glShaderSource"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); @@ -42,13 +42,13 @@ function glShaderSource(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, count: let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glShaderSource", func_type); } - return emitter.builder.buildCall(func, [shader, count, sources, length], ""); + return emitter.builder.buildCall(func, [shader, count, sources, lengths], ""); } /* * void glCompileShader( GLuint shader) */ -function glCompileShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value) { +function glCompileShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): llvm.Value { let func: llvm.Function = emitter.mod.getFunction("glCompileShader"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); @@ -59,18 +59,18 @@ function glCompileShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value) return emitter.builder.buildCall(func, [shader_type], ""); } -function glGetShaderParameter(emitter: llvm_be.LLVMEmitter) { +function glGetShaderParameter(emitter: llvm_be.LLVMEmitter): llvm.Value { throw "not implemented yet"; } -function glGetShaderInfoLog(emitter: llvm_be.LLVMEmitter) { +function glGetShaderInfoLog(emitter: llvm_be.LLVMEmitter): llvm.Value { throw "not implemented yet"; } /* * GLuint glCreateProgram(void) */ -function glCreateProgram(emitter: llvm_be.LLVMEmitter) { +function glCreateProgram(emitter: llvm_be.LLVMEmitter): llvm.Value { let func: llvm.Function = emitter.mod.getFunction("glCreateProgram"); if (func.ref.isNull()) { let ret_type: llvm.Type = gluint(); @@ -84,7 +84,7 @@ function glCreateProgram(emitter: llvm_be.LLVMEmitter) { /* * void glAttachShader(GLuint program, GLuint shader) */ -function glAttachShader(emitter: llvm_be.LLVMEmitter, program: llvm.Value, shader: llvm.Value) { +function glAttachShader(emitter: llvm_be.LLVMEmitter, program: llvm.Value, shader: llvm.Value): llvm.Value { let func: llvm.Function = emitter.mod.getFunction("glAttachShader"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); @@ -98,7 +98,7 @@ function glAttachShader(emitter: llvm_be.LLVMEmitter, program: llvm.Value, shade /* * void glLinkProgram(GLuint program) */ -function glLinkProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value) { +function glLinkProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value): llvm.Value { let func: llvm.Function = emitter.mod.getFunction("glLinkProgram"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); @@ -109,14 +109,14 @@ function glLinkProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value) { return emitter.builder.buildCall(func, [program], ""); } -function glGetProgramParameter(emitter: llvm_be.LLVMEmitter) { +function glGetProgramParameter(emitter: llvm_be.LLVMEmitter): llvm.Value { throw "not implemented yet"; } /* * void glGetProgramInfoLog( GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog) */ -function glGetProgramInfoLog(emitter: llvm_be.LLVMEmitter, program: llvm.Value, max_length: llvm.Value, length: llvm.Value, info_log: llvm.Value) { +function glGetProgramInfoLog(emitter: llvm_be.LLVMEmitter, program: llvm.Value, max_length: llvm.Value, length: llvm.Value, info_log: llvm.Value): llvm.Value { let func: llvm.Function = emitter.mod.getFunction("glGetProgramInfoLog"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); @@ -126,11 +126,28 @@ function glGetProgramInfoLog(emitter: llvm_be.LLVMEmitter, program: llvm.Value, } return emitter.builder.buildCall(func, [program, max_length, length, info_log], ""); } - ////////////////////////////////////////// -function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, src) { - // let shader: llvm.Value = glCreateShader(emitter, llvm.ConstInt.create(shader_type, llvm.IntType.int32())); +/* + * Call printf + */ +function printf(emitter: llvm_be.LLVMEmitter, str: llvm.Value, args: llvm.Value[]): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("printf"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.IntType.int32(); + let arg_types: llvm.Type[] = [llvm.PointerType.create(llvm.IntType.int8(), 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types, true); + func = emitter.mod.addFunction("printf", func_type); + } + let _args: llvm.Value[] = []; + _args.push(str, ...args); + return emitter.builder.buildCall(func, _args, ""); +} + +function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: string) { + let shader: llvm.Value = glCreateShader(emitter, llvm.ConstInt.create(shader_type, glenum())); + + //glShaderSource(emitter, shader, llvm.ConstInt.create(1, glsizei()), sources, lengths); throw "not implemented yet"; } @@ -145,4 +162,9 @@ let compile_rules: ASTVisit = visit_binary(tree: ast.BinaryNode, emitter: llvm_be.LLVMEmitter): llvm.Value { throw "not implemented yet" }, - }); \ No newline at end of file + }); + + + + + From 551303170948fdd140f8d9d0d9a75c7762440d4c Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 8 May 2017 08:37:39 -0400 Subject: [PATCH 04/23] Continue working on opengl.ts --- src/backends/opengl.ts | 59 +++++++++++++++++++++++++++++++++--------- src/backends/webgl.ts | 4 +-- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 9d9c055..994ecc5 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -2,13 +2,14 @@ import * as llvm_be from './llvm'; import * as llvm from '../../node_modules/llvmc/src/wrapped'; import { ASTVisit, ast_visit, compose_visit } from '../visit'; import * as ast from '../ast'; +import {locsym, shadersym} from './webgl' ////////////////////////////////////////// // useful openGL bindings ////////////////////////////////////////// /** - * Methods for getting various openGL types + * Methods for getting various llvm versions of openGL types */ function glchar(): llvm.Type {return llvm.IntType.int8();} function glstring(): llvm.Type {return llvm.PointerType.create(glchar(), 0);} @@ -17,7 +18,15 @@ function gluint(): llvm.Type {return llvm.IntType.int32();} function glsizei(): llvm.Type {return llvm.IntType.int32();} function glenum(): llvm.Type {return llvm.IntType.int32();} -/* +/** + * Various constants + */ +let GL_FRAGMENT_SHADER = 0x8B30; +let GL_VERTEX_SHADER = 0x8B31; +let GL_COMPILE_STATUS = 0x8B81; +let GL_LINK_STATUS = 0x8B82; + +/** * GLuint glCreateShader(GLenum shaderType) */ function glCreateShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): llvm.Value { @@ -31,7 +40,7 @@ function glCreateShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): return emitter.builder.buildCall(func, [shader_type], ""); } -/* +/** * void glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length) */ function glShaderSource(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, count: llvm.Value, sources: llvm.Value, lengths: llvm.Value): llvm.Value { @@ -45,7 +54,7 @@ function glShaderSource(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, count: return emitter.builder.buildCall(func, [shader, count, sources, lengths], ""); } -/* +/** * void glCompileShader( GLuint shader) */ function glCompileShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): llvm.Value { @@ -67,7 +76,7 @@ function glGetShaderInfoLog(emitter: llvm_be.LLVMEmitter): llvm.Value { throw "not implemented yet"; } -/* +/** * GLuint glCreateProgram(void) */ function glCreateProgram(emitter: llvm_be.LLVMEmitter): llvm.Value { @@ -81,7 +90,7 @@ function glCreateProgram(emitter: llvm_be.LLVMEmitter): llvm.Value { return emitter.builder.buildCall(func, [], ""); } -/* +/** * void glAttachShader(GLuint program, GLuint shader) */ function glAttachShader(emitter: llvm_be.LLVMEmitter, program: llvm.Value, shader: llvm.Value): llvm.Value { @@ -95,7 +104,7 @@ function glAttachShader(emitter: llvm_be.LLVMEmitter, program: llvm.Value, shade return emitter.builder.buildCall(func, [program, shader], ""); } -/* +/** * void glLinkProgram(GLuint program) */ function glLinkProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value): llvm.Value { @@ -113,7 +122,7 @@ function glGetProgramParameter(emitter: llvm_be.LLVMEmitter): llvm.Value { throw "not implemented yet"; } -/* +/** * void glGetProgramInfoLog( GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog) */ function glGetProgramInfoLog(emitter: llvm_be.LLVMEmitter, program: llvm.Value, max_length: llvm.Value, length: llvm.Value, info_log: llvm.Value): llvm.Value { @@ -128,7 +137,7 @@ function glGetProgramInfoLog(emitter: llvm_be.LLVMEmitter, program: llvm.Value, } ////////////////////////////////////////// -/* +/** * Call printf */ function printf(emitter: llvm_be.LLVMEmitter, str: llvm.Value, args: llvm.Value[]): llvm.Value { @@ -144,11 +153,37 @@ function printf(emitter: llvm_be.LLVMEmitter, str: llvm.Value, args: llvm.Value[ return emitter.builder.buildCall(func, _args, ""); } -function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: string) { +function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: string): llvm.Value { let shader: llvm.Value = glCreateShader(emitter, llvm.ConstInt.create(shader_type, glenum())); + + let sources: llvm.ConstArray = llvm.ConstArray.create(glstring(), [llvm.ConstString.create(source, false)]); + let lengths: llvm.ConstArray = llvm.ConstArray.create(glint(), [llvm.ConstInt.create(source.length, glint())]); + glShaderSource(emitter, shader, llvm.ConstInt.create(1, glsizei()), sources, lengths); + glCompileShader(emitter, shader); + + // TODO + //if (error) { + //do stuff + //} + + return shader; +} - //glShaderSource(emitter, shader, llvm.ConstInt.create(1, glsizei()), sources, lengths); - throw "not implemented yet"; +function get_shader(emitter: llvm_be.LLVMEmitter, vertex_source: string, fragment_source: string) { + let vert = compile_glsl(emitter, GL_VERTEX_SHADER, vertex_source); + let frag = compile_glsl(emitter, GL_FRAGMENT_SHADER, fragment_source); + + let program = glCreateProgram(emitter); + glAttachShader(emitter, program, vert); + glAttachShader(emitter, program, frag); + glLinkProgram(emitter, program); + + // TODO + //if (error) { + //do stuff + //} + + return program; } // Extend the JavaScript compiler with some WebGL specifics. diff --git a/src/backends/webgl.ts b/src/backends/webgl.ts index ee9e569..93d027c 100644 --- a/src/backends/webgl.ts +++ b/src/backends/webgl.ts @@ -80,14 +80,14 @@ const GL_ATTRIBUTE_TYPES: { [_: string]: [string, string] } = { // Get a JavaScript variable name for a compiled shader program. Uses the ID // of the outermost (vertex) shader Prog. -function shadersym(progid: number) { +export function shadersym(progid: number) { return "s" + progid; } // Get a JavaScript variable name to hold a shader location. Uses the ID of // the corresponding escape expression inside the shader, or the defining // variable ID for free variables. Also needs the ID of the quote. -function locsym(scopeid: number, escid: number) { +export function locsym(scopeid: number, escid: number) { return "s" + scopeid + "l" + escid; } From d4337a3a9dd2984612a6b844397c95e658146409 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Wed, 10 May 2017 23:11:39 -0400 Subject: [PATCH 05/23] Add support for function quotes Also fixed some bugs related to functions --- src/backends/llvm.ts | 167 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 155 insertions(+), 12 deletions(-) diff --git a/src/backends/llvm.ts b/src/backends/llvm.ts index 74f1986..e88a6d9 100644 --- a/src/backends/llvm.ts +++ b/src/backends/llvm.ts @@ -1,9 +1,11 @@ import * as ast from '../ast'; import { ASTVisit, ast_visit, complete_visit } from '../visit'; -import { INT, FLOAT, Type, OverloadedType, FunType } from '../type'; +import { INT, FLOAT, Type, OverloadedType, FunType, CodeType } from '../type'; import { Proc, Prog, Variant, Scope, CompilerIR } from '../compile/ir' import * as llvm from '../../node_modules/llvmc/src/wrapped'; -import { varsym, persistsym, procsym, is_fun_type, useful_pred } from './emitutil'; +import { varsym, persistsym, procsym, progsym, variantsym, is_fun_type, useful_pred } from './emitutil'; + +export let FUNC_ANNOTATION = "js"; /////////////////////////////////////////////////////////////////// // Begin Emit Functions & Redundant Funcs @@ -37,7 +39,7 @@ export interface LLVMEmitter { // generating LLVM IR constructs. emit_expr: (tree: ast.SyntaxNode, emitter: LLVMEmitter) => llvm.Value; emit_proc: (emitter: LLVMEmitter, proc: Proc) => llvm.Value; - //emit_prog: (emitter: LLVMEmitter, prog: Prog) => llvm.Value; + emit_prog: (emitter: LLVMEmitter, prog: Prog) => llvm.Value; //emit_prog_variant: (emitter: LLVMEmitter, variant: Variant, prog: Prog) => llvm.Value; variant: Variant|null; } @@ -88,6 +90,25 @@ function emit_lookup(emitter: LLVMEmitter, emit_extern: (name: string, type: Typ } } +function emit_quote(emitter: LLVMEmitter, tree: ast.SyntaxNode): llvm.Value { + let prog = specialized_prog(emitter, tree.id!); + + // For snippet quotes, just produce the ID. This is used by the pre-splicing + // optimization to look up the corresponding pre-spliced program. + if (prog.snippet_escape !== null) { + throw "not implemented yet"; + } + + // Check whether this is a pre-spliced quote (i.e., it has variants). + let variants = emitter.ir.presplice_variants[tree.id!]; + if (variants == null) { + // No snippets to pre-splice. + return emit_quote_expr(emitter, prog, tree); + } else { + throw "Not implemented yet"; + } +} + function emit_func(emitter: LLVMEmitter, tree: ast.FunNode): llvm.Value { // get function let func: llvm.Function = emitter.mod.getFunction(procsym(tree.id!)); @@ -98,7 +119,6 @@ function emit_func(emitter: LLVMEmitter, tree: ast.FunNode): llvm.Value { // construct pointer to func let _func_type: [llvm.Type, llvm.Type[]] = get_func_type(emitter, func_as_proc.body.id!, func_as_proc.params); let func_type: llvm.FunctionType = llvm.FunctionType.create(_func_type[0], _func_type[1]); - let func_ptr: llvm.Value = emitter.builder.buildAlloca(func_type, "funcptr"); // get values/types of free vars let free_ids: number[] = emitter.ir.procs[tree.id!].free; @@ -123,7 +143,7 @@ function emit_func(emitter: LLVMEmitter, tree: ast.FunNode): llvm.Value { } // return struct that wraps the function and its environment - return llvm.ConstStruct.create([func_ptr, env_void_ptr], true); + return llvm.ConstStruct.create([func, env_void_ptr], true); } function emit_extern(name: string, type: Type): llvm.Value { @@ -144,6 +164,54 @@ function emit(emitter: LLVMEmitter, tree: ast.SyntaxNode): llvm.Value { return emitter.emit_expr(tree, emitter); } +// emit quote at function closurw +function emit_quote_func(emitter: LLVMEmitter, prog: Prog, tree: ast.SyntaxNode): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction(progsym(tree.id!)); + + // construct pointer to func + let _func_type: [llvm.Type, llvm.Type[]] = get_func_type(emitter, prog.body.id!, []); + let func_type: llvm.FunctionType = llvm.FunctionType.create(_func_type[0], _func_type[1]); + + // get values/types of free vars + let free_ids: number[] = emitter.ir.progs[tree.id!].free; + let free_vals: llvm.Value[] = []; + let free_types: llvm.Type[] = []; + for (let id of free_ids) { + free_vals.push(emitter.builder.buildLoad(emitter.named_values[id], "")); + free_types.push(llvm_type(emitter.ir.type_table[id][0])); + } + + // build an environment structure that wraps around free vals + let env_struct: llvm.Value = llvm.ConstStruct.create(free_vals, true); + let env_type: llvm.StructType = llvm.StructType.create(free_types, true); + let env_struct_ptr: llvm.Value = emitter.builder.buildAlloca(env_type, "strctptr"); + emitter.builder.buildStore(env_struct, env_struct_ptr); + let env_void_ptr: llvm.Value = emitter.builder.buildBitCast(env_struct_ptr, llvm.PointerType.create(llvm.VoidType.create(), 0), "vdptr"); + + // The function captures its closed-over references and any persists + // used inside. + for (let p of emitter.ir.progs[tree.id!].persist) { + throw "persists not implemented yet" + } + + // return struct that wraps the function and its environment + return llvm.ConstStruct.create([func, env_void_ptr], true); +} + +function emit_quote_eval(emitter: LLVMEmitter, prog: Prog, tree: ast.SyntaxNode): llvm.Value { + throw "not implemented yet"; +} + +function emit_quote_expr(emitter: LLVMEmitter, prog: Prog, tree: ast.SyntaxNode): llvm.Value { + if (prog.annotation === FUNC_ANNOTATION) { + // A function quote. + return emit_quote_func(emitter, prog, tree); + } else { + // An eval (string) quote. + return emit_quote_eval(emitter, prog, tree); + } +} + function emit_fun(emitter: LLVMEmitter, name: string, arg_ids: number[], free_ids: number[], local_ids: number[], body: ast.ExpressionNode): llvm.Value { // create function let _func_type: [llvm.Type, llvm.Type[]] = get_func_type(emitter, body.id!, arg_ids); @@ -226,10 +294,22 @@ function emit_fun(emitter: LLVMEmitter, name: string, arg_ids: number[], free_id return func; } +/** + * Get the current specialized version of a program, according to the + * emitter's current variant. + */ + function specialized_prog(emitter: LLVMEmitter, progid: number) { + let variant = emitter.variant; + if (!variant) { + return emitter.ir.progs[progid]; + } + return variant.progs[progid] || emitter.ir.progs[progid]; +} + /** * Get the current specialized version of a function. */ -export function specialized_proc(emitter: LLVMEmitter, procid: number) { +function specialized_proc(emitter: LLVMEmitter, procid: number) { let variant = emitter.variant; if (!variant) { return emitter.ir.procs[procid]; @@ -247,10 +327,13 @@ function emit_scope(emitter: LLVMEmitter, scope: number) { return emitter.emit_proc(emitter, proc); } - // TODO prog - throw "cannot handle progs yet"; + // Try a Prog. + let prog = specialized_prog(emitter, scope); + if (prog) { + return emit_prog(emitter, prog); + } - //throw "error: unknown scope id"; + throw "error: unknown scope id"; } // Compile all the Procs and progs who are children of a given scope. @@ -304,10 +387,54 @@ function emit_proc(emitter: LLVMEmitter, proc: Proc): llvm.Value { return _emit_scope_func(emitter, name, arg_ids, free_ids, proc); } -function emit_prog() { +// Compile a quotation (a.k.a. Prog) to a string constant. Also compiles the +// Procs that appear inside this quotation. +function emit_prog_eval(emitter: LLVMEmitter, prog: Prog, name: string): llvm.Value { + throw "not implemented yet"; +} + +// Emit a program as a JavaScript function declaration. This works when the +// program has no splices, and it avoids the overhead of `eval`. +function emit_prog_func(emitter: LLVMEmitter, prog: Prog, name: string): llvm.Value { + // The must be no splices. + if (prog.owned_splice.length) { + throw "error: splices not allowed in a function quote"; + } + + // Free variables become parameters. + let free_ids: number[] = []; + for (let fv of prog.free) { + free_ids.push(fv); + } + // Same with the quote's persists. + for (let esc of prog.persist) { + throw "persists not implemented yet"; + } + + return _emit_scope_func(emitter, name, [], free_ids, prog); } +// Emit a JavaScript Prog (a single variant). The backend depends on the +// annotation. +function emit_prog_decl(emitter: LLVMEmitter, prog: Prog, name: string): llvm.Value { + if (prog.annotation === FUNC_ANNOTATION) { + // A function quote. + return emit_prog_func(emitter, prog, name); + } else { + // An ordinary quote. + return emit_prog_eval(emitter, prog, name); + } +} + +/** + * Emit a single-variant program. + */ +function emit_prog(emitter: LLVMEmitter, prog: Prog): llvm.Value { + return emit_prog_decl(emitter, prog, progsym(prog.id!)); +} + + function emit_prog_variant() { } @@ -339,6 +466,22 @@ function llvm_type(type: Type): llvm.Type { // create struct environment: {function, closure environment} let struct_type: llvm.StructType = llvm.StructType.create([func_type_ptr, llvm.PointerType.create(llvm.VoidType.create(), 0)], true); return struct_type; + } else if (type instanceof CodeType) { + if (type.annotation == FUNC_ANNOTATION) { + // get arg_types and ret_type + let arg_types: llvm.Type[] = [llvm.PointerType.create(llvm.VoidType.create(), 0)]; + let ret_type: llvm.Type = llvm_type(type.inner); + + // construct appropriate func type & wrap in ptr + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + let func_type_ptr: llvm.PointerType = llvm.PointerType.create(func_type, 0); + + // create struct environment: {function, closure environment} + let struct_type: llvm.StructType = llvm.StructType.create([func_type_ptr, llvm.PointerType.create(llvm.VoidType.create(), 0)], true); + return struct_type; + } else { + throw "not implemented yet"; + } } else { throw "Unsupported type in LLVM backend: " + type; } @@ -466,7 +609,7 @@ export let compile_rules: ASTVisit = { }, visit_quote(tree: ast.QuoteNode, emitter: LLVMEmitter): llvm.Value { - throw "visit quote not implemented"; + return emit_quote(emitter, tree); }, visit_escape(tree: ast.EscapeNode, emitter: LLVMEmitter): llvm.Value { @@ -552,7 +695,7 @@ export function codegen(ir: CompilerIR): llvm.Module { named_values: [], emit_expr: (tree: ast.SyntaxNode, emitter: LLVMEmitter) => ast_visit(compile_rules, tree, emitter), emit_proc: emit_proc, - //emit_prog: emit_prog, + emit_prog: emit_prog, //emit_prog_variant: emit_prog_variant, variant: null, }; From 34853e5a63cb7eb5315210882094872b6af5d9e6 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Thu, 11 May 2017 04:03:39 -0400 Subject: [PATCH 06/23] Start codegen function --- src/backends/llvm.ts | 8 ++--- src/backends/opengl.ts | 79 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/src/backends/llvm.ts b/src/backends/llvm.ts index e88a6d9..f53a4c0 100644 --- a/src/backends/llvm.ts +++ b/src/backends/llvm.ts @@ -361,7 +361,7 @@ function _emit_scope_func(emitter: LLVMEmitter, name: string, arg_ids: number[], return func; } -function emit_proc(emitter: LLVMEmitter, proc: Proc): llvm.Value { +export function emit_proc(emitter: LLVMEmitter, proc: Proc): llvm.Value { // The arguments consist of the actual parameters, the closure environment // (free variables), and the persists used inside the function. let arg_ids: number[] = []; @@ -430,12 +430,12 @@ function emit_prog_decl(emitter: LLVMEmitter, prog: Prog, name: string): llvm.Va /** * Emit a single-variant program. */ -function emit_prog(emitter: LLVMEmitter, prog: Prog): llvm.Value { +export function emit_prog(emitter: LLVMEmitter, prog: Prog): llvm.Value { return emit_prog_decl(emitter, prog, progsym(prog.id!)); } -function emit_prog_variant() { +export function emit_prog_variant() { } @@ -719,6 +719,6 @@ export function codegen(ir: CompilerIR): llvm.Module { * Emit the main function (and all the functions it depends on, eventually) * into the specified LLVM module. */ -function emit_main(emitter: LLVMEmitter): llvm.Value { +export function emit_main(emitter: LLVMEmitter): llvm.Value { return emit_proc(emitter, emitter.ir.main); } diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 994ecc5..af9aae5 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -1,7 +1,10 @@ +import { CompilerIR, Prog, Variant } from '../compile/ir'; import * as llvm_be from './llvm'; import * as llvm from '../../node_modules/llvmc/src/wrapped'; import { ASTVisit, ast_visit, compose_visit } from '../visit'; import * as ast from '../ast'; +import { Glue, emit_glue, vtx_expr, render_expr, ProgKind, prog_kind, + FLOAT4X4, SHADER_ANNOTATION, TEXTURE } from './gl'; import {locsym, shadersym} from './webgl' ////////////////////////////////////////// @@ -68,10 +71,16 @@ function glCompileShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): return emitter.builder.buildCall(func, [shader_type], ""); } -function glGetShaderParameter(emitter: llvm_be.LLVMEmitter): llvm.Value { +/** + * void glGetShaderiv( GLuint shader, GLenum pname, GLint *params) + */ +function glGetShaderParameter(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, pname: llvm.Value): llvm.Value { throw "not implemented yet"; } +/** + * void glGetShaderInfoLog( GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog); + */ function glGetShaderInfoLog(emitter: llvm_be.LLVMEmitter): llvm.Value { throw "not implemented yet"; } @@ -118,6 +127,9 @@ function glLinkProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value): llvm. return emitter.builder.buildCall(func, [program], ""); } +/* + *void glGetProgramiv( GLuint program, GLenum pname, GLint *params); +*/ function glGetProgramParameter(emitter: llvm_be.LLVMEmitter): llvm.Value { throw "not implemented yet"; } @@ -199,6 +211,71 @@ let compile_rules: ASTVisit = }, }); +function emit_glsl_prog(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Variant | null): llvm.Value { + throw "not implemented yet"; +} + +// Compile the IR to a JavaScript program that uses WebGL and GLSL. +export function codegen(ir: CompilerIR): llvm.Module { + llvm.initX86Target(); + // Set up the emitter, which includes the LLVM IR builder. + let builder = llvm.Builder.create(); + // Create a module. This is where all the generated code will go. + let mod: llvm.Module = llvm.Module.create("braidprogram"); + // Set the target triple and data layout + let target_triple: string = llvm.TargetMachine.getDefaultTargetTriple(); + let target = llvm.Target.getFromTriple(target_triple); + let target_machine = llvm.TargetMachine.create(target, target_triple); + let data_layout = target_machine.getTargetMachineData().toString(); + + mod.setTarget(target_triple); + mod.setDataLayout(data_layout); + + let emitter: llvm_be.LLVMEmitter = { + mod: mod, + builder: builder, + named_values: [], + ir: ir, + emit_expr: (tree: ast.SyntaxNode, emitter: llvm_be.LLVMEmitter) => + ast_visit(compile_rules, tree, emitter), + + emit_proc: llvm_be.emit_proc, + + emit_prog(emitter: llvm_be.LLVMEmitter, prog: Prog): llvm.Value { + // Choose between emitting JavaScript and GLSL. + if (prog.annotation === SHADER_ANNOTATION) { + return emit_glsl_prog(emitter, prog, null); + } else { + return llvm_be.emit_prog(emitter, prog); + } + }, + + // emit_prog_variant(emitter: llvm_be.LLVMEmitter, variant: Variant, prog: Prog) { + // if (prog.annotation === SHADER_ANNOTATION) { + // return emit_glsl_prog(emitter, prog, variant); + // } else { + // return js.emit_prog_variant(emitter, variant, prog); + // } + // }, + + variant: null, + }; + + // Generate the main function into the module. + llvm_be.emit_main(emitter); + + // TODO: We currently just log the IR and then free the module. Eventually, + // we'd like to return the module to the caller so it can do whatever it + // wants with the result---at the moment, we return a dangling pointer! + console.log(emitter.mod.toString()); + emitter.mod.free(); + + // Now that we're done generating code, we can free the IR builder. + emitter.builder.free(); + + return emitter.mod; +} + From 8fd668b9b72291e90b027ec99288ecfc218b4e9d Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Thu, 11 May 2017 04:54:11 -0400 Subject: [PATCH 07/23] Start emit_glsl_prog --- src/backends/emitter.ts | 5 +++-- src/backends/gl.ts | 3 ++- src/backends/glsl.ts | 3 ++- src/backends/llvm.ts | 24 +----------------------- src/backends/opengl.ts | 29 ++++++++++++++++++++++++++++- 5 files changed, 36 insertions(+), 28 deletions(-) diff --git a/src/backends/emitter.ts b/src/backends/emitter.ts index 1e00d4f..08820bf 100644 --- a/src/backends/emitter.ts +++ b/src/backends/emitter.ts @@ -7,6 +7,7 @@ import { SyntaxNode } from '../ast'; import { Proc, Prog, CompilerIR, Variant } from '../compile/ir'; import { assign } from '../util'; +import { LLVMEmitter } from './llvm' /** * A structure specifying a code-generation backend and its state. @@ -59,7 +60,7 @@ export function emit_main(emitter: Emitter) { * Get the current specialized version of a program, according to the * emitter's current variant. */ -export function specialized_prog(emitter: Emitter, progid: number) { +export function specialized_prog(emitter: Emitter|LLVMEmitter, progid: number) { let variant = emitter.variant; if (!variant) { return emitter.ir.progs[progid]; @@ -70,7 +71,7 @@ export function specialized_prog(emitter: Emitter, progid: number) { /** * Get the current specialized version of a function. */ -export function specialized_proc(emitter: Emitter, procid: number) { +export function specialized_proc(emitter: Emitter|LLVMEmitter, procid: number) { let variant = emitter.variant; if (!variant) { return emitter.ir.procs[procid]; diff --git a/src/backends/gl.ts b/src/backends/gl.ts index b032795..1cec296 100644 --- a/src/backends/gl.ts +++ b/src/backends/gl.ts @@ -18,6 +18,7 @@ import { CompilerIR, Prog, nearest_quote } from '../compile/ir'; import { varsym } from './emitutil'; import { Emitter, specialized_prog } from './emitter'; import { FUNC_ANNOTATION } from './js'; +import { LLVMEmitter } from './llvm' // General OpenGL-related backend components. @@ -470,6 +471,6 @@ function get_glue(ir: CompilerIR, prog: Prog): Glue[] { * Eventually, it would be nice to pre-compute or memoize this. At the moment, * we may be re-computing this many times. */ -export function emit_glue(emitter: Emitter, progid: number) { +export function emit_glue(emitter: Emitter|LLVMEmitter, progid: number) { return get_glue(emitter.ir, specialized_prog(emitter, progid)); } diff --git a/src/backends/glsl.ts b/src/backends/glsl.ts index 3e45e39..e6f9ce7 100644 --- a/src/backends/glsl.ts +++ b/src/backends/glsl.ts @@ -10,6 +10,7 @@ import { Emitter, emit, specialized_prog } from './emitter'; import { varsym, indent, emit_seq, emit_assign, emit_lookup, emit_if, emit_while, emit_body, paren, splicesym } from './emitutil'; import { CompilerIR, nearest_quote, Variant } from '../compile/ir'; +import { LLVMEmitter } from './llvm' // Type checking for uniforms, which are automatically demoted from arrays to // individual values when they persist. @@ -241,7 +242,7 @@ let compile_rules: ASTVisit = { // Emitting the surrounding machinery for communicating between stages. -export function compile_prog(parent_emitter: Emitter, progid: number): string +export function compile_prog(parent_emitter: Emitter|LLVMEmitter, progid: number): string { let ir = parent_emitter.ir; let emitter: Emitter = { diff --git a/src/backends/llvm.ts b/src/backends/llvm.ts index f53a4c0..814725f 100644 --- a/src/backends/llvm.ts +++ b/src/backends/llvm.ts @@ -4,6 +4,7 @@ import { INT, FLOAT, Type, OverloadedType, FunType, CodeType } from '../type'; import { Proc, Prog, Variant, Scope, CompilerIR } from '../compile/ir' import * as llvm from '../../node_modules/llvmc/src/wrapped'; import { varsym, persistsym, procsym, progsym, variantsym, is_fun_type, useful_pred } from './emitutil'; +import { specialized_prog, specialized_proc } from './emitter'; export let FUNC_ANNOTATION = "js"; @@ -294,29 +295,6 @@ function emit_fun(emitter: LLVMEmitter, name: string, arg_ids: number[], free_id return func; } -/** - * Get the current specialized version of a program, according to the - * emitter's current variant. - */ - function specialized_prog(emitter: LLVMEmitter, progid: number) { - let variant = emitter.variant; - if (!variant) { - return emitter.ir.progs[progid]; - } - return variant.progs[progid] || emitter.ir.progs[progid]; -} - -/** - * Get the current specialized version of a function. - */ -function specialized_proc(emitter: LLVMEmitter, procid: number) { - let variant = emitter.variant; - if (!variant) { - return emitter.ir.procs[procid]; - } - return variant.procs[procid] || emitter.ir.procs[procid]; -} - /* * Emit either kind of scope */ diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index af9aae5..8ed1b18 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -2,7 +2,10 @@ import { CompilerIR, Prog, Variant } from '../compile/ir'; import * as llvm_be from './llvm'; import * as llvm from '../../node_modules/llvmc/src/wrapped'; import { ASTVisit, ast_visit, compose_visit } from '../visit'; +import { progsym, paren, variant_suffix } from './emitutil'; import * as ast from '../ast'; +import * as js from './js'; +import * as glsl from './glsl'; import { Glue, emit_glue, vtx_expr, render_expr, ProgKind, prog_kind, FLOAT4X4, SHADER_ANNOTATION, TEXTURE } from './gl'; import {locsym, shadersym} from './webgl' @@ -212,7 +215,31 @@ let compile_rules: ASTVisit = }); function emit_glsl_prog(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Variant | null): llvm.Value { - throw "not implemented yet"; + // Emit subprograms. + for (let subid of prog.quote_children) { + let subprog = emitter.ir.progs[subid]; + if (subprog.annotation !== SHADER_ANNOTATION) { + throw "error: subprograms not allowed in shaders"; + } + emit_glsl_prog(emitter, subprog, variant) + let ptr = emitter.builder.buildAlloca(llvm.PointerType.create(llvm.IntType.int8(), 0), ""); + emitter.builder.buildStore(, ptr); + } + + // Emit the shader program. + let code = glsl.compile_prog(emitter, prog.id!); + let name = progsym(prog.id!) + variant_suffix(variant); + + let ptr = emitter.builder.buildAlloca(llvm.PointerType.create(llvm.IntType.int8(), 0), name); + emitter.builder.buildStore(llvm.ConstString.create(js.emit_string(code), false), ptr); + + // If it's a *vertex shader* quote (i.e., a top-level shader quote), + // emit its setup code too. + if (prog_kind(emitter.ir, prog.id!) === ProgKind.vertex) { + out += emit_shader_setup(emitter, prog.id!, variant); + } + + return ptr; } // Compile the IR to a JavaScript program that uses WebGL and GLSL. From 02a5e1b19a36cfa835948aefa8379e147534403d Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 22 May 2017 12:53:51 -0400 Subject: [PATCH 08/23] Continue working on opengl codegen and its dependencies --- src/backends/opengl.ts | 57 ++++++++++++++++++++++++++++++++++-------- src/backends/webgl.ts | 2 +- 2 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 8ed1b18..0f8b530 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -8,7 +8,12 @@ import * as js from './js'; import * as glsl from './glsl'; import { Glue, emit_glue, vtx_expr, render_expr, ProgKind, prog_kind, FLOAT4X4, SHADER_ANNOTATION, TEXTURE } from './gl'; -import {locsym, shadersym} from './webgl' +import {locsym, shadersym, get_prog_pair} from './webgl' + +//////////////////////////////////////////// +// TODO: Pass around instead of global +//////////////////////////////////////////// +let str_lens = []; ////////////////////////////////////////// // useful openGL bindings @@ -168,11 +173,11 @@ function printf(emitter: llvm_be.LLVMEmitter, str: llvm.Value, args: llvm.Value[ return emitter.builder.buildCall(func, _args, ""); } -function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: string): llvm.Value { +function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: llvm.Value, len: number): llvm.Value { let shader: llvm.Value = glCreateShader(emitter, llvm.ConstInt.create(shader_type, glenum())); - let sources: llvm.ConstArray = llvm.ConstArray.create(glstring(), [llvm.ConstString.create(source, false)]); - let lengths: llvm.ConstArray = llvm.ConstArray.create(glint(), [llvm.ConstInt.create(source.length, glint())]); + let sources: llvm.ConstArray = llvm.ConstArray.create(glstring(), [source]); + let lengths: llvm.ConstArray = llvm.ConstArray.create(glint(), [llvm.ConstInt.create(len, glint())]); glShaderSource(emitter, shader, llvm.ConstInt.create(1, glsizei()), sources, lengths); glCompileShader(emitter, shader); @@ -184,9 +189,9 @@ function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: return shader; } -function get_shader(emitter: llvm_be.LLVMEmitter, vertex_source: string, fragment_source: string) { - let vert = compile_glsl(emitter, GL_VERTEX_SHADER, vertex_source); - let frag = compile_glsl(emitter, GL_FRAGMENT_SHADER, fragment_source); +function get_shader(emitter: llvm_be.LLVMEmitter, vertex_source: llvm.Value, vertex_len: number, fragment_source: llvm.Value, fragment_len: number) { + let vert = compile_glsl(emitter, GL_VERTEX_SHADER, vertex_source, vertex_len); + let frag = compile_glsl(emitter, GL_FRAGMENT_SHADER, fragment_source, fragment_len); let program = glCreateProgram(emitter); glAttachShader(emitter, program, vert); @@ -214,6 +219,38 @@ let compile_rules: ASTVisit = }, }); +// TODO: handle splices and things!! +function emit_shader_code_ref(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Variant|null): llvm.Value { + //let code_expr = progsym(prog.id!) + variant_suffix(variant); + for (let esc of prog.owned_splice) { + throw "not implemented yet"; + } + return emitter.builder.buildLoad(emitter.named_values[prog.id!], ""); // TODO: use code_expr instead of prog.id to look up ptr? +} + +// Emit the setup declarations for a shader program. Takes the ID of a vertex +// (top-level) shader program. +function emit_shader_setup(emitter: llvm_be.LLVMEmitter, progid: number, variant: Variant | null): llvm.Value { + let [vertex_prog, fragment_prog] = get_prog_pair(emitter.ir, progid); + + // Compile and link the shader program. + let vtx_code = emit_shader_code_ref(emitter, vertex_prog, variant); + let frag_code = emit_shader_code_ref(emitter, fragment_prog, variant); + let name = shadersym(vertex_prog.id!) + variant_suffix(variant); + get_shader(emitter, vtx_code, str_lens[vertex_prog.id!], frag_code, str_lens[fragment_prog.id!]); // TODO: str_lens...un-global? change to name->val map? + + // Get the variable locations, for both explicit persists and for free + // variables. + // let glue = emit_glue(emitter, vertex_prog.id!); + // for (let g of glue) { + // out += emit_loc_var(vertex_prog.id!, g.attribute, g.name, g.id, + // variant) + "\n"; + // } + + // return out; + throw "not implemented yet"; +} + function emit_glsl_prog(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Variant | null): llvm.Value { // Emit subprograms. for (let subid of prog.quote_children) { @@ -222,8 +259,6 @@ function emit_glsl_prog(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Varia throw "error: subprograms not allowed in shaders"; } emit_glsl_prog(emitter, subprog, variant) - let ptr = emitter.builder.buildAlloca(llvm.PointerType.create(llvm.IntType.int8(), 0), ""); - emitter.builder.buildStore(, ptr); } // Emit the shader program. @@ -232,11 +267,13 @@ function emit_glsl_prog(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Varia let ptr = emitter.builder.buildAlloca(llvm.PointerType.create(llvm.IntType.int8(), 0), name); emitter.builder.buildStore(llvm.ConstString.create(js.emit_string(code), false), ptr); + emitter.named_values[prog.id!] = ptr; // TODO: should we change named_values to map name -> ptr?? + str_lens[prog.id!] = code.length; // TODO: un-global? change to name->val map? // If it's a *vertex shader* quote (i.e., a top-level shader quote), // emit its setup code too. if (prog_kind(emitter.ir, prog.id!) === ProgKind.vertex) { - out += emit_shader_setup(emitter, prog.id!, variant); + return emit_shader_setup(emitter, prog.id!, variant); } return ptr; diff --git a/src/backends/webgl.ts b/src/backends/webgl.ts index 93d027c..eadfa83 100644 --- a/src/backends/webgl.ts +++ b/src/backends/webgl.ts @@ -91,7 +91,7 @@ export function locsym(scopeid: number, escid: number) { return "s" + scopeid + "l" + escid; } -function get_prog_pair(ir: CompilerIR, progid: number) { +export function get_prog_pair(ir: CompilerIR, progid: number) { let vertex_prog = ir.progs[progid]; // Get the fragment program. From 7a62991e69f5c78df2d7cc41e6488bff69a451bc Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 22 May 2017 14:12:59 -0400 Subject: [PATCH 09/23] Fix some typos --- src/backends/llvm.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backends/llvm.ts b/src/backends/llvm.ts index b96445b..b7943b7 100644 --- a/src/backends/llvm.ts +++ b/src/backends/llvm.ts @@ -440,7 +440,7 @@ function llvm_type(type: Type): llvm.Type { let arg_types: llvm.Type[] = []; for (let arg of type.params) arg_types.push(llvm_type(arg)); - arg_types.push FUNC_ENV_TYPE); + arg_types.push(FUNC_ENV_TYPE); let ret_type: llvm.Type = llvm_type(type.ret); // construct appropriate func type & wrap in ptr @@ -453,7 +453,7 @@ function llvm_type(type: Type): llvm.Type { } else if (type instanceof CodeType) { if (type.annotation == FUNC_ANNOTATION) { // get arg_types and ret_type - let arg_types: llvm.Type[] = FUNC_ENV_TYPE]; + let arg_types: llvm.Type[] = [FUNC_ENV_TYPE]; let ret_type: llvm.Type = llvm_type(type.inner); // construct appropriate func type & wrap in ptr @@ -479,7 +479,7 @@ function get_func_type(emitter: LLVMEmitter, ret_id: number, arg_ids: number[]): let arg_types: llvm.Type[] = []; for (let id of arg_ids) arg_types.push(llvm_type(emitter.ir.type_table[id][0])); - arg_types.push FUNC_ENV_TYPE); // closure environment struct ptr + arg_types.push(FUNC_ENV_TYPE); // closure environment struct ptr return [ret_type, arg_types]; } From cd0151d35f03bcead3daf0024acae518fbca0116 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 22 May 2017 16:27:01 -0400 Subject: [PATCH 10/23] finish emit_shader_setup/emit_loc_var & add string->ptr named_values2 map as temporary fix --- src/backends/llvm.ts | 7 +++ src/backends/opengl.ts | 100 +++++++++++++++++++++++++++++++++-------- 2 files changed, 88 insertions(+), 19 deletions(-) diff --git a/src/backends/llvm.ts b/src/backends/llvm.ts index b7943b7..0102a59 100644 --- a/src/backends/llvm.ts +++ b/src/backends/llvm.ts @@ -35,7 +35,9 @@ export interface LLVMEmitter { /** * Map from id's to Alloca ptr's */ + // TODO: rectifiy named_values and named_values2 named_values: llvm.Value[]; + named_values2: {[key: string]: llvm.Value;}; /** * Program we are compiling @@ -238,6 +240,9 @@ function emit_fun(emitter: LLVMEmitter, name: string, arg_ids: number[], free_id let old_named_values: llvm.Value[] = emitter.named_values emitter.named_values = []; + let old_named_values2 = emitter.named_values2; + emitter.named_values2 = {}; + // make allocas for args for (let i = 0; i < arg_ids.length; i++) { // get arg id & type @@ -297,6 +302,7 @@ function emit_fun(emitter: LLVMEmitter, name: string, arg_ids: number[], free_id emitter.builder.free(); emitter.builder = old_builder; emitter.named_values = old_named_values; + emitter.named_values2 = old_named_values2; return func; } @@ -678,6 +684,7 @@ export function codegen(ir: CompilerIR): llvm.Module { mod: mod, builder: builder, named_values: [], + named_values2: {}, emit_expr: (tree: ast.SyntaxNode, emitter: LLVMEmitter) => ast_visit(compile_rules, tree, emitter), emit_proc: emit_proc, emit_prog: emit_prog, diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 288f341..e42e192 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -11,9 +11,20 @@ import { Glue, emit_glue, vtx_expr, render_expr, ProgKind, prog_kind, import {locsym, shadersym, get_prog_pair} from './webgl' //////////////////////////////////////////// -// TODO: Pass around instead of global +// Handling llvm string lengths //////////////////////////////////////////// -let str_lens = []; + +// TODO: Just use map for now...will probably need to change this eventually +let str_lens: {[id: string]: number} = {}; + +/** + * Function for getting string length. + * All length lookups will be from here, so will just need to change this + * method when find better way to handle string lengths + */ +function get_code_length(id: number) { + return str_lens[id]; +} ////////////////////////////////////////// // useful openGL bindings @@ -155,6 +166,34 @@ function glGetProgramInfoLog(emitter: llvm_be.LLVMEmitter, program: llvm.Value, } return emitter.builder.buildCall(func, [program, max_length, length, info_log], ""); } + +/** + * GLint glGetAttribLocation(GLuint program, const GLchar *name); + */ +function glGetAttribLocation(emitter: llvm_be.LLVMEmitter, program: llvm.Value, name: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glGetAttribLocation"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = glint(); + let arg_types: llvm.Type[] = [gluint(), glstring()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glGetAttribLocation", func_type); + } + return emitter.builder.buildCall(func, [program, name], ""); +} + +/** + * GLint glGetUniformLocation(GLuint program, const GLchar *name) + */ +function glGetUniformLocation(emitter: llvm_be.LLVMEmitter, program: llvm.Value, name: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glGetUniformLocation"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = glint(); + let arg_types: llvm.Type[] = [gluint(), glstring()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glGetUniformLocation", func_type); + } + return emitter.builder.buildCall(func, [program, name], ""); +} ////////////////////////////////////////// /** @@ -189,7 +228,7 @@ function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: return shader; } -function get_shader(emitter: llvm_be.LLVMEmitter, vertex_source: llvm.Value, vertex_len: number, fragment_source: llvm.Value, fragment_len: number) { +function get_shader(emitter: llvm_be.LLVMEmitter, vertex_source: llvm.Value, vertex_len: number, fragment_source: llvm.Value, fragment_len: number): llvm.Value { let vert = compile_glsl(emitter, GL_VERTEX_SHADER, vertex_source, vertex_len); let frag = compile_glsl(emitter, GL_FRAGMENT_SHADER, fragment_source, fragment_len); @@ -211,21 +250,39 @@ let compile_rules: ASTVisit = compose_visit(llvm_be.compile_rules, { // Compile calls to our intrinsics for binding shaders. visit_call(tree: ast.CallNode, emitter: llvm_be.LLVMEmitter): llvm.Value { - throw "not implemented yet" + throw "not implemented yet"; }, visit_binary(tree: ast.BinaryNode, emitter: llvm_be.LLVMEmitter): llvm.Value { - throw "not implemented yet" + throw "not implemented yet"; }, }); // TODO: handle splices and things!! function emit_shader_code_ref(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Variant|null): llvm.Value { - //let code_expr = progsym(prog.id!) + variant_suffix(variant); + let code_expr = progsym(prog.id!) + variant_suffix(variant); for (let esc of prog.owned_splice) { throw "not implemented yet"; } - return emitter.builder.buildLoad(emitter.named_values[prog.id!], ""); // TODO: use code_expr instead of prog.id to look up ptr? + return emitter.builder.buildLoad(emitter.named_values2[code_expr], ""); +} + +function emit_loc_var(emitter: llvm_be.LLVMEmitter, scopeid: number, attribute: boolean, varname: string, varid: number, variant: Variant | null): llvm.Value { + let shader = shadersym(scopeid) + variant_suffix(variant); + let prog_ptr = emitter.named_values2[shader]; + let program = emitter.builder.buildLoad(prog_ptr, ""); + + let name = locsym(scopeid, varid) + variant_suffix(variant); + let ptr = emitter.builder.buildAlloca(glint(), name); + let value; + if (attribute) { + value = glGetAttribLocation(emitter, program, llvm.ConstString.create(name, true)); + } else { + value = glGetUniformLocation(emitter, program, llvm.ConstString.create(name, true)); + } + emitter.builder.buildStore(value, ptr); + emitter.named_values2[name] = ptr; + return ptr; } // Emit the setup declarations for a shader program. Takes the ID of a vertex @@ -237,18 +294,21 @@ function emit_shader_setup(emitter: llvm_be.LLVMEmitter, progid: number, variant let vtx_code = emit_shader_code_ref(emitter, vertex_prog, variant); let frag_code = emit_shader_code_ref(emitter, fragment_prog, variant); let name = shadersym(vertex_prog.id!) + variant_suffix(variant); - get_shader(emitter, vtx_code, str_lens[vertex_prog.id!], frag_code, str_lens[fragment_prog.id!]); // TODO: str_lens...un-global? change to name->val map? + + let program = get_shader(emitter, vtx_code, get_code_length(vertex_prog.id!), frag_code, get_code_length(fragment_prog.id!)); + let ptr = emitter.builder.buildAlloca(gluint(), name); + emitter.builder.buildStore(program, ptr); + + emitter.named_values2[name] = ptr; // Get the variable locations, for both explicit persists and for free // variables. - // let glue = emit_glue(emitter, vertex_prog.id!); - // for (let g of glue) { - // out += emit_loc_var(vertex_prog.id!, g.attribute, g.name, g.id, - // variant) + "\n"; - // } - - // return out; - throw "not implemented yet"; + let glue = emit_glue(emitter, vertex_prog.id!); + let val; + for (let g of glue) { + val = emit_loc_var(emitter, vertex_prog.id!, g.attribute, g.name, g.id, variant); + } + return val; } function emit_glsl_prog(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Variant | null): llvm.Value { @@ -267,8 +327,9 @@ function emit_glsl_prog(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Varia let ptr = emitter.builder.buildAlloca(llvm.PointerType.create(llvm.IntType.int8(), 0), name); emitter.builder.buildStore(llvm.ConstString.create(js.emit_string(code), false), ptr); - emitter.named_values[prog.id!] = ptr; // TODO: should we change named_values to map name -> ptr?? - str_lens[prog.id!] = code.length; // TODO: un-global? change to name->val map? + + emitter.named_values2[name] = ptr; + str_lens[name] = code.length; // TODO: str_lens // If it's a *vertex shader* quote (i.e., a top-level shader quote), // emit its setup code too. @@ -298,7 +359,8 @@ export function codegen(ir: CompilerIR): llvm.Module { let emitter: llvm_be.LLVMEmitter = { mod: mod, builder: builder, - named_values: [], + named_values: [], // TODO: rectify named_values and named_values2 + named_values2: {}, ir: ir, emit_expr: (tree: ast.SyntaxNode, emitter: llvm_be.LLVMEmitter) => ast_visit(compile_rules, tree, emitter), From a14e851a2e97b666ae25dbff01dd268d16630c42 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 22 May 2017 16:58:59 -0400 Subject: [PATCH 11/23] Start visit_call and dependencies --- src/backends/llvm.ts | 2 +- src/backends/opengl.ts | 43 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/backends/llvm.ts b/src/backends/llvm.ts index 0102a59..7cfdf89 100644 --- a/src/backends/llvm.ts +++ b/src/backends/llvm.ts @@ -169,7 +169,7 @@ function emit_extern(name: string, type: Type): llvm.Value { } // mostly a copy of emitter function -function emit(emitter: LLVMEmitter, tree: ast.SyntaxNode): llvm.Value { +export function emit(emitter: LLVMEmitter, tree: ast.SyntaxNode): llvm.Value { return emitter.emit_expr(tree, emitter); } diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index e42e192..2fff0ba 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -245,12 +245,53 @@ function get_shader(emitter: llvm_be.LLVMEmitter, vertex_source: llvm.Value, ver return program; } +function emit_shader_binding_variant(emitter: llvm_be.LLVMEmitter, progid: number, variant: Variant | null): llvm.Value { + throw "not implemented yet"; +} + +function emit_shader_binding(emitter: llvm_be.LLVMEmitter, progid: number): llvm.Value { + // Check whether this shader has variants. + let variants = emitter.ir.presplice_variants[progid]; + if (variants === null) { + // No variants. + return emit_shader_binding_variant(emitter, progid, null); + } else { + // Variants exist. Emit the selector. + //return js.emit_variant_selector( + // emitter, emitter.ir.progs[progid], variants, + // (variant) => { + // return emit_shader_binding_variant(emitter, progid, variant); + // } + //); + } + + throw "not implemented yet"; +} + // Extend the JavaScript compiler with some WebGL specifics. let compile_rules: ASTVisit = compose_visit(llvm_be.compile_rules, { // Compile calls to our intrinsics for binding shaders. visit_call(tree: ast.CallNode, emitter: llvm_be.LLVMEmitter): llvm.Value { - throw "not implemented yet"; + // Check for the intrinsic that indicates a shader invocation. + if (vtx_expr(tree)) { + // For the moment, we require a literal quote so we can statically + // emit the bindings. + if (tree.args[0].tag === "quote") { + let quote = tree.args[0] as ast.QuoteNode; + return emit_shader_binding(emitter, quote.id!); + } else { + throw "dynamic `vtx` calls unimplemented"; + } + + // And our intrinsic for indicating the rendering stage. + } else if (render_expr(tree)) { + // Pass through the code argument. + return llvm_be.emit(emitter, tree.args[0]); + } + + // An ordinary function call. + return ast_visit(llvm_be.compile_rules, tree, emitter); }, visit_binary(tree: ast.BinaryNode, emitter: llvm_be.LLVMEmitter): llvm.Value { From 91d23bcc0406e8ddd6c55c3a5c33a7cb248a031b Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 22 May 2017 17:07:21 -0400 Subject: [PATCH 12/23] Start visit_binary --- src/backends/opengl.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 2fff0ba..20ee7a6 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -295,7 +295,19 @@ let compile_rules: ASTVisit = }, visit_binary(tree: ast.BinaryNode, emitter: llvm_be.LLVMEmitter): llvm.Value { - throw "not implemented yet"; + // If this is a matrix/matrix multiply, emit a function call. + if (tree.op === "*") { + let [typ,] = emitter.ir.type_table[tree.id!]; + if (typ === FLOAT4X4) { + let lhs = llvm_be.emit(emitter, tree.lhs); + let rhs = llvm_be.emit(emitter, tree.rhs); + throw "not implemented yet"; + //return `mat4mult(${lhs}, ${rhs})`; + } + } + + // Otherwise, use the ordinary JavaScript backend. + return ast_visit(llvm_be.compile_rules, tree, emitter); }, }); From e1a8b8dc3af0abd87baea6c1e2724af82f5eda0a Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Tue, 23 May 2017 09:58:59 -0400 Subject: [PATCH 13/23] Finish emit_param_bindings --- src/backends/opengl.ts | 335 +++++++++++++++++++++++++++++++++++++++-- src/backends/webgl.ts | 2 +- 2 files changed, 326 insertions(+), 11 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 20ee7a6..0f18156 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -6,9 +6,11 @@ import { progsym, paren, variant_suffix } from './emitutil'; import * as ast from '../ast'; import * as js from './js'; import * as glsl from './glsl'; +import { Type, PrimitiveType } from '../type'; import { Glue, emit_glue, vtx_expr, render_expr, ProgKind, prog_kind, FLOAT4X4, SHADER_ANNOTATION, TEXTURE } from './gl'; -import {locsym, shadersym, get_prog_pair} from './webgl' +import { assign } from '../util'; +import {locsym, shadersym, get_prog_pair, GL_UNIFORM_FUNCTIONS} from './webgl' //////////////////////////////////////////// // Handling llvm string lengths @@ -33,21 +35,33 @@ function get_code_length(id: number) { /** * Methods for getting various llvm versions of openGL types */ -function glchar(): llvm.Type {return llvm.IntType.int8();} -function glstring(): llvm.Type {return llvm.PointerType.create(glchar(), 0);} -function glint(): llvm.Type {return llvm.IntType.int32();} -function gluint(): llvm.Type {return llvm.IntType.int32();} -function glsizei(): llvm.Type {return llvm.IntType.int32();} -function glenum(): llvm.Type {return llvm.IntType.int32();} +function glvoid(): llvm.Type {return llvm.PointerType.create(llvm.IntType.int8(), 0);} +function glchar(): llvm.Type {return llvm.IntType.int8();} +function glstring(): llvm.Type {return llvm.PointerType.create(glchar(), 0);} +function glboolean(): llvm.Type {return llvm.IntType.int1();} +function glint(): llvm.Type {return llvm.IntType.int32();} +function gluint(): llvm.Type {return llvm.IntType.int32();} +function glsizei(): llvm.Type {return llvm.IntType.int32();} +function glenum(): llvm.Type {return llvm.IntType.int32();} +function glfloat(): llvm.Type {return llvm.FloatType.float();} /** * Various constants */ +let GL_TEXTURE_2D = 0x0DE1; +let GL_FLOAT = 0x1406; +let GL_TEXTURE0 = 0x84C0; +let GL_ARRAY_BUFFER = 0x8892; //TODO: check this one let GL_FRAGMENT_SHADER = 0x8B30; let GL_VERTEX_SHADER = 0x8B31; let GL_COMPILE_STATUS = 0x8B81; let GL_LINK_STATUS = 0x8B82; +const GL_ATTRIBUTE_TYPES: { [_: string]: [number, number] } = { + "Float2": [2, GL_FLOAT], + "Float3": [3, GL_FLOAT], +}; + /** * GLuint glCreateShader(GLenum shaderType) */ @@ -194,6 +208,204 @@ function glGetUniformLocation(emitter: llvm_be.LLVMEmitter, program: llvm.Value, } return emitter.builder.buildCall(func, [program, name], ""); } + +/** + * void glUseProgram(GLuint program) + */ +function glUseProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glUseProgram"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [gluint()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glUseProgram", func_type); + } + return emitter.builder.buildCall(func, [program], ""); +} + +/** + * void glActiveTexture(GLenum texture); + */ +function glActiveTexture(emitter: llvm_be.LLVMEmitter, texture: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glActiveTexture"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glenum()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glActiveTexture", func_type); + } + return emitter.builder.buildCall(func, [texture], ""); +} + +/** + * void glBindTexture(GLenum target, GLuint texture); + */ +function glBindTexture(emitter: llvm_be.LLVMEmitter, target: llvm.Value, texture: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glBindTexture"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glenum(), gluint()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glBindTexture", func_type); + } + return emitter.builder.buildCall(func, [target, texture], ""); +} + +/** + * void glUniform1i(GLint location, GLint v0); + */ +function glUniform1i(emitter: llvm_be.LLVMEmitter, location: llvm.Value, v0: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glUniform1i"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glint(), glint()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glUniform1i", func_type); + } + return emitter.builder.buildCall(func, [location, v0], ""); +} + +/** + * void glUniform3iv(GLint location, GLsizei count, const GLint *value); + */ +function glUniform3iv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, count: llvm.Value, value: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glUniform3iv"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glint(), glsizei(), llvm.PointerType.create(glint(), 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glUniform3iv", func_type); + } + return emitter.builder.buildCall(func, [location, count, value], ""); +} + +/** + * void glUniform4iv(GLint location, GLsizei count, const GLint *value); + */ +function glUniform4iv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, count: llvm.Value, value: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glUniform4iv"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glint(), glsizei(), llvm.PointerType.create(glint(), 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glUniform4iv", func_type); + } + return emitter.builder.buildCall(func, [location, count, value], ""); +} + +/** + * void glUniform1f(GLint location, GLfloat v0): llvm.Value; + */ +function glUniform1f(emitter: llvm_be.LLVMEmitter, location: llvm.Value, v0: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glUniform1f"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glint(), glfloat()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glUniform1f", func_type); + } + return emitter.builder.buildCall(func, [location, v0], ""); +} + +/** + * void glUniform3fv( GLint location, GLsizei count, const GLfloat *value); + */ +function glUniform3fv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, count: llvm.Value, value: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glUniform3fv"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glint(), glsizei(), llvm.PointerType.create(glfloat(), 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glUniform3fv", func_type); + } + return emitter.builder.buildCall(func, [location, count, value], ""); +} + +/** + * void glUniform4fv(GLint location, GLsizei count, const GLfloat *value); + */ +function glUniform4fv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, count: llvm.Value, value: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glUniform4fv"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glint(), glsizei(), llvm.PointerType.create(glfloat(), 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glUniform4fv", func_type); + } + return emitter.builder.buildCall(func, [location, count, value], ""); +} + +/** + * void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + */ +function glUniformMatrix3fv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, count: llvm.Value, transpose: llvm.Value, value: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glUniform4fv"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glint(), glsizei(), glboolean(), llvm.PointerType.create(glfloat(), 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glUniform4fv", func_type); + } + return emitter.builder.buildCall(func, [location, count, transpose, value], ""); +} + +/** + * void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + */ +function glUniformMatrix4fv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, count: llvm.Value, transpose: llvm.Value, value: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glUniformMatrix4fv"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glint(), glsizei(), glboolean(), llvm.PointerType.create(glfloat(), 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glUniformMatrix4fv", func_type); + } + return emitter.builder.buildCall(func, [location, count, transpose, value], ""); +} + +/** + * void glBindBuffer(GLenum target, GLuint buffer); + */ +function glBindBuffer(emitter: llvm_be.LLVMEmitter, target: llvm.Value, buffer: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glBindBuffer"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [glenum(), gluint()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glBindBuffer", func_type); + } + return emitter.builder.buildCall(func, [target, buffer], ""); +} + +/** + * void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer); + */ +function glVertexAttribPointer(emitter: llvm_be.LLVMEmitter, index: llvm.Value, size: llvm.Value, type: llvm.Value, + normalized: llvm.Value, stride: llvm.Value, pointer: llvm.Value): llvm.Value { + + let func: llvm.Function = emitter.mod.getFunction("glVertexAttribPointer"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [gluint(), glint(), glenum(), glboolean(), glsizei(), glvoid()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glVertexAttribPointer", func_type); + } + return emitter.builder.buildCall(func, [index, size, type, normalized, stride, pointer], ""); +} + +/** + * void glEnableVertexAttribArray(GLuint index); + */ +function glEnableVertexAttribArray(emitter: llvm_be.LLVMEmitter, index: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glEnableVertexAttribArray"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [gluint()]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glEnableVertexAttribArray", func_type); + } + return emitter.builder.buildCall(func, [index], ""); +} ////////////////////////////////////////// /** @@ -245,8 +457,112 @@ function get_shader(emitter: llvm_be.LLVMEmitter, vertex_source: llvm.Value, ver return program; } +function emit_param_binding(emitter: llvm_be.LLVMEmitter, scopeid: number, type: Type, varid: number, value: llvm.Value, attribute: boolean, + texture_index: number | undefined, variant: Variant | null): llvm.Value { + + + if (!attribute) { + if (type === TEXTURE) { + // Bind a texture sampler. + if (texture_index === undefined) { + throw "missing texture index"; + } + glActiveTexture(emitter, llvm.ConstInt.create(GL_TEXTURE0 + texture_index, glenum())); + glBindTexture(emitter, llvm.ConstInt.create(GL_TEXTURE_2D, glenum()), value); + + let locname = locsym(scopeid, varid) + variant_suffix(variant); + let locptr = emitter.named_values2[locname]; + let loc = emitter.builder.buildLoad(locptr, ""); + return glUniform1i(emitter, loc, llvm.ConstInt.create(texture_index, glint())); + } else if (type instanceof PrimitiveType) { + // Ordinary uniform. + let fname = GL_UNIFORM_FUNCTIONS[type.name]; + if (fname === undefined) { + throw "error: unsupported uniform type " + type.name; + } + + // Construct the call to gl.uniformX. + let locname = locsym(scopeid, varid) + variant_suffix(variant); + let locptr = emitter.named_values2[locname]; + let loc = emitter.builder.buildLoad(locptr, ""); + + switch (fname) { + case "uniform3iv": + return glUniform3iv(emitter, loc, llvm.ConstInt.create(1, glsizei()), value); + case "uniform4iv": + return glUniform4iv(emitter, loc, llvm.ConstInt.create(1, glsizei()), value); + case "uniform1f": + return glUniform1f(emitter, loc, value); + case "uniform3fv": + return glUniform3fv(emitter, loc, llvm.ConstInt.create(1, glsizei()), value); + case "uniform4fv": + return glUniform4fv(emitter, loc, llvm.ConstInt.create(1, glsizei()), value); + case "uniformMatrix3fv": + return glUniformMatrix3fv(emitter, loc, llvm.ConstInt.create(1, glsizei()), llvm.ConstInt.create(0, glboolean()), value); + case "uniformMatrix4fv": + return glUniformMatrix4fv(emitter, loc, llvm.ConstInt.create(1, glsizei()), llvm.ConstInt.create(0, glboolean()), value) + default: + throw "Unsupported function name"; + } + } else { + throw "error: uniforms must be primitive types"; + } + // Array types are bound as attributes. + } else { + if (type instanceof PrimitiveType) { + // The value is a WebGL buffer object. + // let buf_expr = paren(value); + + // Location handle. + let loc_expr = locsym(scopeid, varid) + variant_suffix(variant); + let loc_ptr = emitter.named_values2[loc_expr]; + let loc = emitter.builder.buildLoad(loc_ptr, ""); + + // Choose the `vertexAttribPointer` arguments based on the type. + let pair = GL_ATTRIBUTE_TYPES[type.name]; + if (!pair) { + throw `error: unknown attribute type ${type.name}`; + } + let [dims, eltype] = pair; + + glBindBuffer(emitter, llvm.ConstInt.create(GL_ARRAY_BUFFER, glenum()), value); + glVertexAttribPointer(emitter, loc, llvm.ConstInt.create(dims, glint()), llvm.ConstInt.create(eltype, glenum()), + llvm.ConstInt.create(0, glboolean()), llvm.ConstInt.create(0, glsizei()), ___ptr___); // TODO: handle this + return glEnableVertexAttribArray(emitter, loc); + } else { + throw "error: attributes must be primitive types"; + } + } +} + function emit_shader_binding_variant(emitter: llvm_be.LLVMEmitter, progid: number, variant: Variant | null): llvm.Value { - throw "not implemented yet"; + let [vertex_prog, fragment_prog] = get_prog_pair(emitter.ir, progid); + + // Bind the shader program. + let shader_name = shadersym(vertex_prog.id!) + variant_suffix(variant); + let ptr = emitter.named_values2[shader_name]; + let shader = emitter.builder.buildLoad(ptr, ""); + glUseProgram(emitter, shader); + + // Emit and bind the uniforms and attributes. + let subemitter = assign({}, emitter); + if (!subemitter.variant) { + subemitter.variant = variant; + } + let glue = emit_glue(subemitter, progid); + let ret: llvm.Value; + for (let g of glue) { + let value: llvm.Value; + if (g.value_name) { + // value = g.value_name; + let ptr = emitter.named_values2[g.value_name]; + value = emitter.builder.buildLoad(ptr, ""); + } else { + value = llvm_be.emit(subemitter, g.value_expr!); + } + ret = emit_param_binding(emitter, vertex_prog.id!, g.type, g.id, value, g.attribute, g.texture_index, variant); + } + return ret; } function emit_shader_binding(emitter: llvm_be.LLVMEmitter, progid: number): llvm.Value { @@ -256,6 +572,7 @@ function emit_shader_binding(emitter: llvm_be.LLVMEmitter, progid: number): llvm // No variants. return emit_shader_binding_variant(emitter, progid, null); } else { + throw "not implemented yet"; // Variants exist. Emit the selector. //return js.emit_variant_selector( // emitter, emitter.ir.progs[progid], variants, @@ -264,8 +581,6 @@ function emit_shader_binding(emitter: llvm_be.LLVMEmitter, progid: number): llvm // } //); } - - throw "not implemented yet"; } // Extend the JavaScript compiler with some WebGL specifics. diff --git a/src/backends/webgl.ts b/src/backends/webgl.ts index eadfa83..3b0cf9c 100644 --- a/src/backends/webgl.ts +++ b/src/backends/webgl.ts @@ -58,7 +58,7 @@ function mat4mult(a, b) { /** * The WebGL functions for binding uniforms. */ -const GL_UNIFORM_FUNCTIONS: { [_: string]: string } = { +export const GL_UNIFORM_FUNCTIONS: { [_: string]: string } = { "Int": "uniform1i", "Int3": "uniform3iv", "Int4": "uniform4iv", From 0865eae53af946b6841aa8abf1a400062ac9767e Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Wed, 24 May 2017 12:16:45 -0400 Subject: [PATCH 14/23] Fix the way function environments structs were built Needed to create struct of undefs and then insert things individually --- src/backends/llvm.ts | 45 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/backends/llvm.ts b/src/backends/llvm.ts index 7cfdf89..354e978 100644 --- a/src/backends/llvm.ts +++ b/src/backends/llvm.ts @@ -139,8 +139,22 @@ function emit_func(emitter: LLVMEmitter, tree: ast.FunNode): llvm.Value { } // build an environment structure that wraps around free vals - let env_struct: llvm.Value = llvm.ConstStruct.create(free_vals, true); + // let env_struct: llvm.Value = llvm.ConstStruct.create(free_vals, true); + // let env_type: llvm.StructType = llvm.StructType.create(free_types, true); + // let env_struct_ptr: llvm.Value = emitter.builder.buildAlloca(env_type, "strctptr"); + // emitter.builder.buildStore(env_struct, env_struct_ptr); + // let env_void_ptr: llvm.Value = emitter.builder.buildBitCast(env_struct_ptr, FUNC_ENV_TYPE, "vdptr"); + + let undef_vals: llvm.Value[] = []; + for (let type of free_types) { + undef_vals.push(llvm.Value.getUndef(type)); + } + let env_struct: llvm.Value = llvm.ConstStruct.create(undef_vals, true); let env_type: llvm.StructType = llvm.StructType.create(free_types, true); + + for (let i = 0; i < free_vals.length; i++) { + env_struct = emitter.builder.buildInsertValue(env_struct, free_vals[i], i, ""); + } let env_struct_ptr: llvm.Value = emitter.builder.buildAlloca(env_type, "strctptr"); emitter.builder.buildStore(env_struct, env_struct_ptr); let env_void_ptr: llvm.Value = emitter.builder.buildBitCast(env_struct_ptr, FUNC_ENV_TYPE, "vdptr"); @@ -152,7 +166,11 @@ function emit_func(emitter: LLVMEmitter, tree: ast.FunNode): llvm.Value { } // return struct that wraps the function and its environment - return llvm.ConstStruct.create([func, env_void_ptr], true); + // return llvm.ConstStruct.create([func, env_void_ptr], true); + + let ret_struct: llvm.Value = llvm.ConstStruct.create([func, llvm.Value.getUndef(FUNC_ENV_TYPE)], true); + //ret_struct = emitter.builder.buildInsertValue(ret_struct, func, 0, ""); + return emitter.builder.buildInsertValue(ret_struct, env_void_ptr, 1, ""); } function emit_extern(name: string, type: Type): llvm.Value { @@ -191,8 +209,22 @@ function emit_quote_func(emitter: LLVMEmitter, prog: Prog, tree: ast.SyntaxNode) } // build an environment structure that wraps around free vals - let env_struct: llvm.Value = llvm.ConstStruct.create(free_vals, true); + // let env_struct: llvm.Value = llvm.ConstStruct.create(free_vals, true); + // let env_type: llvm.StructType = llvm.StructType.create(free_types, true); + // let env_struct_ptr: llvm.Value = emitter.builder.buildAlloca(env_type, "strctptr"); + // emitter.builder.buildStore(env_struct, env_struct_ptr); + // let env_void_ptr: llvm.Value = emitter.builder.buildBitCast(env_struct_ptr, FUNC_ENV_TYPE, "vdptr"); + + let undef_vals: llvm.Value[] = []; + for (let type of free_types) { + undef_vals.push(llvm.Value.getUndef(type)); + } + let env_struct: llvm.Value = llvm.ConstStruct.create(undef_vals, true); let env_type: llvm.StructType = llvm.StructType.create(free_types, true); + + for (let i = 0; i < free_vals.length; i++) { + env_struct = emitter.builder.buildInsertValue(env_struct, free_vals[i], i, ""); + } let env_struct_ptr: llvm.Value = emitter.builder.buildAlloca(env_type, "strctptr"); emitter.builder.buildStore(env_struct, env_struct_ptr); let env_void_ptr: llvm.Value = emitter.builder.buildBitCast(env_struct_ptr, FUNC_ENV_TYPE, "vdptr"); @@ -204,7 +236,12 @@ function emit_quote_func(emitter: LLVMEmitter, prog: Prog, tree: ast.SyntaxNode) } // return struct that wraps the function and its environment - return llvm.ConstStruct.create([func, env_void_ptr], true); + //return llvm.ConstStruct.create([func, env_void_ptr], true); + + let ret_struct: llvm.Value = llvm.ConstStruct.create([func, llvm.Value.getUndef(FUNC_ENV_TYPE)], true); + //ret_struct = emitter.builder.buildInsertValue(ret_struct, func, 0, ""); + return emitter.builder.buildInsertValue(ret_struct, env_void_ptr, 1, ""); + } function emit_quote_eval(emitter: LLVMEmitter, prog: Prog, tree: ast.SyntaxNode): llvm.Value { From 73b74adbf7c377906cad0f38f49d931078d399a4 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Wed, 24 May 2017 12:17:47 -0400 Subject: [PATCH 15/23] Delete some commented out code --- src/backends/llvm.ts | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/backends/llvm.ts b/src/backends/llvm.ts index 354e978..2b2bf85 100644 --- a/src/backends/llvm.ts +++ b/src/backends/llvm.ts @@ -139,12 +139,6 @@ function emit_func(emitter: LLVMEmitter, tree: ast.FunNode): llvm.Value { } // build an environment structure that wraps around free vals - // let env_struct: llvm.Value = llvm.ConstStruct.create(free_vals, true); - // let env_type: llvm.StructType = llvm.StructType.create(free_types, true); - // let env_struct_ptr: llvm.Value = emitter.builder.buildAlloca(env_type, "strctptr"); - // emitter.builder.buildStore(env_struct, env_struct_ptr); - // let env_void_ptr: llvm.Value = emitter.builder.buildBitCast(env_struct_ptr, FUNC_ENV_TYPE, "vdptr"); - let undef_vals: llvm.Value[] = []; for (let type of free_types) { undef_vals.push(llvm.Value.getUndef(type)); @@ -166,10 +160,7 @@ function emit_func(emitter: LLVMEmitter, tree: ast.FunNode): llvm.Value { } // return struct that wraps the function and its environment - // return llvm.ConstStruct.create([func, env_void_ptr], true); - let ret_struct: llvm.Value = llvm.ConstStruct.create([func, llvm.Value.getUndef(FUNC_ENV_TYPE)], true); - //ret_struct = emitter.builder.buildInsertValue(ret_struct, func, 0, ""); return emitter.builder.buildInsertValue(ret_struct, env_void_ptr, 1, ""); } @@ -209,12 +200,6 @@ function emit_quote_func(emitter: LLVMEmitter, prog: Prog, tree: ast.SyntaxNode) } // build an environment structure that wraps around free vals - // let env_struct: llvm.Value = llvm.ConstStruct.create(free_vals, true); - // let env_type: llvm.StructType = llvm.StructType.create(free_types, true); - // let env_struct_ptr: llvm.Value = emitter.builder.buildAlloca(env_type, "strctptr"); - // emitter.builder.buildStore(env_struct, env_struct_ptr); - // let env_void_ptr: llvm.Value = emitter.builder.buildBitCast(env_struct_ptr, FUNC_ENV_TYPE, "vdptr"); - let undef_vals: llvm.Value[] = []; for (let type of free_types) { undef_vals.push(llvm.Value.getUndef(type)); @@ -236,10 +221,7 @@ function emit_quote_func(emitter: LLVMEmitter, prog: Prog, tree: ast.SyntaxNode) } // return struct that wraps the function and its environment - //return llvm.ConstStruct.create([func, env_void_ptr], true); - let ret_struct: llvm.Value = llvm.ConstStruct.create([func, llvm.Value.getUndef(FUNC_ENV_TYPE)], true); - //ret_struct = emitter.builder.buildInsertValue(ret_struct, func, 0, ""); return emitter.builder.buildInsertValue(ret_struct, env_void_ptr, 1, ""); } From b3992c9faf39ab19552cf89f5807c255ed5d7906 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Fri, 26 May 2017 10:42:09 -0400 Subject: [PATCH 16/23] Implement mat4mult helper --- src/backends/opengl.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 0f18156..7cf4280 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -408,6 +408,20 @@ function glEnableVertexAttribArray(emitter: llvm_be.LLVMEmitter, index: llvm.Val } ////////////////////////////////////////// +/** + * Matrix multiplication + */ +function mat4mult(emitter: llvm_be.LLVMEmitter, left: llvm.Value, right: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("mat4mult"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.PointerType.create(llvm.IntType.int8(), 0); + let arg_types: llvm.Type[] = [llvm.PointerType.create(llvm.IntType.int8(), 0), llvm.PointerType.create(llvm.IntType.int8(), 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("mat4mult", func_type); + } + return emitter.builder.buildCall(func, [left, right], ""); +} + /** * Call printf */ @@ -616,8 +630,7 @@ let compile_rules: ASTVisit = if (typ === FLOAT4X4) { let lhs = llvm_be.emit(emitter, tree.lhs); let rhs = llvm_be.emit(emitter, tree.rhs); - throw "not implemented yet"; - //return `mat4mult(${lhs}, ${rhs})`; + return mat4mult(emitter, lhs, rhs); } } From 7713a6473d464e4c633a0632d610ec80d9c17def Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 29 May 2017 12:33:32 -0400 Subject: [PATCH 17/23] Use constants to get types instead of functions --- src/backends/opengl.ts | 124 ++++++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 7cf4280..c237557 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -33,29 +33,29 @@ function get_code_length(id: number) { ////////////////////////////////////////// /** - * Methods for getting various llvm versions of openGL types + * llvm versions of various openGL types */ -function glvoid(): llvm.Type {return llvm.PointerType.create(llvm.IntType.int8(), 0);} -function glchar(): llvm.Type {return llvm.IntType.int8();} -function glstring(): llvm.Type {return llvm.PointerType.create(glchar(), 0);} -function glboolean(): llvm.Type {return llvm.IntType.int1();} -function glint(): llvm.Type {return llvm.IntType.int32();} -function gluint(): llvm.Type {return llvm.IntType.int32();} -function glsizei(): llvm.Type {return llvm.IntType.int32();} -function glenum(): llvm.Type {return llvm.IntType.int32();} -function glfloat(): llvm.Type {return llvm.FloatType.float();} +let GLVOID: llvm.Type = llvm.PointerType.create(llvm.IntType.int8(), 0); +let GLCHAR: llvm.Type = llvm.IntType.int8(); +let GLSTRING: llvm.Type = llvm.PointerType.create(GLCHAR, 0); +let GLBOOLEAN: llvm.Type = llvm.IntType.int1(); +let GLINT: llvm.Type = llvm.IntType.int32(); +let GLUINT: llvm.Type = llvm.IntType.int32(); +let GLSIZEI: llvm.Type = llvm.IntType.int32(); +let GLENUM: llvm.Type = llvm.IntType.int32(); +let GLFLOAT: llvm.Type = llvm.FloatType.float(); /** * Various constants */ -let GL_TEXTURE_2D = 0x0DE1; -let GL_FLOAT = 0x1406; -let GL_TEXTURE0 = 0x84C0; -let GL_ARRAY_BUFFER = 0x8892; //TODO: check this one -let GL_FRAGMENT_SHADER = 0x8B30; -let GL_VERTEX_SHADER = 0x8B31; -let GL_COMPILE_STATUS = 0x8B81; -let GL_LINK_STATUS = 0x8B82; +let GL_TEXTURE_2D = 0x0DE1; +let GL_FLOAT = 0x1406; +let GL_TEXTURE0 = 0x84C0; +let GL_ARRAY_BUFFER = 0x8892; //TODO: check this one +let GL_FRAGMENT_SHADER = 0x8B30; +let GL_VERTEX_SHADER = 0x8B31; +let GL_COMPILE_STATUS = 0x8B81; +let GL_LINK_STATUS = 0x8B82; const GL_ATTRIBUTE_TYPES: { [_: string]: [number, number] } = { "Float2": [2, GL_FLOAT], @@ -68,8 +68,8 @@ const GL_ATTRIBUTE_TYPES: { [_: string]: [number, number] } = { function glCreateShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): llvm.Value { let func: llvm.Function = emitter.mod.getFunction("glCreateShader"); if (func.ref.isNull()) { - let ret_type: llvm.Type = gluint(); - let arg_types: llvm.Type[] = [glenum()]; + let ret_type: llvm.Type = GLUINT; + let arg_types: llvm.Type[] = [GLENUM]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glCreateShader", func_type); } @@ -83,7 +83,7 @@ function glShaderSource(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, count: let func: llvm.Function = emitter.mod.getFunction("glShaderSource"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [gluint(), glsizei(), llvm.PointerType.create(glstring(), 0), llvm.PointerType.create(glint(), 0)]; + let arg_types: llvm.Type[] = [GLUINT, GLSIZEI, llvm.PointerType.create(GLSTRING, 0), llvm.PointerType.create(GLINT, 0)]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glShaderSource", func_type); } @@ -97,7 +97,7 @@ function glCompileShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): let func: llvm.Function = emitter.mod.getFunction("glCompileShader"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [gluint()]; + let arg_types: llvm.Type[] = [GLUINT]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glCompileShader", func_type); } @@ -124,7 +124,7 @@ function glGetShaderInfoLog(emitter: llvm_be.LLVMEmitter): llvm.Value { function glCreateProgram(emitter: llvm_be.LLVMEmitter): llvm.Value { let func: llvm.Function = emitter.mod.getFunction("glCreateProgram"); if (func.ref.isNull()) { - let ret_type: llvm.Type = gluint(); + let ret_type: llvm.Type = GLUINT; let arg_types: llvm.Type[] = []; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glCreateProgram", func_type); @@ -139,7 +139,7 @@ function glAttachShader(emitter: llvm_be.LLVMEmitter, program: llvm.Value, shade let func: llvm.Function = emitter.mod.getFunction("glAttachShader"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [gluint(), gluint()]; + let arg_types: llvm.Type[] = [GLUINT, GLUINT]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glAttachShader", func_type); } @@ -153,7 +153,7 @@ function glLinkProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value): llvm. let func: llvm.Function = emitter.mod.getFunction("glLinkProgram"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [gluint()]; + let arg_types: llvm.Type[] = [GLUINT]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glLinkProgram", func_type); } @@ -174,7 +174,7 @@ function glGetProgramInfoLog(emitter: llvm_be.LLVMEmitter, program: llvm.Value, let func: llvm.Function = emitter.mod.getFunction("glGetProgramInfoLog"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [gluint(), glsizei(), llvm.PointerType.create(glsizei(),0), glstring()]; + let arg_types: llvm.Type[] = [GLUINT, GLSIZEI, llvm.PointerType.create(GLSIZEI,0), GLSTRING]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glGetProgramInfoLog", func_type); } @@ -187,8 +187,8 @@ function glGetProgramInfoLog(emitter: llvm_be.LLVMEmitter, program: llvm.Value, function glGetAttribLocation(emitter: llvm_be.LLVMEmitter, program: llvm.Value, name: llvm.Value): llvm.Value { let func: llvm.Function = emitter.mod.getFunction("glGetAttribLocation"); if (func.ref.isNull()) { - let ret_type: llvm.Type = glint(); - let arg_types: llvm.Type[] = [gluint(), glstring()]; + let ret_type: llvm.Type = GLINT; + let arg_types: llvm.Type[] = [GLUINT, GLSTRING]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glGetAttribLocation", func_type); } @@ -201,8 +201,8 @@ function glGetAttribLocation(emitter: llvm_be.LLVMEmitter, program: llvm.Value, function glGetUniformLocation(emitter: llvm_be.LLVMEmitter, program: llvm.Value, name: llvm.Value): llvm.Value { let func: llvm.Function = emitter.mod.getFunction("glGetUniformLocation"); if (func.ref.isNull()) { - let ret_type: llvm.Type = glint(); - let arg_types: llvm.Type[] = [gluint(), glstring()]; + let ret_type: llvm.Type = GLINT; + let arg_types: llvm.Type[] = [GLUINT, GLSTRING]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glGetUniformLocation", func_type); } @@ -216,7 +216,7 @@ function glUseProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value): llvm.V let func: llvm.Function = emitter.mod.getFunction("glUseProgram"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [gluint()]; + let arg_types: llvm.Type[] = [GLUINT]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glUseProgram", func_type); } @@ -230,7 +230,7 @@ function glActiveTexture(emitter: llvm_be.LLVMEmitter, texture: llvm.Value): llv let func: llvm.Function = emitter.mod.getFunction("glActiveTexture"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glenum()]; + let arg_types: llvm.Type[] = [GLENUM]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glActiveTexture", func_type); } @@ -244,7 +244,7 @@ function glBindTexture(emitter: llvm_be.LLVMEmitter, target: llvm.Value, texture let func: llvm.Function = emitter.mod.getFunction("glBindTexture"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glenum(), gluint()]; + let arg_types: llvm.Type[] = [GLENUM, GLUINT]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glBindTexture", func_type); } @@ -258,7 +258,7 @@ function glUniform1i(emitter: llvm_be.LLVMEmitter, location: llvm.Value, v0: llv let func: llvm.Function = emitter.mod.getFunction("glUniform1i"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glint(), glint()]; + let arg_types: llvm.Type[] = [GLINT, GLINT]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glUniform1i", func_type); } @@ -272,7 +272,7 @@ function glUniform3iv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, count: let func: llvm.Function = emitter.mod.getFunction("glUniform3iv"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glint(), glsizei(), llvm.PointerType.create(glint(), 0)]; + let arg_types: llvm.Type[] = [GLINT, GLSIZEI, llvm.PointerType.create(GLINT, 0)]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glUniform3iv", func_type); } @@ -286,7 +286,7 @@ function glUniform4iv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, count: let func: llvm.Function = emitter.mod.getFunction("glUniform4iv"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glint(), glsizei(), llvm.PointerType.create(glint(), 0)]; + let arg_types: llvm.Type[] = [GLINT, GLSIZEI, llvm.PointerType.create(GLINT, 0)]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glUniform4iv", func_type); } @@ -300,7 +300,7 @@ function glUniform1f(emitter: llvm_be.LLVMEmitter, location: llvm.Value, v0: llv let func: llvm.Function = emitter.mod.getFunction("glUniform1f"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glint(), glfloat()]; + let arg_types: llvm.Type[] = [GLINT, GLFLOAT]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glUniform1f", func_type); } @@ -314,7 +314,7 @@ function glUniform3fv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, count: let func: llvm.Function = emitter.mod.getFunction("glUniform3fv"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glint(), glsizei(), llvm.PointerType.create(glfloat(), 0)]; + let arg_types: llvm.Type[] = [GLINT, GLSIZEI, llvm.PointerType.create(GLFLOAT, 0)]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glUniform3fv", func_type); } @@ -328,7 +328,7 @@ function glUniform4fv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, count: let func: llvm.Function = emitter.mod.getFunction("glUniform4fv"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glint(), glsizei(), llvm.PointerType.create(glfloat(), 0)]; + let arg_types: llvm.Type[] = [GLINT, GLSIZEI, llvm.PointerType.create(GLFLOAT, 0)]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glUniform4fv", func_type); } @@ -342,7 +342,7 @@ function glUniformMatrix3fv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, let func: llvm.Function = emitter.mod.getFunction("glUniform4fv"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glint(), glsizei(), glboolean(), llvm.PointerType.create(glfloat(), 0)]; + let arg_types: llvm.Type[] = [GLINT, GLSIZEI, GLBOOLEAN, llvm.PointerType.create(GLFLOAT, 0)]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glUniform4fv", func_type); } @@ -356,7 +356,7 @@ function glUniformMatrix4fv(emitter: llvm_be.LLVMEmitter, location: llvm.Value, let func: llvm.Function = emitter.mod.getFunction("glUniformMatrix4fv"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glint(), glsizei(), glboolean(), llvm.PointerType.create(glfloat(), 0)]; + let arg_types: llvm.Type[] = [GLINT, GLSIZEI, GLBOOLEAN, llvm.PointerType.create(GLFLOAT, 0)]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glUniformMatrix4fv", func_type); } @@ -370,7 +370,7 @@ function glBindBuffer(emitter: llvm_be.LLVMEmitter, target: llvm.Value, buffer: let func: llvm.Function = emitter.mod.getFunction("glBindBuffer"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [glenum(), gluint()]; + let arg_types: llvm.Type[] = [GLENUM, GLUINT]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glBindBuffer", func_type); } @@ -386,7 +386,7 @@ function glVertexAttribPointer(emitter: llvm_be.LLVMEmitter, index: llvm.Value, let func: llvm.Function = emitter.mod.getFunction("glVertexAttribPointer"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [gluint(), glint(), glenum(), glboolean(), glsizei(), glvoid()]; + let arg_types: llvm.Type[] = [GLUINT, GLINT, GLENUM, GLBOOLEAN, GLSIZEI, GLVOID]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glVertexAttribPointer", func_type); } @@ -400,7 +400,7 @@ function glEnableVertexAttribArray(emitter: llvm_be.LLVMEmitter, index: llvm.Val let func: llvm.Function = emitter.mod.getFunction("glEnableVertexAttribArray"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [gluint()]; + let arg_types: llvm.Type[] = [GLUINT]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glEnableVertexAttribArray", func_type); } @@ -439,11 +439,11 @@ function printf(emitter: llvm_be.LLVMEmitter, str: llvm.Value, args: llvm.Value[ } function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: llvm.Value, len: number): llvm.Value { - let shader: llvm.Value = glCreateShader(emitter, llvm.ConstInt.create(shader_type, glenum())); + let shader: llvm.Value = glCreateShader(emitter, llvm.ConstInt.create(shader_type, GLENUM)); - let sources: llvm.ConstArray = llvm.ConstArray.create(glstring(), [source]); - let lengths: llvm.ConstArray = llvm.ConstArray.create(glint(), [llvm.ConstInt.create(len, glint())]); - glShaderSource(emitter, shader, llvm.ConstInt.create(1, glsizei()), sources, lengths); + let sources: llvm.ConstArray = llvm.ConstArray.create(GLSTRING, [source]); + let lengths: llvm.ConstArray = llvm.ConstArray.create(GLINT, [llvm.ConstInt.create(len, GLINT)]); + glShaderSource(emitter, shader, llvm.ConstInt.create(1, GLSIZEI), sources, lengths); glCompileShader(emitter, shader); // TODO @@ -481,13 +481,13 @@ function emit_param_binding(emitter: llvm_be.LLVMEmitter, scopeid: number, type: if (texture_index === undefined) { throw "missing texture index"; } - glActiveTexture(emitter, llvm.ConstInt.create(GL_TEXTURE0 + texture_index, glenum())); - glBindTexture(emitter, llvm.ConstInt.create(GL_TEXTURE_2D, glenum()), value); + glActiveTexture(emitter, llvm.ConstInt.create(GL_TEXTURE0 + texture_index, GLENUM)); + glBindTexture(emitter, llvm.ConstInt.create(GL_TEXTURE_2D, GLENUM), value); let locname = locsym(scopeid, varid) + variant_suffix(variant); let locptr = emitter.named_values2[locname]; let loc = emitter.builder.buildLoad(locptr, ""); - return glUniform1i(emitter, loc, llvm.ConstInt.create(texture_index, glint())); + return glUniform1i(emitter, loc, llvm.ConstInt.create(texture_index, GLINT)); } else if (type instanceof PrimitiveType) { // Ordinary uniform. let fname = GL_UNIFORM_FUNCTIONS[type.name]; @@ -502,19 +502,19 @@ function emit_param_binding(emitter: llvm_be.LLVMEmitter, scopeid: number, type: switch (fname) { case "uniform3iv": - return glUniform3iv(emitter, loc, llvm.ConstInt.create(1, glsizei()), value); + return glUniform3iv(emitter, loc, llvm.ConstInt.create(1, GLSIZEI), value); case "uniform4iv": - return glUniform4iv(emitter, loc, llvm.ConstInt.create(1, glsizei()), value); + return glUniform4iv(emitter, loc, llvm.ConstInt.create(1, GLSIZEI), value); case "uniform1f": return glUniform1f(emitter, loc, value); case "uniform3fv": - return glUniform3fv(emitter, loc, llvm.ConstInt.create(1, glsizei()), value); + return glUniform3fv(emitter, loc, llvm.ConstInt.create(1, GLSIZEI), value); case "uniform4fv": - return glUniform4fv(emitter, loc, llvm.ConstInt.create(1, glsizei()), value); + return glUniform4fv(emitter, loc, llvm.ConstInt.create(1, GLSIZEI), value); case "uniformMatrix3fv": - return glUniformMatrix3fv(emitter, loc, llvm.ConstInt.create(1, glsizei()), llvm.ConstInt.create(0, glboolean()), value); + return glUniformMatrix3fv(emitter, loc, llvm.ConstInt.create(1, GLSIZEI), llvm.ConstInt.create(0, GLBOOLEAN), value); case "uniformMatrix4fv": - return glUniformMatrix4fv(emitter, loc, llvm.ConstInt.create(1, glsizei()), llvm.ConstInt.create(0, glboolean()), value) + return glUniformMatrix4fv(emitter, loc, llvm.ConstInt.create(1, GLSIZEI), llvm.ConstInt.create(0, GLBOOLEAN), value) default: throw "Unsupported function name"; } @@ -539,9 +539,9 @@ function emit_param_binding(emitter: llvm_be.LLVMEmitter, scopeid: number, type: } let [dims, eltype] = pair; - glBindBuffer(emitter, llvm.ConstInt.create(GL_ARRAY_BUFFER, glenum()), value); - glVertexAttribPointer(emitter, loc, llvm.ConstInt.create(dims, glint()), llvm.ConstInt.create(eltype, glenum()), - llvm.ConstInt.create(0, glboolean()), llvm.ConstInt.create(0, glsizei()), ___ptr___); // TODO: handle this + glBindBuffer(emitter, llvm.ConstInt.create(GL_ARRAY_BUFFER, GLENUM), value); + glVertexAttribPointer(emitter, loc, llvm.ConstInt.create(dims, GLINT), llvm.ConstInt.create(eltype, GLENUM), + llvm.ConstInt.create(0, GLBOOLEAN), llvm.ConstInt.create(0, GLSIZEI), ___ptr___); // TODO: handle this return glEnableVertexAttribArray(emitter, loc); } else { throw "error: attributes must be primitive types"; @@ -654,7 +654,7 @@ function emit_loc_var(emitter: llvm_be.LLVMEmitter, scopeid: number, attribute: let program = emitter.builder.buildLoad(prog_ptr, ""); let name = locsym(scopeid, varid) + variant_suffix(variant); - let ptr = emitter.builder.buildAlloca(glint(), name); + let ptr = emitter.builder.buildAlloca(GLINT, name); let value; if (attribute) { value = glGetAttribLocation(emitter, program, llvm.ConstString.create(name, true)); @@ -677,7 +677,7 @@ function emit_shader_setup(emitter: llvm_be.LLVMEmitter, progid: number, variant let name = shadersym(vertex_prog.id!) + variant_suffix(variant); let program = get_shader(emitter, vtx_code, get_code_length(vertex_prog.id!), frag_code, get_code_length(fragment_prog.id!)); - let ptr = emitter.builder.buildAlloca(gluint(), name); + let ptr = emitter.builder.buildAlloca(GLUINT, name); emitter.builder.buildStore(program, ptr); emitter.named_values2[name] = ptr; From eaa7bd41b2c4f7cd9babc92b9168730df6723598 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 29 May 2017 12:55:47 -0400 Subject: [PATCH 18/23] Use null as last arg to glVertexAttribPointer --- src/backends/opengl.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index c237557..a9ccca7 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -35,15 +35,15 @@ function get_code_length(id: number) { /** * llvm versions of various openGL types */ -let GLVOID: llvm.Type = llvm.PointerType.create(llvm.IntType.int8(), 0); -let GLCHAR: llvm.Type = llvm.IntType.int8(); -let GLSTRING: llvm.Type = llvm.PointerType.create(GLCHAR, 0); -let GLBOOLEAN: llvm.Type = llvm.IntType.int1(); -let GLINT: llvm.Type = llvm.IntType.int32(); -let GLUINT: llvm.Type = llvm.IntType.int32(); -let GLSIZEI: llvm.Type = llvm.IntType.int32(); -let GLENUM: llvm.Type = llvm.IntType.int32(); -let GLFLOAT: llvm.Type = llvm.FloatType.float(); +let GLVOIDSTAR: llvm.Type = llvm.PointerType.create(llvm.IntType.int8(), 0); +let GLCHAR: llvm.Type = llvm.IntType.int8(); +let GLSTRING: llvm.Type = llvm.PointerType.create(GLCHAR, 0); +let GLBOOLEAN: llvm.Type = llvm.IntType.int1(); +let GLINT: llvm.Type = llvm.IntType.int32(); +let GLUINT: llvm.Type = llvm.IntType.int32(); +let GLSIZEI: llvm.Type = llvm.IntType.int32(); +let GLENUM: llvm.Type = llvm.IntType.int32(); +let GLFLOAT: llvm.Type = llvm.FloatType.float(); /** * Various constants @@ -378,7 +378,7 @@ function glBindBuffer(emitter: llvm_be.LLVMEmitter, target: llvm.Value, buffer: } /** - * void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer); + * void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLVOIDSTAR * pointer); */ function glVertexAttribPointer(emitter: llvm_be.LLVMEmitter, index: llvm.Value, size: llvm.Value, type: llvm.Value, normalized: llvm.Value, stride: llvm.Value, pointer: llvm.Value): llvm.Value { @@ -386,7 +386,7 @@ function glVertexAttribPointer(emitter: llvm_be.LLVMEmitter, index: llvm.Value, let func: llvm.Function = emitter.mod.getFunction("glVertexAttribPointer"); if (func.ref.isNull()) { let ret_type: llvm.Type = llvm.VoidType.create(); - let arg_types: llvm.Type[] = [GLUINT, GLINT, GLENUM, GLBOOLEAN, GLSIZEI, GLVOID]; + let arg_types: llvm.Type[] = [GLUINT, GLINT, GLENUM, GLBOOLEAN, GLSIZEI, GLVOIDSTAR]; let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); func = emitter.mod.addFunction("glVertexAttribPointer", func_type); } @@ -541,7 +541,7 @@ function emit_param_binding(emitter: llvm_be.LLVMEmitter, scopeid: number, type: glBindBuffer(emitter, llvm.ConstInt.create(GL_ARRAY_BUFFER, GLENUM), value); glVertexAttribPointer(emitter, loc, llvm.ConstInt.create(dims, GLINT), llvm.ConstInt.create(eltype, GLENUM), - llvm.ConstInt.create(0, GLBOOLEAN), llvm.ConstInt.create(0, GLSIZEI), ___ptr___); // TODO: handle this + llvm.ConstInt.create(0, GLBOOLEAN), llvm.ConstInt.create(0, GLSIZEI), llvm.Value.constNull(GLVOIDSTAR)); return glEnableVertexAttribArray(emitter, loc); } else { throw "error: attributes must be primitive types"; From 5b9b395516d24faac6885f93f99a5927479b05af Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 29 May 2017 12:56:12 -0400 Subject: [PATCH 19/23] Fix a comment --- src/backends/opengl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index a9ccca7..f87adb8 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -378,7 +378,7 @@ function glBindBuffer(emitter: llvm_be.LLVMEmitter, target: llvm.Value, buffer: } /** - * void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLVOIDSTAR * pointer); + * void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer); */ function glVertexAttribPointer(emitter: llvm_be.LLVMEmitter, index: llvm.Value, size: llvm.Value, type: llvm.Value, normalized: llvm.Value, stride: llvm.Value, pointer: llvm.Value): llvm.Value { From 098984732de8ce5fc9b14515fdff58e612cd14e1 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 29 May 2017 13:06:07 -0400 Subject: [PATCH 20/23] Add some todo's and type specifications --- src/backends/opengl.ts | 84 +++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index f87adb8..2475754 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -21,7 +21,7 @@ let str_lens: {[id: string]: number} = {}; /** * Function for getting string length. - * All length lookups will be from here, so will just need to change this + * TODO: All length lookups will be from here, so will just need to change this * method when find better way to handle string lengths */ function get_code_length(id: number) { @@ -438,6 +438,7 @@ function printf(emitter: llvm_be.LLVMEmitter, str: llvm.Value, args: llvm.Value[ return emitter.builder.buildCall(func, _args, ""); } +// TODO: create a compile_glsl function in LLVM IR instead of just inlining each call function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: llvm.Value, len: number): llvm.Value { let shader: llvm.Value = glCreateShader(emitter, llvm.ConstInt.create(shader_type, GLENUM)); @@ -446,7 +447,7 @@ function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: glShaderSource(emitter, shader, llvm.ConstInt.create(1, GLSIZEI), sources, lengths); glCompileShader(emitter, shader); - // TODO + // TODO: Error handling //if (error) { //do stuff //} @@ -454,16 +455,17 @@ function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: return shader; } +// TODO: create a get_shader function in LLVM IR instead of just inlining each call function get_shader(emitter: llvm_be.LLVMEmitter, vertex_source: llvm.Value, vertex_len: number, fragment_source: llvm.Value, fragment_len: number): llvm.Value { - let vert = compile_glsl(emitter, GL_VERTEX_SHADER, vertex_source, vertex_len); - let frag = compile_glsl(emitter, GL_FRAGMENT_SHADER, fragment_source, fragment_len); + let vert: llvm.Value = compile_glsl(emitter, GL_VERTEX_SHADER, vertex_source, vertex_len); + let frag: llvm.Value = compile_glsl(emitter, GL_FRAGMENT_SHADER, fragment_source, fragment_len); - let program = glCreateProgram(emitter); + let program: llvm.Value = glCreateProgram(emitter); glAttachShader(emitter, program, vert); glAttachShader(emitter, program, frag); glLinkProgram(emitter, program); - // TODO + // TODO: Error handling //if (error) { //do stuff //} @@ -484,21 +486,22 @@ function emit_param_binding(emitter: llvm_be.LLVMEmitter, scopeid: number, type: glActiveTexture(emitter, llvm.ConstInt.create(GL_TEXTURE0 + texture_index, GLENUM)); glBindTexture(emitter, llvm.ConstInt.create(GL_TEXTURE_2D, GLENUM), value); - let locname = locsym(scopeid, varid) + variant_suffix(variant); - let locptr = emitter.named_values2[locname]; - let loc = emitter.builder.buildLoad(locptr, ""); + let locname: string = locsym(scopeid, varid) + variant_suffix(variant); + let locptr: llvm.Value = emitter.named_values2[locname]; + let loc: llvm.Value = emitter.builder.buildLoad(locptr, ""); + return glUniform1i(emitter, loc, llvm.ConstInt.create(texture_index, GLINT)); } else if (type instanceof PrimitiveType) { // Ordinary uniform. - let fname = GL_UNIFORM_FUNCTIONS[type.name]; + let fname: string = GL_UNIFORM_FUNCTIONS[type.name]; if (fname === undefined) { throw "error: unsupported uniform type " + type.name; } // Construct the call to gl.uniformX. - let locname = locsym(scopeid, varid) + variant_suffix(variant); - let locptr = emitter.named_values2[locname]; - let loc = emitter.builder.buildLoad(locptr, ""); + let locname: string = locsym(scopeid, varid) + variant_suffix(variant); + let locptr: llvm.Value = emitter.named_values2[locname]; + let loc: llvm.Value = emitter.builder.buildLoad(locptr, ""); switch (fname) { case "uniform3iv": @@ -523,14 +526,11 @@ function emit_param_binding(emitter: llvm_be.LLVMEmitter, scopeid: number, type: } // Array types are bound as attributes. } else { - if (type instanceof PrimitiveType) { - // The value is a WebGL buffer object. - // let buf_expr = paren(value); - + if (type instanceof PrimitiveType) { // The value is a WebGL buffer object. // Location handle. - let loc_expr = locsym(scopeid, varid) + variant_suffix(variant); - let loc_ptr = emitter.named_values2[loc_expr]; - let loc = emitter.builder.buildLoad(loc_ptr, ""); + let loc_expr: string = locsym(scopeid, varid) + variant_suffix(variant); + let loc_ptr: llvm.Value = emitter.named_values2[loc_expr]; + let loc: llvm.Value = emitter.builder.buildLoad(loc_ptr, ""); // Choose the `vertexAttribPointer` arguments based on the type. let pair = GL_ATTRIBUTE_TYPES[type.name]; @@ -553,9 +553,9 @@ function emit_shader_binding_variant(emitter: llvm_be.LLVMEmitter, progid: numbe let [vertex_prog, fragment_prog] = get_prog_pair(emitter.ir, progid); // Bind the shader program. - let shader_name = shadersym(vertex_prog.id!) + variant_suffix(variant); - let ptr = emitter.named_values2[shader_name]; - let shader = emitter.builder.buildLoad(ptr, ""); + let shader_name: string = shadersym(vertex_prog.id!) + variant_suffix(variant); + let ptr: llvm.Value = emitter.named_values2[shader_name]; + let shader: llvm.Value = emitter.builder.buildLoad(ptr, ""); glUseProgram(emitter, shader); // Emit and bind the uniforms and attributes. @@ -569,7 +569,7 @@ function emit_shader_binding_variant(emitter: llvm_be.LLVMEmitter, progid: numbe let value: llvm.Value; if (g.value_name) { // value = g.value_name; - let ptr = emitter.named_values2[g.value_name]; + let ptr: llvm.Value = emitter.named_values2[g.value_name]; value = emitter.builder.buildLoad(ptr, ""); } else { value = llvm_be.emit(subemitter, g.value_expr!); @@ -628,8 +628,8 @@ let compile_rules: ASTVisit = if (tree.op === "*") { let [typ,] = emitter.ir.type_table[tree.id!]; if (typ === FLOAT4X4) { - let lhs = llvm_be.emit(emitter, tree.lhs); - let rhs = llvm_be.emit(emitter, tree.rhs); + let lhs: llvm.Value = llvm_be.emit(emitter, tree.lhs); + let rhs: llvm.Value = llvm_be.emit(emitter, tree.rhs); return mat4mult(emitter, lhs, rhs); } } @@ -641,7 +641,7 @@ let compile_rules: ASTVisit = // TODO: handle splices and things!! function emit_shader_code_ref(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Variant|null): llvm.Value { - let code_expr = progsym(prog.id!) + variant_suffix(variant); + let code_expr: string = progsym(prog.id!) + variant_suffix(variant); for (let esc of prog.owned_splice) { throw "not implemented yet"; } @@ -649,13 +649,13 @@ function emit_shader_code_ref(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: } function emit_loc_var(emitter: llvm_be.LLVMEmitter, scopeid: number, attribute: boolean, varname: string, varid: number, variant: Variant | null): llvm.Value { - let shader = shadersym(scopeid) + variant_suffix(variant); - let prog_ptr = emitter.named_values2[shader]; - let program = emitter.builder.buildLoad(prog_ptr, ""); + let shader: string = shadersym(scopeid) + variant_suffix(variant); + let prog_ptr: llvm.Value = emitter.named_values2[shader]; + let program: llvm.Value = emitter.builder.buildLoad(prog_ptr, ""); - let name = locsym(scopeid, varid) + variant_suffix(variant); - let ptr = emitter.builder.buildAlloca(GLINT, name); - let value; + let name: string = locsym(scopeid, varid) + variant_suffix(variant); + let ptr: llvm.Value = emitter.builder.buildAlloca(GLINT, name); + let value: llvm.Value; if (attribute) { value = glGetAttribLocation(emitter, program, llvm.ConstString.create(name, true)); } else { @@ -672,12 +672,12 @@ function emit_shader_setup(emitter: llvm_be.LLVMEmitter, progid: number, variant let [vertex_prog, fragment_prog] = get_prog_pair(emitter.ir, progid); // Compile and link the shader program. - let vtx_code = emit_shader_code_ref(emitter, vertex_prog, variant); - let frag_code = emit_shader_code_ref(emitter, fragment_prog, variant); - let name = shadersym(vertex_prog.id!) + variant_suffix(variant); + let vtx_code: llvm.Value = emit_shader_code_ref(emitter, vertex_prog, variant); + let frag_code: llvm.Value = emit_shader_code_ref(emitter, fragment_prog, variant); + let name: string = shadersym(vertex_prog.id!) + variant_suffix(variant); - let program = get_shader(emitter, vtx_code, get_code_length(vertex_prog.id!), frag_code, get_code_length(fragment_prog.id!)); - let ptr = emitter.builder.buildAlloca(GLUINT, name); + let program: llvm.Value = get_shader(emitter, vtx_code, get_code_length(vertex_prog.id!), frag_code, get_code_length(fragment_prog.id!)); + let ptr: llvm.Value = emitter.builder.buildAlloca(GLUINT, name); emitter.builder.buildStore(program, ptr); emitter.named_values2[name] = ptr; @@ -685,7 +685,7 @@ function emit_shader_setup(emitter: llvm_be.LLVMEmitter, progid: number, variant // Get the variable locations, for both explicit persists and for free // variables. let glue = emit_glue(emitter, vertex_prog.id!); - let val; + let val: llvm.Value; for (let g of glue) { val = emit_loc_var(emitter, vertex_prog.id!, g.attribute, g.name, g.id, variant); } @@ -703,10 +703,10 @@ function emit_glsl_prog(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Varia } // Emit the shader program. - let code = glsl.compile_prog(emitter, prog.id!); - let name = progsym(prog.id!) + variant_suffix(variant); + let code: string = glsl.compile_prog(emitter, prog.id!); + let name: string = progsym(prog.id!) + variant_suffix(variant); - let ptr = emitter.builder.buildAlloca(llvm.PointerType.create(llvm.IntType.int8(), 0), name); + let ptr: llvm.Value = emitter.builder.buildAlloca(llvm.PointerType.create(llvm.IntType.int8(), 0), name); emitter.builder.buildStore(llvm.ConstString.create(js.emit_string(code), false), ptr); emitter.named_values2[name] = ptr; From 438daa5eb27808ca029d642d538399c07e66b142 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Mon, 29 May 2017 13:11:06 -0400 Subject: [PATCH 21/23] Fix some comments and add some todo's --- src/backends/opengl.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 2475754..dd3116b 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -108,6 +108,7 @@ function glCompileShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): * void glGetShaderiv( GLuint shader, GLenum pname, GLint *params) */ function glGetShaderParameter(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, pname: llvm.Value): llvm.Value { + // TODO throw "not implemented yet"; } @@ -115,6 +116,7 @@ function glGetShaderParameter(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, * void glGetShaderInfoLog( GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog); */ function glGetShaderInfoLog(emitter: llvm_be.LLVMEmitter): llvm.Value { + // TODO throw "not implemented yet"; } @@ -164,6 +166,7 @@ function glLinkProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value): llvm. *void glGetProgramiv( GLuint program, GLenum pname, GLint *params); */ function glGetProgramParameter(emitter: llvm_be.LLVMEmitter): llvm.Value { + // TODO throw "not implemented yet"; } @@ -476,7 +479,6 @@ function get_shader(emitter: llvm_be.LLVMEmitter, vertex_source: llvm.Value, ver function emit_param_binding(emitter: llvm_be.LLVMEmitter, scopeid: number, type: Type, varid: number, value: llvm.Value, attribute: boolean, texture_index: number | undefined, variant: Variant | null): llvm.Value { - if (!attribute) { if (type === TEXTURE) { // Bind a texture sampler. @@ -526,7 +528,7 @@ function emit_param_binding(emitter: llvm_be.LLVMEmitter, scopeid: number, type: } // Array types are bound as attributes. } else { - if (type instanceof PrimitiveType) { // The value is a WebGL buffer object. + if (type instanceof PrimitiveType) { // The value is a buffer object. // Location handle. let loc_expr: string = locsym(scopeid, varid) + variant_suffix(variant); let loc_ptr: llvm.Value = emitter.named_values2[loc_expr]; @@ -586,6 +588,7 @@ function emit_shader_binding(emitter: llvm_be.LLVMEmitter, progid: number): llvm // No variants. return emit_shader_binding_variant(emitter, progid, null); } else { + // TODO throw "not implemented yet"; // Variants exist. Emit the selector. //return js.emit_variant_selector( @@ -597,7 +600,6 @@ function emit_shader_binding(emitter: llvm_be.LLVMEmitter, progid: number): llvm } } -// Extend the JavaScript compiler with some WebGL specifics. let compile_rules: ASTVisit = compose_visit(llvm_be.compile_rules, { // Compile calls to our intrinsics for binding shaders. @@ -634,15 +636,15 @@ let compile_rules: ASTVisit = } } - // Otherwise, use the ordinary JavaScript backend. + // Otherwise, use the ordinary LLVM backend. return ast_visit(llvm_be.compile_rules, tree, emitter); }, }); -// TODO: handle splices and things!! function emit_shader_code_ref(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Variant|null): llvm.Value { let code_expr: string = progsym(prog.id!) + variant_suffix(variant); for (let esc of prog.owned_splice) { + // TODO: handle splices and things!! throw "not implemented yet"; } return emitter.builder.buildLoad(emitter.named_values2[code_expr], ""); @@ -721,7 +723,7 @@ function emit_glsl_prog(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Varia return ptr; } -// Compile the IR to a JavaScript program that uses WebGL and GLSL. +// Compile to an LLVM program that uses OpenGL and GLSL. export function codegen(ir: CompilerIR): llvm.Module { llvm.initX86Target(); // Set up the emitter, which includes the LLVM IR builder. @@ -749,7 +751,7 @@ export function codegen(ir: CompilerIR): llvm.Module { emit_proc: llvm_be.emit_proc, emit_prog(emitter: llvm_be.LLVMEmitter, prog: Prog): llvm.Value { - // Choose between emitting JavaScript and GLSL. + // Choose between emitting LLVM and GLSL. if (prog.annotation === SHADER_ANNOTATION) { return emit_glsl_prog(emitter, prog, null); } else { From 70377556fe1ab425adf3a4fe371afaaac168a762 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Tue, 30 May 2017 12:12:18 -0400 Subject: [PATCH 22/23] Implement missing openGL func bindings --- src/backends/opengl.ts | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index dd3116b..86ca8b9 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -107,17 +107,29 @@ function glCompileShader(emitter: llvm_be.LLVMEmitter, shader_type: llvm.Value): /** * void glGetShaderiv( GLuint shader, GLenum pname, GLint *params) */ -function glGetShaderParameter(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, pname: llvm.Value): llvm.Value { - // TODO - throw "not implemented yet"; +function glGetShaderiv(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, pname: llvm.Value, params: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glGetShaderiv"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [GLUINT, GLENUM, llvm.PointerType.create(GLINT, 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glGetShaderiv", func_type); + } + return emitter.builder.buildCall(func, [shader, pname, params], ""); } /** * void glGetShaderInfoLog( GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog); */ -function glGetShaderInfoLog(emitter: llvm_be.LLVMEmitter): llvm.Value { - // TODO - throw "not implemented yet"; +function glGetShaderInfoLog(emitter: llvm_be.LLVMEmitter, shader: llvm.Value, max_len: llvm.Value, length: llvm.Value, info_log: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glGetShaderInfoLog"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [GLUINT, GLSIZEI, llvm.PointerType.create(GLSIZEI, 0), GLSTRING]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glGetShaderInfoLog", func_type); + } + return emitter.builder.buildCall(func, [shader, max_len, length, info_log], ""); } /** @@ -163,11 +175,17 @@ function glLinkProgram(emitter: llvm_be.LLVMEmitter, program: llvm.Value): llvm. } /* - *void glGetProgramiv( GLuint program, GLenum pname, GLint *params); -*/ -function glGetProgramParameter(emitter: llvm_be.LLVMEmitter): llvm.Value { - // TODO - throw "not implemented yet"; + * void glGetProgramiv( GLuint program, GLenum pname, GLint *params); + */ +function glGetProgramiv(emitter: llvm_be.LLVMEmitter, program: llvm.Value, pname: llvm.Value, params: llvm.Value): llvm.Value { + let func: llvm.Function = emitter.mod.getFunction("glGetProgramiv"); + if (func.ref.isNull()) { + let ret_type: llvm.Type = llvm.VoidType.create(); + let arg_types: llvm.Type[] = [GLUINT, GLENUM, llvm.PointerType.create(GLINT, 0)]; + let func_type: llvm.FunctionType = llvm.FunctionType.create(ret_type, arg_types); + func = emitter.mod.addFunction("glGetProgramiv", func_type); + } + return emitter.builder.buildCall(func, [program, pname, params], ""); } /** From 3a5e5f9a42837cbe90deb5a71babb434c0f55eb4 Mon Sep 17 00:00:00 2001 From: Richard Henwood Date: Tue, 30 May 2017 12:22:31 -0400 Subject: [PATCH 23/23] Adjust some comments --- src/backends/opengl.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backends/opengl.ts b/src/backends/opengl.ts index 86ca8b9..9a3ae84 100644 --- a/src/backends/opengl.ts +++ b/src/backends/opengl.ts @@ -459,7 +459,7 @@ function printf(emitter: llvm_be.LLVMEmitter, str: llvm.Value, args: llvm.Value[ return emitter.builder.buildCall(func, _args, ""); } -// TODO: create a compile_glsl function in LLVM IR instead of just inlining each call +// TODO: maybe create a compile_glsl function in LLVM IR instead of just inlining each call function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: llvm.Value, len: number): llvm.Value { let shader: llvm.Value = glCreateShader(emitter, llvm.ConstInt.create(shader_type, GLENUM)); @@ -476,7 +476,7 @@ function compile_glsl(emitter: llvm_be.LLVMEmitter, shader_type: number, source: return shader; } -// TODO: create a get_shader function in LLVM IR instead of just inlining each call +// TODO: maybe create a get_shader function in LLVM IR instead of just inlining each call function get_shader(emitter: llvm_be.LLVMEmitter, vertex_source: llvm.Value, vertex_len: number, fragment_source: llvm.Value, fragment_len: number): llvm.Value { let vert: llvm.Value = compile_glsl(emitter, GL_VERTEX_SHADER, vertex_source, vertex_len); let frag: llvm.Value = compile_glsl(emitter, GL_FRAGMENT_SHADER, fragment_source, fragment_len); @@ -730,7 +730,7 @@ function emit_glsl_prog(emitter: llvm_be.LLVMEmitter, prog: Prog, variant: Varia emitter.builder.buildStore(llvm.ConstString.create(js.emit_string(code), false), ptr); emitter.named_values2[name] = ptr; - str_lens[name] = code.length; // TODO: str_lens + str_lens[name] = code.length; // If it's a *vertex shader* quote (i.e., a top-level shader quote), // emit its setup code too.