From 5cb63c6cfc34cb8a62e542e36951947a60a6fb27 Mon Sep 17 00:00:00 2001 From: Nimaoth Date: Sun, 12 Nov 2023 23:33:40 +0100 Subject: [PATCH] added basic allocation --- src/ast/base_language.nim | 33 ++++++++++++++++++++++++++++++++- src/ast/base_language_wasm.nim | 29 ++++++++++++++++++++++++++--- src/ast_ids.nim | 7 ++++--- src/scripting/wasm_builder.nim | 3 ++- 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/ast/base_language.nim b/src/ast/base_language.nim index 33f49c35..a26fc5b6 100644 --- a/src/ast/base_language.nim +++ b/src/ast/base_language.nim @@ -85,6 +85,11 @@ let arrayAccessClass* = newNodeClass(IdArrayAccess, "ArrayAccess", alias="[]", b NodeChildDescription(id: IdArrayAccessValue, role: "value", class: expressionClass.id, count: ChildCount.One), NodeChildDescription(id: IdArrayAccessIndex, role: "index", class: expressionClass.id, count: ChildCount.One)]) +let allocateClass* = newNodeClass(IdAllocate, "Allocate", alias="alloc", base=expressionClass, + children=[ + NodeChildDescription(id: IdAllocateType, role: "type", class: expressionClass.id, count: ChildCount.One), + NodeChildDescription(id: IdAllocateCount, role: "count", class: expressionClass.id, count: ChildCount.ZeroOrOne)]) + let constDeclClass* = newNodeClass(IdConstDecl, "ConstDecl", alias="const", base=expressionClass, interfaces=[declarationInterface], children=[ NodeChildDescription(id: IdConstDeclType, role: "type", class: expressionClass.id, count: ChildCount.ZeroOrOne), @@ -398,6 +403,18 @@ builder.addBuilderFor IdArrayAccess, idNone(), proc(builder: CellBuilder, node: cell.add ConstantCell(node: node, text: "]", flags: &{NoSpaceLeft}, themeForegroundColors: @["punctuation", "&editor.foreground"], disableEditing: true) return cell +builder.addBuilderFor IdAllocate, idNone(), proc(builder: CellBuilder, node: AstNode): Cell = + var cell = CollectionCell(id: newId().CellId, node: node, uiFlags: &{LayoutHorizontal}) + cell.fillChildren = proc(map: NodeCellMap) = + # echo "fill collection assignment" + cell.add ConstantCell(node: node, text: "alloc", themeForegroundColors: @["keyword"], disableEditing: true) + cell.add builder.buildChildren(map, node, IdAllocateType, &{LayoutHorizontal}) + cell.add ConstantCell(node: node, text: ",", flags: &{NoSpaceLeft}, themeForegroundColors: @["punctuation", "&editor.foreground"], disableEditing: true) + cell.add block: + buildChildrenT(builder, map, node, IdAllocateCount, &{LayoutHorizontal}, 0.CellFlags): + placeholder: PlaceholderCell(id: newId().CellId, node: node, role: role, shadowText: "1") + return cell + builder.addBuilderFor callClass.id, idNone(), proc(builder: CellBuilder, node: AstNode): Cell = var cell = CollectionCell(id: newId().CellId, node: node, uiFlags: &{LayoutHorizontal}) cell.fillChildren = proc(map: NodeCellMap) = @@ -914,6 +931,20 @@ typeComputers[structMemberDefinitionClass.id] = proc(ctx: ModelComputationContex return voidTypeInstance +typeComputers[IdAllocate] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = + debugf"compute scope for allocate {node}" + + if node.firstChild(IdAllocateType).getSome(typeNode): + let targetType = ctx.computeType(typeNode) + var typ = newAstNode(pointerTypeClass) + typ.add(IdPointerTypeTarget, targetType) + typ.model = node.model + typ.forEach2 n: + n.model = node.model + return typ + + return voidTypeInstance + typeComputers[IdAddressOf] = proc(ctx: ModelComputationContextBase, node: AstNode): AstNode = debugf"compute scope for address of {node}" @@ -1005,7 +1036,7 @@ let baseLanguage* = newLanguage(IdBaseLanguage, @[ addExpressionClass, subExpressionClass, mulExpressionClass, divExpressionClass, modExpressionClass, lessExpressionClass, lessEqualExpressionClass, greaterExpressionClass, greaterEqualExpressionClass, equalExpressionClass, notEqualExpressionClass, andExpressionClass, orExpressionClass, orderExpressionClass, negateExpressionClass, notExpressionClass, - appendStringExpressionClass, printExpressionClass, buildExpressionClass, + appendStringExpressionClass, printExpressionClass, buildExpressionClass, allocateClass, structDefinitionClass, structMemberDefinitionClass, structMemberAccessClass, addressOfClass, derefClass, arrayAccessClass, diff --git a/src/ast/base_language_wasm.nim b/src/ast/base_language_wasm.nim index 5a26d1e3..a61a641f 100644 --- a/src/ast/base_language_wasm.nim +++ b/src/ast/base_language_wasm.nim @@ -53,6 +53,7 @@ type # implemented inline buildString: WasmFuncIdx strlen: WasmFuncIdx + allocFunc: WasmFuncIdx stackBase: WasmGlobalIdx stackEnd: WasmGlobalIdx @@ -95,7 +96,7 @@ proc newBaseLanguageWasmCompiler*(ctx: ModelComputationContextBase): BaseLanguag result.heapSize = result.builder.addGlobal(I32, mut=true, 0, id="__heap_size") # todo: add proper allocator. For now just a bump allocator without freeing - let alloc = result.builder.addFunction([I32], [I32], [], exportName="my_alloc".some, body=WasmExpr(instr: @[ + result.allocFunc = result.builder.addFunction([I32], [I32], [], exportName="my_alloc".some, body=WasmExpr(instr: @[ WasmInstr(kind: GlobalGet, globalIdx: result.heapBase), WasmInstr(kind: GlobalGet, globalIdx: result.heapSize), WasmInstr(kind: I32Add), @@ -178,7 +179,7 @@ proc newBaseLanguageWasmCompiler*(ctx: ModelComputationContextBase): BaseLanguag # result = alloc(resultLength) WasmInstr(kind: I32Const, i32Const: 1), WasmInstr(kind: I32Add), - WasmInstr(kind: Call, callFuncIdx: alloc), + WasmInstr(kind: Call, callFuncIdx: result.allocFunc), WasmInstr(kind: LocalTee, localIdx: resultAddress), # memcpy(resultAddress, a, a.length) @@ -247,6 +248,8 @@ proc genNode*(self: BaseLanguageWasmCompiler, node: AstNode, dest: Destination) proc toWasmValueType(typ: AstNode): Option[WasmValueType] = if typ.class == IdInt: return WasmValueType.I32.some + if typ.class == IdPointerType: + return WasmValueType.I32.some if typ.class == IdString: return WasmValueType.I64.some if typ.class == IdFunctionType: @@ -778,6 +781,8 @@ proc genNodePrintExpression(self: BaseLanguageWasmCompiler, node: AstNode, dest: let typ = self.ctx.computeType(c) if typ.class == IdInt: self.instr(Call, callFuncIdx: self.printI32) + elif typ.class == IdPointerType: + self.instr(Call, callFuncIdx: self.printI32) elif typ.class == IdString: self.instr(I32WrapI64) self.instr(Call, callFuncIdx: self.printString) @@ -964,6 +969,23 @@ proc genNodeArrayAccess(self: BaseLanguageWasmCompiler, node: AstNode, dest: Des self.genCopyToDestination(node, dest) +proc genNodeAllocate(self: BaseLanguageWasmCompiler, node: AstNode, dest: Destination) = + let typeNode = node.firstChild(IdAllocateType).getOr: + log lvlError, fmt"No type: {node}" + return + + let typ = self.ctx.computeType(typeNode) # todo: replace with get value once implemented + let (size, align) = self.getTypeAttributes(typ) + + self.instr(I32Const, i32Const: size) + + if node.firstChild(IdAllocateCount).getSome(countNode): + self.genNode(countNode, Destination(kind: Stack)) + self.instr(I32Mul) + + self.instr(Call, callFuncIdx: self.allocFunc) + self.genStoreDestination(node, dest) + proc setupGenerators(self: BaseLanguageWasmCompiler) = self.generators[IdBlock] = genNodeBlock self.generators[IdAdd] = genNodeBinaryAddExpression @@ -997,4 +1019,5 @@ proc setupGenerators(self: BaseLanguageWasmCompiler) = self.generators[IdStructMemberAccess] = genNodeStructMemberAccessExpression self.generators[IdAddressOf] = genNodeAddressOf self.generators[IdDeref] = genNodeDeref - self.generators[IdArrayAccess] = genNodeArrayAccess \ No newline at end of file + self.generators[IdArrayAccess] = genNodeArrayAccess + self.generators[IdAllocate] = genNodeAllocate \ No newline at end of file diff --git a/src/ast_ids.nim b/src/ast_ids.nim index a21a4df9..b7921fa0 100644 --- a/src/ast_ids.nim +++ b/src/ast_ids.nim @@ -139,11 +139,12 @@ let IdArrayAccess* = "654fbb281446e19b3822520e".parseId.ClassId let IdArrayAccessValue* = "654fbb281446e19b3822520f".parseId.RoleId let IdArrayAccessIndex* = "654fbb281446e19b38225210".parseId.RoleId +let IdAllocate* = "654fbb281446e19b38225211".parseId.ClassId +let IdAllocateType* = "654fbb281446e19b38225212".parseId.RoleId +let IdAllocateCount* = "654fbb281446e19b38225213".parseId.RoleId + # new ids -let Id654fbb281446e19b38225211* = "654fbb281446e19b38225211".parseId -let Id654fbb281446e19b38225212* = "654fbb281446e19b38225212".parseId -let Id654fbb281446e19b38225213* = "654fbb281446e19b38225213".parseId let Id654fbb281446e19b38225214* = "654fbb281446e19b38225214".parseId let Id654fbb281446e19b38225215* = "654fbb281446e19b38225215".parseId let Id654fbb281446e19b38225216* = "654fbb281446e19b38225216".parseId diff --git a/src/scripting/wasm_builder.nim b/src/scripting/wasm_builder.nim index cc14b0ee..f0485d33 100644 --- a/src/scripting/wasm_builder.nim +++ b/src/scripting/wasm_builder.nim @@ -421,7 +421,8 @@ proc addFunction*(self: WasmBuilder, self.funcs.add WasmFunc( typeIdx: typeIdx, locals: @locals, - body: body + body: body, + id: exportName.get "" ) if exportName.getSome(exportName):