From 3ddc6c61c8cd42b89758d9d5527c00a023b511b2 Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 13 Nov 2019 20:27:39 -0300 Subject: [PATCH 01/10] add basic x86 struct --- src/x86.zig | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/x86.zig diff --git a/src/x86.zig b/src/x86.zig new file mode 100644 index 0000000..d1e6713 --- /dev/null +++ b/src/x86.zig @@ -0,0 +1,27 @@ +const std = @import("std"); +const ast = @import("ast.zig"); +const comp = @import("comp_ctx.zig"); + +pub const CompileError = error{ + EmitError, + TypeError, + Invalid, +}; + +pub const Codegenx86 = struct { + allocator: *std.mem.Allocator, + ctx: *comp.CompilationContext, + + current_function_name: ?[]const u8 = null, + + pub fn init(allocator: *std.mem.Allocator, ctx: *comp.CompilationContext) Codegen { + return Codegen{ + .allocator = allocator, + .ctx = ctx, + }; + } + + // TODO + + pub fn gen(self: *Codegen, root: *ast.Node) !void {} +}; From e42a97e192459422d4c32b74761161d558bc78a0 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 25 Nov 2019 21:42:24 -0300 Subject: [PATCH 02/10] use 'as' builtin - move src/codegen.zig to src/codegen/llvm.zig --- src/analysis.zig | 26 +- src/codegen.zig | 603 +------------------------------------------ src/codegen/llvm.zig | 599 ++++++++++++++++++++++++++++++++++++++++++ src/comp_ctx.zig | 2 +- src/main.zig | 2 +- src/parsers.zig | 5 +- 6 files changed, 622 insertions(+), 615 deletions(-) create mode 100644 src/codegen/llvm.zig diff --git a/src/analysis.zig b/src/analysis.zig index 1962762..c3363a5 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -88,7 +88,7 @@ pub const Analyzer = struct { self.doError( "expected struct or enum for '{}', got {}", val, - @tagName(comp.SymbolType(sym.?.value.*)), + @tagName(@as(comp.SymbolType, sym.?.value.*)), ); break :blk null; }, @@ -106,7 +106,7 @@ pub const Analyzer = struct { symbol_type: comp.SymbolUnderlyingType, wanted_type_enum: comp.SymbolUnderlyingTypeEnum, ) !void { - var actual_enum = comp.SymbolUnderlyingTypeEnum(symbol_type); + var actual_enum = @as(comp.SymbolUnderlyingTypeEnum, symbol_type); if (actual_enum != wanted_type_enum) { std.debug.warn("Expected {}, got {}\n", wanted_type_enum, actual_enum); return CompileError.TypeError; @@ -121,7 +121,7 @@ pub const Analyzer = struct { switch (symbol_type) { .Integer32, .Integer64, .Double => {}, else => { - var actual_enum = comp.SymbolUnderlyingTypeEnum(symbol_type); + var actual_enum = @as(comp.SymbolUnderlyingTypeEnum, symbol_type); std.debug.warn("Expected numeric, got {}\n", actual_enum); return CompileError.TypeError; }, @@ -154,8 +154,8 @@ pub const Analyzer = struct { symbol_type: comp.SymbolUnderlyingType, expected_type: comp.SymbolUnderlyingType, ) !void { - const symbol_enum = comp.SymbolUnderlyingTypeEnum(symbol_type); - const expected_enum = comp.SymbolUnderlyingTypeEnum(expected_type); + const symbol_enum = @as(comp.SymbolUnderlyingTypeEnum, symbol_type); + const expected_enum = @as(comp.SymbolUnderlyingTypeEnum, expected_type); if (symbol_enum != expected_enum) { std.debug.warn("Expected {}, got {}\n", expected_enum, symbol_enum); @@ -253,7 +253,7 @@ pub const Analyzer = struct { .Call => |call| { self.setErrToken(call.paren); - std.debug.assert(ast.ExprType(call.callee.*) == .Variable); + std.debug.assert(@as(ast.ExprType, call.callee.*) == .Variable); const func_name = call.callee.*.Variable.lexeme; var symbol = try ctx.fetchGlobalSymbol(func_name, .Function); @@ -264,11 +264,14 @@ pub const Analyzer = struct { var arg_type = try self.resolveExprType(ctx, &arg_expr); self.expectSymUnTypeEqual(arg_type, param_type) catch { + const param_type_val = @as(comp.SymbolUnderlyingTypeEnum, param_type); + const arg_type_val = @as(comp.SymbolUnderlyingTypeEnum, arg_type); + self.doError( "Expected parameter {} to be {}, got {}", idx, - @tagName(comp.SymbolUnderlyingTypeEnum(param_type)), - @tagName(comp.SymbolUnderlyingTypeEnum(arg_type)), + @tagName(param_type_val), + @tagName(arg_type_val), ); return CompileError.TypeError; @@ -287,8 +290,9 @@ pub const Analyzer = struct { .Get => |get| { var target = get.target.*; - if (ast.ExprType(target) != .Variable) { - std.debug.warn("Expected Variable as get target, got {}\n", ast.ExprType(target)); + const target_type = @as(ast.ExprType, target); + if (target_type != .Variable) { + std.debug.warn("Expected Variable as get target, got {}\n", target_type); return CompileError.TypeError; } @@ -332,7 +336,7 @@ pub const Analyzer = struct { else => { self.doError( "Expected Struct/Enum as get target, got {}", - comp.SymbolUnderlyingTypeEnum(global_typ), + @as(comp.SymbolUnderlyingTypeEnum, global_typ), ); return CompileError.TypeError; diff --git a/src/codegen.zig b/src/codegen.zig index bad81e6..38aa1bd 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1,606 +1,9 @@ -const std = @import("std"); -const ast = @import("ast.zig"); -const llvm = @import("llvm.zig"); -const comp = @import("comp_ctx.zig"); -// const analysis = @import("analysis.zig"); - -fn sliceify(non_slice: ?[*]const u8) []const u8 { - if (non_slice == null) return ""; - return non_slice.?[0..std.mem.len(u8, non_slice.?)]; -} +pub const llvm = @import("codegen/llvm.zig"); +// pub const x86 = @import("codegen/x86.zig"); pub const CompileError = error{ - LLVMError, + BackendError, EmitError, TypeError, Invalid, }; - -fn mkLLVMBool(val: bool) llvm.LLVMValueRef { - if (val) { - return llvm.LLVMConstInt(llvm.LLVMInt1Type(), 1, 1); - } else { - return llvm.LLVMConstInt(llvm.LLVMInt1Type(), 0, 1); - } -} - -pub const LLVMTable = std.StringHashMap(llvm.LLVMValueRef); -pub const LLVMValueList = std.ArrayList(llvm.LLVMValueRef); - -pub const Codegen = struct { - allocator: *std.mem.Allocator, - ctx: *comp.CompilationContext, - llvm_table: LLVMTable, - - current_function_name: ?[]const u8 = null, - - pub fn init(allocator: *std.mem.Allocator, ctx: *comp.CompilationContext) Codegen { - return Codegen{ - .allocator = allocator, - .ctx = ctx, - .llvm_table = LLVMTable.init(allocator), - }; - } - - fn typeToLLVM(self: *@This(), typ: comp.SymbolUnderlyingType) !llvm.LLVMTypeRef { - return switch (typ) { - .Integer32 => llvm.LLVMInt32Type(), - .Integer64 => llvm.LLVMInt64Type(), - .Bool => llvm.LLVMInt1Type(), - - .OpaqueType => |val| { - std.debug.warn("Invalid return type: {}\n", val); - return CompileError.TypeError; - }, - - .Struct, .Enum => |lex| blk: { - var sym_data = self.ctx.symbol_table.get(lex).?.value; - break :blk switch (sym_data.*) { - .Struct => unreachable, - .Enum => llvm.LLVMInt32Type(), - else => { - std.debug.warn("Function {} is not a type\n", lex); - return CompileError.TypeError; - }, - }; - }, - - else => { - std.debug.warn("TODO handle {}\n", typ); - return CompileError.TypeError; - }, - }; - } - - fn emitForVariableType(self: *@This(), vari: var, get: var, kv: var) !llvm.LLVMValueRef { - var sym = kv.value; - - switch (sym.*) { - .Enum => |map| { - var val = map.get(get.name.lexeme); - if (val == null) { - std.debug.warn( - "enum {} does not have field {}\n", - vari.lexeme, - get.name.lexeme, - ); - } - return llvm.LLVMConstInt(llvm.LLVMInt32Type(), val.?.value, 1); - }, - - .Struct => @panic("TODO handle struct"), - else => { - std.debug.warn("Invalid get target: {}\n", comp.SymbolType(sym.*)); - return CompileError.EmitError; - }, - } - } - - fn emitExpr( - self: *Codegen, - builder: var, - expr: *const ast.Expr, - ) anyerror!llvm.LLVMValueRef { - return switch (expr.*) { - - // TODO handle all literals, construct llvm values for them - .Literal => |literal| blk: { - break :blk switch (literal) { - // TODO other literals - .Integer32 => |val| llvm.LLVMConstInt( - llvm.LLVMInt32Type(), - @intCast(c_ulonglong, val), - 10, - ), - .Integer64 => |val| llvm.LLVMConstInt( - llvm.LLVMInt64Type(), - @intCast(c_ulonglong, val), - 10, - ), - - .Float => |val| blk2: { - var val_cstr = try std.cstr.addNullByte(self.allocator, val); - break :blk2 llvm.LLVMConstRealOfString(llvm.LLVMDoubleType(), val_cstr.ptr); - }, - .Bool => |val| blk2: { - break :blk2 mkLLVMBool(val); - }, - else => unreachable, - }; - }, - - .Unary => |unary| { - var right = try self.emitExpr(builder, unary.right); - - return switch (unary.op) { - .Negate => llvm.LLVMBuildNeg(builder, right, c"neg_tmp"), - .Not => llvm.LLVMBuildNot(builder, right, c"neg_tmp"), - }; - }, - - .Binary => |binary| { - var left = try self.emitExpr(builder, binary.left); - var right = try self.emitExpr(builder, binary.right); - - return switch (binary.op) { - .Add => llvm.LLVMBuildAdd(builder, left, right, c"addtmp"), - .Sub => llvm.LLVMBuildSub(builder, left, right, c"subtmp"), - .Mul => llvm.LLVMBuildMul(builder, left, right, c"multmp"), - - //.Div => llvm.LLVMBuildDiv(builder, left, right, c"divtmp"), - .And => llvm.LLVMBuildAnd(builder, left, right, c"andtmp"), - .Or => llvm.LLVMBuildOr(builder, left, right, c"ortmp"), - - else => { - std.debug.warn("Unexpected binary operator: '{}'\n", binary.op); - return CompileError.EmitError; - }, - }; - }, - - .Get => |get| { - var target = get.target.*; - - switch (target) { - .Variable => |vari| { - // first, we must check if the target is a type - // and emit accordingly - var kv_sym_opt = self.ctx.symbol_table.get(vari.lexeme); - if (kv_sym_opt) |kv| { - return try self.emitForVariableType(vari, get, kv); - } - - // if not, its likely a variable, we should handle it accordingly - // as well - @panic("TODO handle variables"); - }, - - else => { - std.debug.warn("Invalid get target: {}\n", ast.ExprType(target)); - return CompileError.EmitError; - }, - } - }, - - .Call => |call| { - const name = call.callee.*.Variable.lexeme; - - var llvm_func = self.llvm_table.get(name); - if (llvm_func == null) { - std.debug.warn("Function '{}' not found\n", name); - return CompileError.EmitError; - } - - var args = LLVMValueList.init(self.allocator); - errdefer args.deinit(); - - for (call.arguments.toSlice()) |arg_expr| { - var arg_val = try self.emitExpr(builder, &arg_expr); - try args.append(arg_val); - } - - var args_slice = args.toSlice(); - - return llvm.LLVMBuildCall( - builder, - llvm_func.?.value, - args_slice.ptr, - @intCast(c_uint, args_slice.len), - c"call", - ); - }, - - .Assign => |assign| { - const name = assign.name.lexeme; - var meta = self.ctx.current_scope.?.meta_map.get(name).?.value; - var assign_expr = try self.emitExpr(builder, assign.value); - var llvm_alloca: llvm.LLVMValueRef = switch (meta.using) { - .Function => meta.from_function.?.parameters.get(name).?.value.llvm_alloca.?, - .Scope => meta.llvm_alloca.?, - }; - - return llvm.LLVMBuildStore(builder, assign_expr, llvm_alloca); - }, - - .Variable => |vari| { - var kv_opt = self.ctx.current_scope.?.meta_map.get(vari.lexeme); - - if (kv_opt == null) { - std.debug.warn("variable {} not fully analyzed\n", vari.lexeme); - return CompileError.EmitError; - } - - // we have metadata, which means we can check if the variable - // is coming from the scope or from the function - - var metadata = kv_opt.?.value; - std.debug.warn("!! LOAD FROM VAR META {}\n", @ptrToInt(metadata)); - - var buf = try self.allocator.alloc(u8, 512); - errdefer self.allocator.free(buf); - - var load_str = try std.fmt.bufPrint(buf, "{}_loaded", vari.lexeme); - - var load_cstr = try std.cstr.addNullByte(self.allocator, load_str); - errdefer self.allocator.free(load_cstr); - - return switch (metadata.using) { - .Function => blk: { - var param = metadata.from_function.?.parameters.get(vari.lexeme).?.value; - break :blk llvm.LLVMBuildLoad(builder, param.llvm_alloca.?, load_cstr.ptr); - }, - - .Scope => blk: { - var llvm_alloca = metadata.llvm_alloca.?; - //var var_typ = metadata.from_scope.?.env.get(vari.lexeme).?.value; - break :blk llvm.LLVMBuildLoad(builder, llvm_alloca, load_cstr.ptr); - }, - }; - }, - - .Grouping => |expr_ptr| blk: { - break :blk try self.emitExpr(builder, expr_ptr); - }, - - else => { - std.debug.warn("Got unexpected expr {}\n", ast.ExprType(expr.*)); - return CompileError.EmitError; - }, - }; - } - - fn emitStmt(self: *Codegen, builder: var, stmt: *ast.Stmt) anyerror!void { - std.debug.warn("cgen: emitting stmt {}\n", ast.StmtType(stmt.*)); - - switch (stmt.*) { - .Expr => |expr| _ = try self.emitExpr(builder, expr), - - .Return => |ret| { - var ret_expr = try self.emitExpr(builder, ret.value); - _ = llvm.LLVMBuildRet(builder, ret_expr); - }, - - .If => |ifstmt| { - var cond = try self.emitExpr(builder, ifstmt.condition); - var zero = mkLLVMBool(false); - var icmp = llvm.LLVMBuildICmp(builder, llvm.LLVMIntPredicate.LLVMIntNE, cond, zero, c"ifcond"); - - var insert = llvm.LLVMGetInsertBlock(builder); - var function = llvm.LLVMGetBasicBlockParent(insert); - - var then_bb = llvm.LLVMAppendBasicBlock(function, c"then"); - var else_bb = llvm.LLVMAppendBasicBlock(function, c"else"); - var merge_bb = llvm.LLVMAppendBasicBlock(function, c"ifcont"); - - var condbr = llvm.LLVMBuildCondBr(builder, icmp, then_bb, else_bb); - - llvm.LLVMPositionBuilderAtEnd(builder, then_bb); - - // roughly translating to kaleidoscope's - // 'Value *ThenV = Then->codegen();' - var then_rets = false; - var else_rets = false; - - self.ctx.setScope(self.ctx.current_scope.?.nextChild()); - - var then_branch = ifstmt.then_branch.toSlice(); - for (then_branch) |_, idx| { - // keep emitting until branch has ret - var then_stmt = &then_branch[idx]; - - if (!then_rets) - try self.emitStmt(builder, then_stmt); - - // TODO break? lol - switch (then_stmt.*) { - .Return => then_rets = true, - else => {}, - } - } - - self.ctx.dumpScope(); - - // only build the br instruction if we didn't ret, because - // there can't be any instruction after a terminator - // same applies for the else branch - if (!then_rets) - _ = llvm.LLVMBuildBr(builder, merge_bb); - - then_bb = llvm.LLVMGetInsertBlock(builder); - - llvm.LLVMPositionBuilderAtEnd(builder, else_bb); - - // roughly translating to kaleidoscope's - // 'Else *ElseV = Else->codegen();' - if (ifstmt.else_branch) |else_block| { - self.ctx.setScope(self.ctx.current_scope.?.nextChild()); - - var else_slice = else_block.toSlice(); - for (else_slice) |_, idx| { - // keep emitting until branch has ret - var else_stmt = &else_slice[idx]; - - if (!else_rets) - try self.emitStmt(builder, else_stmt); - - switch (else_stmt.*) { - .Return => else_rets = true, - else => {}, - } - } - - self.ctx.dumpScope(); - } - - if (!else_rets) - _ = llvm.LLVMBuildBr(builder, merge_bb); - - else_bb = llvm.LLVMGetInsertBlock(builder); - - llvm.LLVMPositionBuilderAtEnd(builder, merge_bb); - - // if both of the branches return, we should put - // the merge branch as unreachable. - if (then_rets and else_rets) - _ = llvm.LLVMBuildUnreachable(builder); - }, - - .VarDecl => |vardecl| { - // we alaready inferred the type of the variable in the - // analyze pass and the current scope contains the variable's - // type(hopefully), so we resolve it - const name = vardecl.name.lexeme; - var var_metadata = self.ctx.current_scope.?.meta_map.get(name).?.value; - - var name_cstr = try std.cstr.addNullByte(self.allocator, name); - errdefer self.allocator.free(name_cstr); - - var fn_symbol = self.getFnSymbol(self.current_function_name.?); - - var variable = llvm.LLVMBuildAlloca( - builder, - try self.typeToLLVM(var_metadata.typ), - name_cstr.ptr, - ); - - stmt.*.VarDecl.llvm_alloca = variable; - - var_metadata.*.llvm_alloca = variable; - - std.debug.warn("!! DECL VAR {} => {}\n", @ptrToInt(var_metadata), variable); - - var llvm_expr = try self.emitExpr(builder, vardecl.value); - _ = llvm.LLVMBuildStore(builder, llvm_expr, variable); - }, - - else => { - std.debug.warn("Got unexpected stmt {}\n", stmt.*); - return CompileError.EmitError; - }, - } - } - - fn getFnSymbol(self: *@This(), name: []const u8) *comp.FunctionSymbol { - var fn_sym_search = self.ctx.symbol_table.get(name).?.value; - std.debug.assert(comp.SymbolType(fn_sym_search.*) == .Function); - return &fn_sym_search.Function; - } - - /// Emit LLVM ir for the given node. - fn genNode( - self: *Codegen, - mod: llvm.LLVMModuleRef, - node: *ast.Node, - ) !void { - switch (node.*) { - .Root => @panic("Should not have gotten Root"), - .FnDecl => |decl| { - const name = decl.func_name.lexeme; - self.current_function_name = name; - std.debug.warn("cgen: genning function '{}'\n", name); - - var fn_sym = self.getFnSymbol(name); - - const name_cstr = try std.cstr.addNullByte(self.allocator, name); - errdefer self.allocator.free(name_cstr); - - var param_types = llvm.LLVMTypeList.init(self.allocator); - errdefer param_types.deinit(); - - for (decl.params.toSlice()) |param| { - try param_types.append(try self.typeToLLVM(fn_sym.parameters.get( - param.name.lexeme, - ).?.value.typ)); - } - - var llvm_ret_type = llvm.LLVMFunctionType( - try self.typeToLLVM(fn_sym.return_type), - param_types.toSlice().ptr, - @intCast(c_uint, param_types.len), - 0, - ); - - var func = llvm.LLVMAddFunction(mod, name_cstr.ptr, llvm_ret_type); - _ = try self.llvm_table.put(name, func); - - var buf = try self.allocator.alloc(u8, 512); - var entry_lbl = try std.fmt.bufPrint(buf, "fn_{}_entry", name); - var entry_lbl_cstr = try std.cstr.addNullByte(self.allocator, entry_lbl); - var entry = llvm.LLVMAppendBasicBlock(func, entry_lbl_cstr.ptr); - - var builder = llvm.LLVMCreateBuilder(); - llvm.LLVMPositionBuilderAtEnd(builder, entry); - - // to have the ability to mutate parameters, we must allocate them on - // the stack - var params_slice = decl.params.toSlice(); - for (params_slice) |param_node, idx| { - var param = fn_sym.parameters.get(param_node.name.lexeme).?.value; - - const param_name_cstr = try std.cstr.addNullByte(self.allocator, param_node.name.lexeme); - errdefer self.allocator.free(param_name_cstr); - - var alloca = llvm.LLVMBuildAlloca(builder, try self.typeToLLVM(param.typ), param_name_cstr.ptr); - - std.debug.warn("SET PARAM LLVM ALLOCA {} to {}\n", param_node.name.lexeme, alloca); - param.llvm_alloca = alloca; - - _ = llvm.LLVMBuildStore( - builder, - llvm.LLVMGetParam(func, @intCast(c_uint, idx)), - alloca, - ); - } - - self.ctx.setScope(fn_sym.scope); - - // TODO check if stmt is return and if we already - // returned before - var body_slice = decl.body.toSlice(); - for (body_slice) |_, idx| { - try self.emitStmt(builder, &body_slice[idx]); - } - - self.ctx.dumpScope(); - std.debug.warn("cgen: generated function '{}'\n", name); - }, - - // NOTE: enums don't have specific llvm ir code generated for them - .Enum => {}, - - .ConstDecl => |constdecls| { - for (constdecls.toSlice()) |constdecl| { - const name = constdecl.name.lexeme; - - var const_type = self.ctx.symbol_table.get(name).?.value; - var const_llvm_type = try self.typeToLLVM(const_type.Const); - - const const_name = try std.cstr.addNullByte(self.allocator, name); - errdefer self.allocator.free(const_name); - - var global = llvm.LLVMAddGlobal(mod, const_llvm_type, const_name.ptr); - - // TODO maybe put builder at main function so we can still - // call other functions inside consts? - - var builder = llvm.LLVMCreateBuilder(); - var expr_llvm_val = try self.emitExpr(builder, constdecl.expr); - - llvm.LLVMSetInitializer(global, expr_llvm_val); - } - }, - - else => { - std.debug.warn("TODO handle node type {}\n", @tagName(node.*)); - return; - }, - } - } - - pub fn gen(self: *Codegen, root: *ast.Node) !void { - std.debug.warn("cgen: start gen\n"); - _ = llvm.LLVMInitializeNativeTarget(); - - var mod = llvm.LLVMModuleCreateWithName(c"awoo").?; - defer llvm.LLVMDisposeModule(mod); - - var root_slice = root.Root.toSlice(); - for (root_slice) |_, idx| { - try self.genNode(mod, &root_slice[idx]); - } - - var err: ?[*]u8 = null; - defer llvm.LLVMDisposeMessage(err); - - if (llvm.LLVMPrintModuleToFile(mod, c"output.ll", &err) != 0) { - std.debug.warn("error printing module to file: {}\n", sliceify(err)); - return CompileError.LLVMError; - } - - //if (llvm.LLVMWriteBitcodeToFile(mod, c"awoo.bc") != 0) { - // std.debug.warn("error writing bitcode to file: {}\n", sliceify(err)); - // return CompileError.LLVMError; - //} - - std.debug.warn("cgen: verify llvm module\n"); - _ = llvm.LLVMVerifyModule( - mod, - llvm.LLVMVerifierFailureAction.LLVMAbortProcessAction, - &err, - ); - - llvm.LLVMInitializeAllTargetInfos(); - llvm.LLVMInitializeAllTargets(); - llvm.LLVMInitializeAllTargetMCs(); - llvm.LLVMInitializeAllAsmParsers(); - llvm.LLVMInitializeAllAsmPrinters(); - - var engine: llvm.LLVMExecutionEngineRef = undefined; - if (llvm.LLVMCreateExecutionEngineForModule(&engine, mod, &err) != 0) { - std.debug.warn("failed to create execution engine: {}\n", sliceify(err)); - return CompileError.LLVMError; - } - - var machine = llvm.LLVMGetExecutionEngineTargetMachine(engine); - defer llvm.LLVMDisposeTargetMachine(machine); - - var target = llvm.LLVMGetTargetMachineTarget(machine); - var target_data = llvm.LLVMCreateTargetDataLayout(machine); - var data_layout = llvm.LLVMCopyStringRepOfTargetData(target_data); - llvm.LLVMSetDataLayout(mod, data_layout); - - var outpath_cstr = try std.cstr.addNullByte(self.allocator, "outpath.o"); - - //var asmpath_cstr = try std.cstr.addNullByte(self.allocator, "output.S"); - - var desc = llvm.LLVMGetTargetDescription(target); - var features = llvm.LLVMGetTargetMachineFeatureString(machine); - var triple = llvm.LLVMGetTargetMachineTriple(machine); - - std.debug.warn("target: {}\n", sliceify(desc)); - std.debug.warn("triple: {}\n", sliceify(triple)); - std.debug.warn("features: {}\n", sliceify(features)); - - //if (llvm.LLVMTargetMachineEmitToFile( - // machine, - // mod, - // asmpath_cstr.ptr, - // llvm.LLVMCodeGenFileType.LLVMAssemblyFile, - // &err, - //) != 0) { - // std.debug.warn("failed to emit to assembly file: {}\n", sliceify(err)); - // return CompileError.LLVMError; - //} - - if (llvm.LLVMTargetMachineEmitToFile( - machine, - mod, - outpath_cstr.ptr, - llvm.LLVMCodeGenFileType.LLVMObjectFile, - &err, - ) != 0) { - std.debug.warn("failed to emit to file: {}\n", sliceify(err)); - return CompileError.LLVMError; - } - } -}; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig new file mode 100644 index 0000000..6da6f82 --- /dev/null +++ b/src/codegen/llvm.zig @@ -0,0 +1,599 @@ +const std = @import("std"); +const ast = @import("../ast.zig"); +const llvm = @import("../llvm.zig"); +const comp = @import("../comp_ctx.zig"); +const CompileError = @import("../codegen.zig").CompileError; + +fn sliceify(non_slice: ?[*]const u8) []const u8 { + if (non_slice == null) return ""; + return non_slice.?[0..std.mem.len(u8, non_slice.?)]; +} + +fn mkLLVMBool(val: bool) llvm.LLVMValueRef { + if (val) { + return llvm.LLVMConstInt(llvm.LLVMInt1Type(), 1, 1); + } else { + return llvm.LLVMConstInt(llvm.LLVMInt1Type(), 0, 1); + } +} + +pub const LLVMTable = std.StringHashMap(llvm.LLVMValueRef); +pub const LLVMValueList = std.ArrayList(llvm.LLVMValueRef); + +pub const Codegen = struct { + allocator: *std.mem.Allocator, + ctx: *comp.CompilationContext, + llvm_table: LLVMTable, + + current_function_name: ?[]const u8 = null, + + pub fn init(allocator: *std.mem.Allocator, ctx: *comp.CompilationContext) Codegen { + return Codegen{ + .allocator = allocator, + .ctx = ctx, + .llvm_table = LLVMTable.init(allocator), + }; + } + + fn typeToLLVM(self: *@This(), typ: comp.SymbolUnderlyingType) !llvm.LLVMTypeRef { + return switch (typ) { + .Integer32 => llvm.LLVMInt32Type(), + .Integer64 => llvm.LLVMInt64Type(), + .Bool => llvm.LLVMInt1Type(), + + .OpaqueType => |val| { + std.debug.warn("Invalid return type: {}\n", val); + return CompileError.TypeError; + }, + + .Struct, .Enum => |lex| blk: { + var sym_data = self.ctx.symbol_table.get(lex).?.value; + break :blk switch (sym_data.*) { + .Struct => unreachable, + .Enum => llvm.LLVMInt32Type(), + else => { + std.debug.warn("Function {} is not a type\n", lex); + return CompileError.TypeError; + }, + }; + }, + + else => { + std.debug.warn("TODO handle {}\n", typ); + return CompileError.TypeError; + }, + }; + } + + fn emitForVariableType(self: *@This(), vari: var, get: var, kv: var) !llvm.LLVMValueRef { + var sym = kv.value; + + switch (sym.*) { + .Enum => |map| { + var val = map.get(get.name.lexeme); + if (val == null) { + std.debug.warn( + "enum {} does not have field {}\n", + vari.lexeme, + get.name.lexeme, + ); + } + return llvm.LLVMConstInt(llvm.LLVMInt32Type(), val.?.value, 1); + }, + + .Struct => @panic("TODO handle struct"), + else => { + std.debug.warn("Invalid get target: {}\n", @as(comp.SymbolType, sym.*)); + return CompileError.EmitError; + }, + } + } + + fn emitExpr( + self: *Codegen, + builder: var, + expr: *const ast.Expr, + ) anyerror!llvm.LLVMValueRef { + return switch (expr.*) { + + // TODO handle all literals, construct llvm values for them + .Literal => |literal| blk: { + break :blk switch (literal) { + // TODO other literals + .Integer32 => |val| llvm.LLVMConstInt( + llvm.LLVMInt32Type(), + @intCast(c_ulonglong, val), + 10, + ), + .Integer64 => |val| llvm.LLVMConstInt( + llvm.LLVMInt64Type(), + @intCast(c_ulonglong, val), + 10, + ), + + .Float => |val| blk2: { + var val_cstr = try std.cstr.addNullByte(self.allocator, val); + break :blk2 llvm.LLVMConstRealOfString(llvm.LLVMDoubleType(), val_cstr.ptr); + }, + .Bool => |val| blk2: { + break :blk2 mkLLVMBool(val); + }, + else => unreachable, + }; + }, + + .Unary => |unary| { + var right = try self.emitExpr(builder, unary.right); + + return switch (unary.op) { + .Negate => llvm.LLVMBuildNeg(builder, right, c"neg_tmp"), + .Not => llvm.LLVMBuildNot(builder, right, c"neg_tmp"), + }; + }, + + .Binary => |binary| { + var left = try self.emitExpr(builder, binary.left); + var right = try self.emitExpr(builder, binary.right); + + return switch (binary.op) { + .Add => llvm.LLVMBuildAdd(builder, left, right, c"addtmp"), + .Sub => llvm.LLVMBuildSub(builder, left, right, c"subtmp"), + .Mul => llvm.LLVMBuildMul(builder, left, right, c"multmp"), + + //.Div => llvm.LLVMBuildDiv(builder, left, right, c"divtmp"), + .And => llvm.LLVMBuildAnd(builder, left, right, c"andtmp"), + .Or => llvm.LLVMBuildOr(builder, left, right, c"ortmp"), + + else => { + std.debug.warn("Unexpected binary operator: '{}'\n", binary.op); + return CompileError.EmitError; + }, + }; + }, + + .Get => |get| { + var target = get.target.*; + + switch (target) { + .Variable => |vari| { + // first, we must check if the target is a type + // and emit accordingly + var kv_sym_opt = self.ctx.symbol_table.get(vari.lexeme); + if (kv_sym_opt) |kv| { + return try self.emitForVariableType(vari, get, kv); + } + + // if not, its likely a variable, we should handle it accordingly + // as well + @panic("TODO handle variables"); + }, + + else => { + std.debug.warn("Invalid get target: {}\n", @as(ast.ExprType, target)); + return CompileError.EmitError; + }, + } + }, + + .Call => |call| { + const name = call.callee.*.Variable.lexeme; + + var llvm_func = self.llvm_table.get(name); + if (llvm_func == null) { + std.debug.warn("Function '{}' not found\n", name); + return CompileError.EmitError; + } + + var args = LLVMValueList.init(self.allocator); + errdefer args.deinit(); + + for (call.arguments.toSlice()) |arg_expr| { + var arg_val = try self.emitExpr(builder, &arg_expr); + try args.append(arg_val); + } + + var args_slice = args.toSlice(); + + return llvm.LLVMBuildCall( + builder, + llvm_func.?.value, + args_slice.ptr, + @intCast(c_uint, args_slice.len), + c"call", + ); + }, + + .Assign => |assign| { + const name = assign.name.lexeme; + var meta = self.ctx.current_scope.?.meta_map.get(name).?.value; + var assign_expr = try self.emitExpr(builder, assign.value); + var llvm_alloca: llvm.LLVMValueRef = switch (meta.using) { + .Function => meta.from_function.?.parameters.get(name).?.value.llvm_alloca.?, + .Scope => meta.llvm_alloca.?, + }; + + return llvm.LLVMBuildStore(builder, assign_expr, llvm_alloca); + }, + + .Variable => |vari| { + var kv_opt = self.ctx.current_scope.?.meta_map.get(vari.lexeme); + + if (kv_opt == null) { + std.debug.warn("variable {} not fully analyzed\n", vari.lexeme); + return CompileError.EmitError; + } + + // we have metadata, which means we can check if the variable + // is coming from the scope or from the function + + var metadata = kv_opt.?.value; + std.debug.warn("!! LOAD FROM VAR META {}\n", @ptrToInt(metadata)); + + var buf = try self.allocator.alloc(u8, 512); + errdefer self.allocator.free(buf); + + var load_str = try std.fmt.bufPrint(buf, "{}_loaded", vari.lexeme); + + var load_cstr = try std.cstr.addNullByte(self.allocator, load_str); + errdefer self.allocator.free(load_cstr); + + return switch (metadata.using) { + .Function => blk: { + var param = metadata.from_function.?.parameters.get(vari.lexeme).?.value; + break :blk llvm.LLVMBuildLoad(builder, param.llvm_alloca.?, load_cstr.ptr); + }, + + .Scope => blk: { + var llvm_alloca = metadata.llvm_alloca.?; + //var var_typ = metadata.from_scope.?.env.get(vari.lexeme).?.value; + break :blk llvm.LLVMBuildLoad(builder, llvm_alloca, load_cstr.ptr); + }, + }; + }, + + .Grouping => |expr_ptr| blk: { + break :blk try self.emitExpr(builder, expr_ptr); + }, + + else => { + std.debug.warn("Got unexpected expr {}\n", @as(ast.ExprType, expr.*)); + return CompileError.EmitError; + }, + }; + } + + fn emitStmt(self: *Codegen, builder: var, stmt: *ast.Stmt) anyerror!void { + std.debug.warn("cgen: emitting stmt {}\n", @as(ast.StmtType, stmt.*)); + + switch (stmt.*) { + .Expr => |expr| _ = try self.emitExpr(builder, expr), + + .Return => |ret| { + var ret_expr = try self.emitExpr(builder, ret.value); + _ = llvm.LLVMBuildRet(builder, ret_expr); + }, + + .If => |ifstmt| { + var cond = try self.emitExpr(builder, ifstmt.condition); + var zero = mkLLVMBool(false); + var icmp = llvm.LLVMBuildICmp(builder, llvm.LLVMIntPredicate.LLVMIntNE, cond, zero, c"ifcond"); + + var insert = llvm.LLVMGetInsertBlock(builder); + var function = llvm.LLVMGetBasicBlockParent(insert); + + var then_bb = llvm.LLVMAppendBasicBlock(function, c"then"); + var else_bb = llvm.LLVMAppendBasicBlock(function, c"else"); + var merge_bb = llvm.LLVMAppendBasicBlock(function, c"ifcont"); + + var condbr = llvm.LLVMBuildCondBr(builder, icmp, then_bb, else_bb); + + llvm.LLVMPositionBuilderAtEnd(builder, then_bb); + + // roughly translating to kaleidoscope's + // 'Value *ThenV = Then->codegen();' + var then_rets = false; + var else_rets = false; + + self.ctx.setScope(self.ctx.current_scope.?.nextChild()); + + var then_branch = ifstmt.then_branch.toSlice(); + for (then_branch) |_, idx| { + // keep emitting until branch has ret + var then_stmt = &then_branch[idx]; + + if (!then_rets) + try self.emitStmt(builder, then_stmt); + + // TODO break? lol + switch (then_stmt.*) { + .Return => then_rets = true, + else => {}, + } + } + + self.ctx.dumpScope(); + + // only build the br instruction if we didn't ret, because + // there can't be any instruction after a terminator + // same applies for the else branch + if (!then_rets) + _ = llvm.LLVMBuildBr(builder, merge_bb); + + then_bb = llvm.LLVMGetInsertBlock(builder); + + llvm.LLVMPositionBuilderAtEnd(builder, else_bb); + + // roughly translating to kaleidoscope's + // 'Else *ElseV = Else->codegen();' + if (ifstmt.else_branch) |else_block| { + self.ctx.setScope(self.ctx.current_scope.?.nextChild()); + + var else_slice = else_block.toSlice(); + for (else_slice) |_, idx| { + // keep emitting until branch has ret + var else_stmt = &else_slice[idx]; + + if (!else_rets) + try self.emitStmt(builder, else_stmt); + + switch (else_stmt.*) { + .Return => else_rets = true, + else => {}, + } + } + + self.ctx.dumpScope(); + } + + if (!else_rets) + _ = llvm.LLVMBuildBr(builder, merge_bb); + + else_bb = llvm.LLVMGetInsertBlock(builder); + + llvm.LLVMPositionBuilderAtEnd(builder, merge_bb); + + // if both of the branches return, we should put + // the merge branch as unreachable. + if (then_rets and else_rets) + _ = llvm.LLVMBuildUnreachable(builder); + }, + + .VarDecl => |vardecl| { + // we alaready inferred the type of the variable in the + // analyze pass and the current scope contains the variable's + // type(hopefully), so we resolve it + const name = vardecl.name.lexeme; + var var_metadata = self.ctx.current_scope.?.meta_map.get(name).?.value; + + var name_cstr = try std.cstr.addNullByte(self.allocator, name); + errdefer self.allocator.free(name_cstr); + + var fn_symbol = self.getFnSymbol(self.current_function_name.?); + + var variable = llvm.LLVMBuildAlloca( + builder, + try self.typeToLLVM(var_metadata.typ), + name_cstr.ptr, + ); + + stmt.*.VarDecl.llvm_alloca = variable; + + var_metadata.*.llvm_alloca = variable; + + std.debug.warn("!! DECL VAR {} => {}\n", @ptrToInt(var_metadata), variable); + + var llvm_expr = try self.emitExpr(builder, vardecl.value); + _ = llvm.LLVMBuildStore(builder, llvm_expr, variable); + }, + + else => { + std.debug.warn("Got unexpected stmt {}\n", stmt.*); + return CompileError.EmitError; + }, + } + } + + fn getFnSymbol(self: *@This(), name: []const u8) *comp.FunctionSymbol { + var fn_sym_search = self.ctx.symbol_table.get(name).?.value; + std.debug.assert(@as(comp.SymbolType, fn_sym_search.*) == .Function); + return &fn_sym_search.Function; + } + + /// Emit LLVM ir for the given node. + fn genNode( + self: *Codegen, + mod: llvm.LLVMModuleRef, + node: *ast.Node, + ) !void { + switch (node.*) { + .Root => @panic("Should not have gotten Root"), + .FnDecl => |decl| { + const name = decl.func_name.lexeme; + self.current_function_name = name; + std.debug.warn("cgen: genning function '{}'\n", name); + + var fn_sym = self.getFnSymbol(name); + + const name_cstr = try std.cstr.addNullByte(self.allocator, name); + errdefer self.allocator.free(name_cstr); + + var param_types = llvm.LLVMTypeList.init(self.allocator); + errdefer param_types.deinit(); + + for (decl.params.toSlice()) |param| { + try param_types.append(try self.typeToLLVM(fn_sym.parameters.get( + param.name.lexeme, + ).?.value.typ)); + } + + var llvm_ret_type = llvm.LLVMFunctionType( + try self.typeToLLVM(fn_sym.return_type), + param_types.toSlice().ptr, + @intCast(c_uint, param_types.len), + 0, + ); + + var func = llvm.LLVMAddFunction(mod, name_cstr.ptr, llvm_ret_type); + _ = try self.llvm_table.put(name, func); + + var buf = try self.allocator.alloc(u8, 512); + var entry_lbl = try std.fmt.bufPrint(buf, "fn_{}_entry", name); + var entry_lbl_cstr = try std.cstr.addNullByte(self.allocator, entry_lbl); + var entry = llvm.LLVMAppendBasicBlock(func, entry_lbl_cstr.ptr); + + var builder = llvm.LLVMCreateBuilder(); + llvm.LLVMPositionBuilderAtEnd(builder, entry); + + // to have the ability to mutate parameters, we must allocate them on + // the stack + var params_slice = decl.params.toSlice(); + for (params_slice) |param_node, idx| { + var param = fn_sym.parameters.get(param_node.name.lexeme).?.value; + + const param_name_cstr = try std.cstr.addNullByte(self.allocator, param_node.name.lexeme); + errdefer self.allocator.free(param_name_cstr); + + var alloca = llvm.LLVMBuildAlloca(builder, try self.typeToLLVM(param.typ), param_name_cstr.ptr); + + std.debug.warn("SET PARAM LLVM ALLOCA {} to {}\n", param_node.name.lexeme, alloca); + param.llvm_alloca = alloca; + + _ = llvm.LLVMBuildStore( + builder, + llvm.LLVMGetParam(func, @intCast(c_uint, idx)), + alloca, + ); + } + + self.ctx.setScope(fn_sym.scope); + + // TODO check if stmt is return and if we already + // returned before + var body_slice = decl.body.toSlice(); + for (body_slice) |_, idx| { + try self.emitStmt(builder, &body_slice[idx]); + } + + self.ctx.dumpScope(); + std.debug.warn("cgen: generated function '{}'\n", name); + }, + + // NOTE: enums don't have specific llvm ir code generated for them + .Enum => {}, + + .ConstDecl => |constdecls| { + for (constdecls.toSlice()) |constdecl| { + const name = constdecl.name.lexeme; + + var const_type = self.ctx.symbol_table.get(name).?.value; + var const_llvm_type = try self.typeToLLVM(const_type.Const); + + const const_name = try std.cstr.addNullByte(self.allocator, name); + errdefer self.allocator.free(const_name); + + var global = llvm.LLVMAddGlobal(mod, const_llvm_type, const_name.ptr); + + // TODO maybe put builder at main function so we can still + // call other functions inside consts? + + var builder = llvm.LLVMCreateBuilder(); + var expr_llvm_val = try self.emitExpr(builder, constdecl.expr); + + llvm.LLVMSetInitializer(global, expr_llvm_val); + } + }, + + else => { + std.debug.warn("TODO handle node type {}\n", @tagName(node.*)); + return; + }, + } + } + + pub fn gen(self: *Codegen, root: *ast.Node) !void { + std.debug.warn("cgen: start gen\n"); + _ = llvm.LLVMInitializeNativeTarget(); + + var mod = llvm.LLVMModuleCreateWithName(c"awoo").?; + defer llvm.LLVMDisposeModule(mod); + + var root_slice = root.Root.toSlice(); + for (root_slice) |_, idx| { + try self.genNode(mod, &root_slice[idx]); + } + + var err: ?[*]u8 = null; + defer llvm.LLVMDisposeMessage(err); + + if (llvm.LLVMPrintModuleToFile(mod, c"output.ll", &err) != 0) { + std.debug.warn("error printing module to file: {}\n", sliceify(err)); + return CompileError.BackendError; + } + + //if (llvm.LLVMWriteBitcodeToFile(mod, c"awoo.bc") != 0) { + // std.debug.warn("error writing bitcode to file: {}\n", sliceify(err)); + // return CompileError.BackendError; + //} + + std.debug.warn("cgen: verify llvm module\n"); + _ = llvm.LLVMVerifyModule( + mod, + llvm.LLVMVerifierFailureAction.LLVMAbortProcessAction, + &err, + ); + + llvm.LLVMInitializeAllTargetInfos(); + llvm.LLVMInitializeAllTargets(); + llvm.LLVMInitializeAllTargetMCs(); + llvm.LLVMInitializeAllAsmParsers(); + llvm.LLVMInitializeAllAsmPrinters(); + + var engine: llvm.LLVMExecutionEngineRef = undefined; + if (llvm.LLVMCreateExecutionEngineForModule(&engine, mod, &err) != 0) { + std.debug.warn("failed to create execution engine: {}\n", sliceify(err)); + return CompileError.BackendError; + } + + var machine = llvm.LLVMGetExecutionEngineTargetMachine(engine); + defer llvm.LLVMDisposeTargetMachine(machine); + + var target = llvm.LLVMGetTargetMachineTarget(machine); + var target_data = llvm.LLVMCreateTargetDataLayout(machine); + var data_layout = llvm.LLVMCopyStringRepOfTargetData(target_data); + llvm.LLVMSetDataLayout(mod, data_layout); + + var outpath_cstr = try std.cstr.addNullByte(self.allocator, "outpath.o"); + + //var asmpath_cstr = try std.cstr.addNullByte(self.allocator, "output.S"); + + var desc = llvm.LLVMGetTargetDescription(target); + var features = llvm.LLVMGetTargetMachineFeatureString(machine); + var triple = llvm.LLVMGetTargetMachineTriple(machine); + + std.debug.warn("target: {}\n", sliceify(desc)); + std.debug.warn("triple: {}\n", sliceify(triple)); + std.debug.warn("features: {}\n", sliceify(features)); + + //if (llvm.LLVMTargetMachineEmitToFile( + // machine, + // mod, + // asmpath_cstr.ptr, + // llvm.LLVMCodeGenFileType.LLVMAssemblyFile, + // &err, + //) != 0) { + // std.debug.warn("failed to emit to assembly file: {}\n", sliceify(err)); + // return CompileError.BackendError; + //} + + if (llvm.LLVMTargetMachineEmitToFile( + machine, + mod, + outpath_cstr.ptr, + llvm.LLVMCodeGenFileType.LLVMObjectFile, + &err, + ) != 0) { + std.debug.warn("failed to emit to file: {}\n", sliceify(err)); + return CompileError.BackendError; + } + } +}; diff --git a/src/comp_ctx.zig b/src/comp_ctx.zig index 0d4246c..fdbcaeb 100644 --- a/src/comp_ctx.zig +++ b/src/comp_ctx.zig @@ -355,7 +355,7 @@ pub const CompilationContext = struct { var value = sym_kv.?.value; - var sym_typ = SymbolType(value.*); + var sym_typ = @as(SymbolType, value.*); if (sym_typ != typ) { std.debug.warn("Expected {}, got {}\n", sym_typ, typ); return CompilationError.TypeError; diff --git a/src/main.zig b/src/main.zig index 17e004e..4dc9918 100644 --- a/src/main.zig +++ b/src/main.zig @@ -56,7 +56,7 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { std.debug.warn("symbol table\n"); printer.printContext(ctx); - var cgen = codegen.Codegen.init(allocator, &ctx); + var cgen = codegen.llvm.Codegen.init(allocator, &ctx); try cgen.gen(root); var child = try std.ChildProcess.init( diff --git a/src/parsers.zig b/src/parsers.zig index 75bedfc..dbf3722 100644 --- a/src/parsers.zig +++ b/src/parsers.zig @@ -1026,8 +1026,9 @@ pub const Parser = struct { fn finishStructVal(self: *@This(), expr: *Expr) !*Expr { // {a: 10 b: 10} // for this to work properly, must be Variable, since its a type. - if (ast.ExprType(expr.*) != .Variable) { - return self.doError("Expected variable for struct type, got {}", ast.ExprType(expr.*)); + const expr_type = @as(ast.ExprType, expr.*); + if (expr_type != .Variable) { + return self.doError("Expected variable for struct type, got {}", expr_type); } var inits = ast.StructInitList.init(self.allocator); From 9a9008247fded846b4c027f019a8156f80f3b5d0 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 25 Nov 2019 21:44:04 -0300 Subject: [PATCH 03/10] move x86 to codegen.x86 --- src/codegen.zig | 2 +- src/{ => codegen}/x86.zig | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{ => codegen}/x86.zig (100%) diff --git a/src/codegen.zig b/src/codegen.zig index 38aa1bd..9f64b56 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1,5 +1,5 @@ pub const llvm = @import("codegen/llvm.zig"); -// pub const x86 = @import("codegen/x86.zig"); +pub const x86 = @import("codegen/x86.zig"); pub const CompileError = error{ BackendError, diff --git a/src/x86.zig b/src/codegen/x86.zig similarity index 100% rename from src/x86.zig rename to src/codegen/x86.zig From ebf4af6537683212c4a74d41a8fc1c5744c9bcb7 Mon Sep 17 00:00:00 2001 From: Luna Date: Sat, 7 Dec 2019 20:28:55 -0300 Subject: [PATCH 04/10] fixes for latest zig --- examples/hello.ry | 2 +- src/codegen/llvm.zig | 37 ++++++++++++++++++------------------- src/main.zig | 2 +- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/examples/hello.ry b/examples/hello.ry index 62bfab3..40e69a4 100644 --- a/examples/hello.ry +++ b/examples/hello.ry @@ -30,5 +30,5 @@ fn add(a: i32, b: i32) i32 { } fn main() i32 { - return 1; + return 123; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 6da6f82..6071da0 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -4,8 +4,7 @@ const llvm = @import("../llvm.zig"); const comp = @import("../comp_ctx.zig"); const CompileError = @import("../codegen.zig").CompileError; -fn sliceify(non_slice: ?[*]const u8) []const u8 { - if (non_slice == null) return ""; +fn sliceify(non_slice: ?[*:0]const u8) []const u8 { return non_slice.?[0..std.mem.len(u8, non_slice.?)]; } @@ -126,8 +125,8 @@ pub const Codegen = struct { var right = try self.emitExpr(builder, unary.right); return switch (unary.op) { - .Negate => llvm.LLVMBuildNeg(builder, right, c"neg_tmp"), - .Not => llvm.LLVMBuildNot(builder, right, c"neg_tmp"), + .Negate => llvm.LLVMBuildNeg(builder, right, "neg_tmp"), + .Not => llvm.LLVMBuildNot(builder, right, "neg_tmp"), }; }, @@ -136,13 +135,13 @@ pub const Codegen = struct { var right = try self.emitExpr(builder, binary.right); return switch (binary.op) { - .Add => llvm.LLVMBuildAdd(builder, left, right, c"addtmp"), - .Sub => llvm.LLVMBuildSub(builder, left, right, c"subtmp"), - .Mul => llvm.LLVMBuildMul(builder, left, right, c"multmp"), + .Add => llvm.LLVMBuildAdd(builder, left, right, "addtmp"), + .Sub => llvm.LLVMBuildSub(builder, left, right, "subtmp"), + .Mul => llvm.LLVMBuildMul(builder, left, right, "multmp"), - //.Div => llvm.LLVMBuildDiv(builder, left, right, c"divtmp"), - .And => llvm.LLVMBuildAnd(builder, left, right, c"andtmp"), - .Or => llvm.LLVMBuildOr(builder, left, right, c"ortmp"), + //.Div => llvm.LLVMBuildDiv(builder, left, right, "divtmp"), + .And => llvm.LLVMBuildAnd(builder, left, right, "andtmp"), + .Or => llvm.LLVMBuildOr(builder, left, right, "ortmp"), else => { std.debug.warn("Unexpected binary operator: '{}'\n", binary.op); @@ -199,7 +198,7 @@ pub const Codegen = struct { llvm_func.?.value, args_slice.ptr, @intCast(c_uint, args_slice.len), - c"call", + "call", ); }, @@ -276,14 +275,14 @@ pub const Codegen = struct { .If => |ifstmt| { var cond = try self.emitExpr(builder, ifstmt.condition); var zero = mkLLVMBool(false); - var icmp = llvm.LLVMBuildICmp(builder, llvm.LLVMIntPredicate.LLVMIntNE, cond, zero, c"ifcond"); + var icmp = llvm.LLVMBuildICmp(builder, llvm.LLVMIntPredicate.LLVMIntNE, cond, zero, "ifcond"); var insert = llvm.LLVMGetInsertBlock(builder); var function = llvm.LLVMGetBasicBlockParent(insert); - var then_bb = llvm.LLVMAppendBasicBlock(function, c"then"); - var else_bb = llvm.LLVMAppendBasicBlock(function, c"else"); - var merge_bb = llvm.LLVMAppendBasicBlock(function, c"ifcont"); + var then_bb = llvm.LLVMAppendBasicBlock(function, "then"); + var else_bb = llvm.LLVMAppendBasicBlock(function, "else"); + var merge_bb = llvm.LLVMAppendBasicBlock(function, "ifcont"); var condbr = llvm.LLVMBuildCondBr(builder, icmp, then_bb, else_bb); @@ -514,7 +513,7 @@ pub const Codegen = struct { std.debug.warn("cgen: start gen\n"); _ = llvm.LLVMInitializeNativeTarget(); - var mod = llvm.LLVMModuleCreateWithName(c"awoo").?; + var mod = llvm.LLVMModuleCreateWithName("awoo").?; defer llvm.LLVMDisposeModule(mod); var root_slice = root.Root.toSlice(); @@ -522,15 +521,15 @@ pub const Codegen = struct { try self.genNode(mod, &root_slice[idx]); } - var err: ?[*]u8 = null; + var err: ?[*:0]u8 = null; defer llvm.LLVMDisposeMessage(err); - if (llvm.LLVMPrintModuleToFile(mod, c"output.ll", &err) != 0) { + if (llvm.LLVMPrintModuleToFile(mod, "output.ll", &err) != 0) { std.debug.warn("error printing module to file: {}\n", sliceify(err)); return CompileError.BackendError; } - //if (llvm.LLVMWriteBitcodeToFile(mod, c"awoo.bc") != 0) { + //if (llvm.LLVMWriteBitcodeToFile(mod, "awoo.bc") != 0) { // std.debug.warn("error writing bitcode to file: {}\n", sliceify(err)); // return CompileError.BackendError; //} diff --git a/src/main.zig b/src/main.zig index 4dc9918..5e91ab8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -60,7 +60,7 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { try cgen.gen(root); var child = try std.ChildProcess.init( - [_][]const u8{ "gcc", "src/entry.c", "outpath.o", "-o", "a.out" }, + &[_][]const u8{ "gcc", "src/entry.c", "outpath.o", "-o", "a.out" }, allocator, ); try child.spawn(); From cf22d47e137f4069050d60abcce238a5539f5123 Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 1 Apr 2020 16:03:46 -0300 Subject: [PATCH 05/10] ast_printer: tuple-ify --- src/ast_printer.zig | 128 ++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/src/ast_printer.zig b/src/ast_printer.zig index 36bd72a..1bdc248 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -10,7 +10,7 @@ const warn = std.debug.warn; fn printIdent(ident: usize) void { var i: usize = 0; while (i < ident) : (i += 1) { - std.debug.warn("\t"); + std.debug.warn("\t", .{}); } } @@ -20,12 +20,12 @@ fn print(ident: usize, comptime fmt: []const u8, args: ...) void { } fn printBlock(ident: usize, block: var, endNewline: bool) void { - std.debug.warn("(\n"); + std.debug.warn("(\n", .{}); for (block.toSlice()) |stmt| { printIdent(ident); printStmt(ident, &stmt); - std.debug.warn("\n"); + std.debug.warn("\n", .{}); } if (endNewline) { @@ -48,18 +48,18 @@ pub fn printNode(node: *const Node, ident: usize) void { const vari = method.variable.lexeme; const typ = method.typ.lexeme; - warn("(method {} {} {} {} (", vari, typ, name, ret_type); + warn("(method {} {} {} {} (", .{ vari, typ, name, ret_type }); } else { - warn("(fn {} {} (", name, ret_type); + warn("(fn {} {} (", .{ name, ret_type }); } for (decl.params.toSlice()) |param| { - warn(" ({} {})", param.name.lexeme, param.typ.lexeme); + warn(" ({} {})", .{ param.name.lexeme, param.typ.lexeme }); } - warn(") "); + warn(") ", .{}); printBlock(ident + 1, decl.body, false); - warn("\n"); + warn("\n", .{}); }, .ConstDecl => |consts| { @@ -73,7 +73,7 @@ pub fn printNode(node: *const Node, ident: usize) void { ); printExpr(const_decl.expr); - std.debug.warn(")\n"); + std.debug.warn(")\n", .{}); } print(ident, "))\n"); @@ -114,20 +114,20 @@ pub fn printNode(node: *const Node, ident: usize) void { } fn parenthetize(name: []const u8, exprs: []const Expr) void { - std.debug.warn("({}", name); + std.debug.warn("({}", .{name}); for (exprs) |expr| { - std.debug.warn(" "); + std.debug.warn(" ", .{}); printExpr(&expr); } - std.debug.warn(")"); + std.debug.warn(")", .{}); } fn printTwoExprs(expr_a: *const Expr, expr_b: *const Expr) void { - std.debug.warn(" "); + std.debug.warn(" ", .{}); printExpr(expr_a); - std.debug.warn(" "); + std.debug.warn(" ", .{}); printExpr(expr_b); } @@ -161,9 +161,9 @@ fn binOpToStr(op: BinaryOperator) ?[]const u8 { } fn printBinOp(inner: var) void { - std.debug.warn("({}", binOpToStr(inner.op)); + std.debug.warn("({}", .{binOpToStr(inner.op)}); printTwoExprs(inner.left, inner.right); - std.debug.warn(")"); + std.debug.warn(")", .{}); } const unary_operator_tokens = [_][]const u8{ @@ -187,9 +187,9 @@ fn printSingleOp(op: UnaryOperator, applied: *const Expr) void { } fn printSimpleOp(op: ?[]const u8, applied: *const Expr) void { - std.debug.warn("({}", op); + std.debug.warn("({}", .{op}); printExpr(applied); - std.debug.warn(")"); + std.debug.warn(")", .{}); } pub fn printExpr(expr: *const Expr) void { @@ -201,66 +201,66 @@ pub fn printExpr(expr: *const Expr) void { .Literal => |literal| { switch (literal) { - .Bool => |val| std.debug.warn("{}", val), - .Integer32 => |val| std.debug.warn("{}", val), - .Integer64 => |val| std.debug.warn("{}", val), - .Float => |val| std.debug.warn("{}", val), - .String => |val| std.debug.warn("'{}'", val), + .Bool => |val| std.debug.warn("{}", .{val}), + .Integer32 => |val| std.debug.warn("{}", .{val}), + .Integer64 => |val| std.debug.warn("{}", .{val}), + .Float => |val| std.debug.warn("{}", .{val}), + .String => |val| std.debug.warn("'{}'", .{val}), .Array => |exprs| { parenthetize("array", exprs.toSlice()); }, - else => |typ| std.debug.warn("UnknownLiteral-{}", typ), + else => |typ| std.debug.warn("UnknownLiteral-{}", .{typ}), } }, - .Variable => |token| std.debug.warn("{}", token.lexeme), + .Variable => |token| std.debug.warn("{}", .{token.lexeme}), .Assign => |assign| { - std.debug.warn("(set "); - std.debug.warn("{} ", assign.name.lexeme); + std.debug.warn("(set ", .{}); + std.debug.warn("{} ", .{assign.name.lexeme}); printExpr(assign.value); - std.debug.warn(")"); + std.debug.warn(")", .{}); }, .Call => |call| { - std.debug.warn("("); + std.debug.warn("(", .{}); printExpr(call.callee); for (call.arguments.toSlice()) |arg| { - std.debug.warn(" "); + std.debug.warn(" ", .{}); printExpr(&arg); } - std.debug.warn(")"); + std.debug.warn(")", .{}); }, .Struct => |val| { - std.debug.warn("({} (", val.name.lexeme); + std.debug.warn("({} (", .{val.name.lexeme}); for (val.inits.toSlice()) |init| { - std.debug.warn(" ({} ", init.field.lexeme); + std.debug.warn(" ({} ", .{init.field.lexeme}); printExpr(init.expr); - std.debug.warn(")"); + std.debug.warn(")", .{}); } - std.debug.warn("))"); + std.debug.warn("))", .{}); }, .Get => |get| { - warn("("); + warn("(", .{}); printExpr(get.target); warn(".{})", get.name.lexeme); }, .Set => |set| { - warn("(set "); + warn("(set ", .{}); printExpr(set.struc); - warn(" {} ", set.field.lexeme); + warn(" {} ", .{set.field.lexeme}); printExpr(set.value); - warn(")"); + warn(")", .{}); }, - else => std.debug.warn("UnknownExpr-{}", @tagName(expr.*)), + else => std.debug.warn("UnknownExpr-{}", .{@tagName(expr.*)}), } } @@ -270,60 +270,60 @@ pub fn printStmt(ident: usize, stmt: *const Stmt) void { .Expr => |expr| printExpr(expr), .VarDecl => |decl| { - std.debug.warn("(let {} ", decl.name.lexeme); + std.debug.warn("(let {} ", .{decl.name.lexeme}); printExpr(decl.value); - std.debug.warn(")"); + std.debug.warn(")", .{}); }, .If => |ifstmt| { - std.debug.warn("(if "); + std.debug.warn("(if ", .{}); printExpr(ifstmt.condition); - std.debug.warn(" "); + std.debug.warn(" ", .{}); printBlock(ident + 1, ifstmt.then_branch, false); if (ifstmt.else_branch) |else_branch| { - std.debug.warn(" else "); + std.debug.warn(" else ", .{}); printBlock(ident + 1, else_branch, false); } - std.debug.warn(")\n"); + std.debug.warn(")\n", .{}); }, .Loop => |loop| { - std.debug.warn("(loop "); + std.debug.warn("(loop ", .{}); if (loop.condition) |cond| { printExpr(cond); } else { - std.debug.warn("true"); + std.debug.warn("true", .{}); } - std.debug.warn(" "); + std.debug.warn(" ", .{}); printBlock(ident + 1, loop.then_branch, false); - std.debug.warn(")\n"); + std.debug.warn(")\n", .{}); }, .For => |forstmt| { - std.debug.warn("(for "); + std.debug.warn("(for ", .{}); if (forstmt.index) |index| { - std.debug.warn("({} {}) ", index.lexeme, forstmt.value.lexeme); + std.debug.warn("({} {}) ", .{ index.lexeme, forstmt.value.lexeme }); } else { - std.debug.warn("{} ", forstmt.value.lexeme); + std.debug.warn("{} ", .{forstmt.value.lexeme}); } - std.debug.warn("{} ", forstmt.array.lexeme); + std.debug.warn("{} ", .{forstmt.array.lexeme}); printBlock(ident + 1, forstmt.block, false); - std.debug.warn(")\n"); + std.debug.warn(")\n", .{}); }, .Return => |ret| { - std.debug.warn("(return "); + std.debug.warn("(return ", .{}); printExpr(ret.value); - std.debug.warn(")\n"); + std.debug.warn(")\n", .{}); }, - else => std.debug.warn("UnknownStmt-{}", @tagName(stmt.*)), + else => std.debug.warn("UnknownStmt-{}", .{@tagName(stmt.*)}), } } @@ -381,12 +381,12 @@ pub fn printContext(ctx: CompilationContext) void { } // go through scopes - std.debug.warn("scope info:\n"); + std.debug.warn("scope info:\n", .{}); printScope(fn_sym.scope, 1); }, .Struct => |typemap| { - std.debug.warn("struct '{}'\n", kv.key); + std.debug.warn("struct '{}'\n", .{kv.key}); var map_it = typemap.iterator(); while (map_it.next()) |map_kv| { std.debug.warn( @@ -404,21 +404,21 @@ pub fn printContext(ctx: CompilationContext) void { ), .Enum => |identmap| { - std.debug.warn("enum {}:", kv.key); + std.debug.warn("enum {}:", .{kv.key}); var mapit = identmap.iterator(); while (mapit.next()) |field_kv| { - std.debug.warn("\t{} => {}\n", field_kv.key, field_kv.value); + std.debug.warn("\t{} => {}\n", .{ field_kv.key, field_kv.value }); } }, .Const => |typ| { - std.debug.warn("const '{}', typ={}\n", kv.key, prettyType(typ)); + std.debug.warn("const '{}', typ={}\n", .{ kv.key, prettyType(typ) }); }, else => { - std.debug.warn("TODO handle print of {}\n", kv.value); + std.debug.warn("TODO handle print of {}\n", .{kv.value}); unreachable; }, } From 7976b64cf624f37417b592c5c09a7656142002b4 Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 1 Apr 2020 16:09:39 -0300 Subject: [PATCH 06/10] tuple-inator pass --- src/analysis.zig | 20 ++++++++-------- src/codegen/llvm.zig | 54 ++++++++++++++++++++++---------------------- src/comp_ctx.zig | 14 ++++++------ src/errors.zig | 10 ++++---- src/main.zig | 8 +++---- src/parsers.zig | 12 +++++----- 6 files changed, 59 insertions(+), 59 deletions(-) diff --git a/src/analysis.zig b/src/analysis.zig index c3363a5..4f92c4a 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -45,18 +45,18 @@ pub const Analyzer = struct { fn doError(self: *@This(), comptime fmt: []const u8, args: ...) void { self.hadError = true; - std.debug.warn("analysis error"); + std.debug.warn("analysis error" , .{ }); if (self.err_tok) |tok| { - std.debug.warn(" at line {}", tok.line); + std.debug.warn(" at line {}" , .{ tok.line }); } if (self.err_ctx) |ctx| { - std.debug.warn(" on {}", ctx); + std.debug.warn(" on {}" , .{ ctx }); } - std.debug.warn("\n\t"); + std.debug.warn("\n\t" , .{ }); std.debug.warn(fmt, args); - std.debug.warn("\n"); + std.debug.warn("\n" , .{ }); } /// Resolve a type in global scope @@ -108,7 +108,7 @@ pub const Analyzer = struct { ) !void { var actual_enum = @as(comp.SymbolUnderlyingTypeEnum, symbol_type); if (actual_enum != wanted_type_enum) { - std.debug.warn("Expected {}, got {}\n", wanted_type_enum, actual_enum); + std.debug.warn("Expected {}, got {}\n" , .{ wanted_type_enum, actual_enum }); return CompileError.TypeError; } } @@ -122,7 +122,7 @@ pub const Analyzer = struct { .Integer32, .Integer64, .Double => {}, else => { var actual_enum = @as(comp.SymbolUnderlyingTypeEnum, symbol_type); - std.debug.warn("Expected numeric, got {}\n", actual_enum); + std.debug.warn("Expected numeric, got {}\n" , .{ actual_enum }); return CompileError.TypeError; }, } @@ -158,7 +158,7 @@ pub const Analyzer = struct { const expected_enum = @as(comp.SymbolUnderlyingTypeEnum, expected_type); if (symbol_enum != expected_enum) { - std.debug.warn("Expected {}, got {}\n", expected_enum, symbol_enum); + std.debug.warn("Expected {}, got {}\n" , .{ expected_enum, symbol_enum }); return CompileError.TypeError; } @@ -292,7 +292,7 @@ pub const Analyzer = struct { var target = get.target.*; const target_type = @as(ast.ExprType, target); if (target_type != .Variable) { - std.debug.warn("Expected Variable as get target, got {}\n", target_type); + std.debug.warn("Expected Variable as get target, got {}\n" , .{ target_type }); return CompileError.TypeError; } @@ -475,7 +475,7 @@ pub const Analyzer = struct { self.setErrContext("function {}", name); var ret_type = self.resolveGlobalType(ctx, decl.return_type.lexeme); - std.debug.warn("start analysis of fn {}, ret type: {}\n", decl.func_name.lexeme, ret_type); + std.debug.warn("start analysis of fn {}, ret type: {}\n" , .{ decl.func_name.lexeme, ret_type }); var parameters = comp.TypeList.init(self.allocator); for (decl.params.toSlice()) |param| { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 6071da0..010dc1c 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -41,7 +41,7 @@ pub const Codegen = struct { .Bool => llvm.LLVMInt1Type(), .OpaqueType => |val| { - std.debug.warn("Invalid return type: {}\n", val); + std.debug.warn("Invalid return type: {}\n", .{val}); return CompileError.TypeError; }, @@ -51,14 +51,14 @@ pub const Codegen = struct { .Struct => unreachable, .Enum => llvm.LLVMInt32Type(), else => { - std.debug.warn("Function {} is not a type\n", lex); + std.debug.warn("Function {} is not a type\n", .{lex}); return CompileError.TypeError; }, }; }, else => { - std.debug.warn("TODO handle {}\n", typ); + std.debug.warn("TODO handle {}\n", .{typ}); return CompileError.TypeError; }, }; @@ -82,7 +82,7 @@ pub const Codegen = struct { .Struct => @panic("TODO handle struct"), else => { - std.debug.warn("Invalid get target: {}\n", @as(comp.SymbolType, sym.*)); + std.debug.warn("Invalid get target: {}\n", .{@as(comp.SymbolType, sym.*)}); return CompileError.EmitError; }, } @@ -144,7 +144,7 @@ pub const Codegen = struct { .Or => llvm.LLVMBuildOr(builder, left, right, "ortmp"), else => { - std.debug.warn("Unexpected binary operator: '{}'\n", binary.op); + std.debug.warn("Unexpected binary operator: '{}'\n", .{binary.op}); return CompileError.EmitError; }, }; @@ -168,7 +168,7 @@ pub const Codegen = struct { }, else => { - std.debug.warn("Invalid get target: {}\n", @as(ast.ExprType, target)); + std.debug.warn("Invalid get target: {}\n", .{@as(ast.ExprType, target)}); return CompileError.EmitError; }, } @@ -179,7 +179,7 @@ pub const Codegen = struct { var llvm_func = self.llvm_table.get(name); if (llvm_func == null) { - std.debug.warn("Function '{}' not found\n", name); + std.debug.warn("Function '{}' not found\n", .{name}); return CompileError.EmitError; } @@ -218,7 +218,7 @@ pub const Codegen = struct { var kv_opt = self.ctx.current_scope.?.meta_map.get(vari.lexeme); if (kv_opt == null) { - std.debug.warn("variable {} not fully analyzed\n", vari.lexeme); + std.debug.warn("variable {} not fully analyzed\n", .{vari.lexeme}); return CompileError.EmitError; } @@ -226,7 +226,7 @@ pub const Codegen = struct { // is coming from the scope or from the function var metadata = kv_opt.?.value; - std.debug.warn("!! LOAD FROM VAR META {}\n", @ptrToInt(metadata)); + std.debug.warn("!! LOAD FROM VAR META {}\n", .{@ptrToInt(metadata)}); var buf = try self.allocator.alloc(u8, 512); errdefer self.allocator.free(buf); @@ -255,14 +255,14 @@ pub const Codegen = struct { }, else => { - std.debug.warn("Got unexpected expr {}\n", @as(ast.ExprType, expr.*)); + std.debug.warn("Got unexpected expr {}\n", .{@as(ast.ExprType, expr.*)}); return CompileError.EmitError; }, }; } fn emitStmt(self: *Codegen, builder: var, stmt: *ast.Stmt) anyerror!void { - std.debug.warn("cgen: emitting stmt {}\n", @as(ast.StmtType, stmt.*)); + std.debug.warn("cgen: emitting stmt {}\n", .{@as(ast.StmtType, stmt.*)}); switch (stmt.*) { .Expr => |expr| _ = try self.emitExpr(builder, expr), @@ -379,14 +379,14 @@ pub const Codegen = struct { var_metadata.*.llvm_alloca = variable; - std.debug.warn("!! DECL VAR {} => {}\n", @ptrToInt(var_metadata), variable); + std.debug.warn("!! DECL VAR {} => {}\n", .{ @ptrToInt(var_metadata), variable }); var llvm_expr = try self.emitExpr(builder, vardecl.value); _ = llvm.LLVMBuildStore(builder, llvm_expr, variable); }, else => { - std.debug.warn("Got unexpected stmt {}\n", stmt.*); + std.debug.warn("Got unexpected stmt {}\n", .{stmt.*}); return CompileError.EmitError; }, } @@ -409,7 +409,7 @@ pub const Codegen = struct { .FnDecl => |decl| { const name = decl.func_name.lexeme; self.current_function_name = name; - std.debug.warn("cgen: genning function '{}'\n", name); + std.debug.warn("cgen: genning function '{}'\n", .{name}); var fn_sym = self.getFnSymbol(name); @@ -454,7 +454,7 @@ pub const Codegen = struct { var alloca = llvm.LLVMBuildAlloca(builder, try self.typeToLLVM(param.typ), param_name_cstr.ptr); - std.debug.warn("SET PARAM LLVM ALLOCA {} to {}\n", param_node.name.lexeme, alloca); + std.debug.warn("SET PARAM LLVM ALLOCA {} to {}\n", .{ param_node.name.lexeme, alloca }); param.llvm_alloca = alloca; _ = llvm.LLVMBuildStore( @@ -474,7 +474,7 @@ pub const Codegen = struct { } self.ctx.dumpScope(); - std.debug.warn("cgen: generated function '{}'\n", name); + std.debug.warn("cgen: generated function '{}'\n", .{name}); }, // NOTE: enums don't have specific llvm ir code generated for them @@ -503,14 +503,14 @@ pub const Codegen = struct { }, else => { - std.debug.warn("TODO handle node type {}\n", @tagName(node.*)); + std.debug.warn("TODO handle node type {}\n", .{@tagName(node.*)}); return; }, } } pub fn gen(self: *Codegen, root: *ast.Node) !void { - std.debug.warn("cgen: start gen\n"); + std.debug.warn("cgen: start gen\n", .{}); _ = llvm.LLVMInitializeNativeTarget(); var mod = llvm.LLVMModuleCreateWithName("awoo").?; @@ -525,16 +525,16 @@ pub const Codegen = struct { defer llvm.LLVMDisposeMessage(err); if (llvm.LLVMPrintModuleToFile(mod, "output.ll", &err) != 0) { - std.debug.warn("error printing module to file: {}\n", sliceify(err)); + std.debug.warn("error printing module to file: {}\n", .{sliceify(err)}); return CompileError.BackendError; } //if (llvm.LLVMWriteBitcodeToFile(mod, "awoo.bc") != 0) { - // std.debug.warn("error writing bitcode to file: {}\n", sliceify(err)); + // std.debug.warn("error writing bitcode to file: {}\n" , .{ sliceify(err) }); // return CompileError.BackendError; //} - std.debug.warn("cgen: verify llvm module\n"); + std.debug.warn("cgen: verify llvm module\n", .{}); _ = llvm.LLVMVerifyModule( mod, llvm.LLVMVerifierFailureAction.LLVMAbortProcessAction, @@ -549,7 +549,7 @@ pub const Codegen = struct { var engine: llvm.LLVMExecutionEngineRef = undefined; if (llvm.LLVMCreateExecutionEngineForModule(&engine, mod, &err) != 0) { - std.debug.warn("failed to create execution engine: {}\n", sliceify(err)); + std.debug.warn("failed to create execution engine: {}\n", .{sliceify(err)}); return CompileError.BackendError; } @@ -569,9 +569,9 @@ pub const Codegen = struct { var features = llvm.LLVMGetTargetMachineFeatureString(machine); var triple = llvm.LLVMGetTargetMachineTriple(machine); - std.debug.warn("target: {}\n", sliceify(desc)); - std.debug.warn("triple: {}\n", sliceify(triple)); - std.debug.warn("features: {}\n", sliceify(features)); + std.debug.warn("target: {}\n", .{sliceify(desc)}); + std.debug.warn("triple: {}\n", .{sliceify(triple)}); + std.debug.warn("features: {}\n", .{sliceify(features)}); //if (llvm.LLVMTargetMachineEmitToFile( // machine, @@ -580,7 +580,7 @@ pub const Codegen = struct { // llvm.LLVMCodeGenFileType.LLVMAssemblyFile, // &err, //) != 0) { - // std.debug.warn("failed to emit to assembly file: {}\n", sliceify(err)); + // std.debug.warn("failed to emit to assembly file: {}\n" , .{ sliceify(err) }); // return CompileError.BackendError; //} @@ -591,7 +591,7 @@ pub const Codegen = struct { llvm.LLVMCodeGenFileType.LLVMObjectFile, &err, ) != 0) { - std.debug.warn("failed to emit to file: {}\n", sliceify(err)); + std.debug.warn("failed to emit to file: {}\n", .{sliceify(err)}); return CompileError.BackendError; } } diff --git a/src/comp_ctx.zig b/src/comp_ctx.zig index fdbcaeb..751ef6c 100644 --- a/src/comp_ctx.zig +++ b/src/comp_ctx.zig @@ -158,7 +158,7 @@ pub const VariableMetadata = struct { typ: SymbolUnderlyingType, ) !*VariableMetadata { var meta = try allocator.create(VariableMetadata); - std.debug.warn("VARMETA create from scope={}, meta={}\n", @ptrToInt(scope), @ptrToInt(meta)); + std.debug.warn("VARMETA create from scope={}, meta={}\n" , .{ @ptrToInt(scope), @ptrToInt(meta) }); meta.* = VariableMetadata{ .typ = typ, .from_scope = scope, .using = .Scope }; return meta; } @@ -169,7 +169,7 @@ pub const VariableMetadata = struct { typ: SymbolUnderlyingType, ) !*VariableMetadata { var meta = try allocator.create(VariableMetadata); - std.debug.warn("VARMETA create from fndecl={}, meta={}\n", @ptrToInt(func), @ptrToInt(meta)); + std.debug.warn("VARMETA create from fndecl={}, meta={}\n" , .{ @ptrToInt(func), @ptrToInt(meta) }); meta.* = VariableMetadata{ .typ = typ, .from_function = func, .using = .Function }; return meta; } @@ -204,7 +204,7 @@ pub const CompilationContext = struct { @panic("can't bump scope from null"); } - std.debug.warn("==scope bump== '{}'\n", scope_id); + std.debug.warn("==scope bump== '{}'\n" , .{ scope_id }); var child = try self.current_scope.?.createChild(scope_id); self.current_scope = child; @@ -212,7 +212,7 @@ pub const CompilationContext = struct { /// Set a given scope as the current scope. pub fn setScope(self: *@This(), scope: *Scope) void { - std.debug.warn("==set== set scope to {}\n", scope.id); + std.debug.warn("==set== set scope to {}\n" , .{ scope.id }); self.current_scope = scope; } @@ -349,7 +349,7 @@ pub const CompilationContext = struct { ) !*SymbolData { var sym_kv = self.symbol_table.get(identifier); if (sym_kv == null) { - std.debug.warn("Unknown {} '{}'\n", typ, identifier); + std.debug.warn("Unknown {} '{}'\n" , .{ typ, identifier }); return CompilationError.TypeError; } @@ -357,7 +357,7 @@ pub const CompilationContext = struct { var sym_typ = @as(SymbolType, value.*); if (sym_typ != typ) { - std.debug.warn("Expected {}, got {}\n", sym_typ, typ); + std.debug.warn("Expected {}, got {}\n" , .{ sym_typ, typ }); return CompilationError.TypeError; } @@ -417,7 +417,7 @@ pub const CompilationContext = struct { } } - std.debug.warn("Unknown name {}\n", name); + std.debug.warn("Unknown name {}\n" , .{ name }); return CompilationError.UnknownName; } diff --git a/src/errors.zig b/src/errors.zig index 9043f2e..39528b6 100644 --- a/src/errors.zig +++ b/src/errors.zig @@ -2,9 +2,9 @@ const std = @import("std"); pub fn report(line: usize, where: []const u8, ctx_opt: ?[]const u8, message: []const u8) void { if (ctx_opt) |ctx| { - std.debug.warn("[line {}] Error{} on {}: {}", line, where, ctx, message); + std.debug.warn("[line {}] Error{} on {}: {}" , .{ line, where, ctx, message }); } else { - std.debug.warn("[line {}] Error{}: {}", line, where, message); + std.debug.warn("[line {}] Error{}: {}" , .{ line, where, message }); } } @@ -14,11 +14,11 @@ pub fn reportN(line: usize, message: []const u8) void { pub fn reportFmt(line: usize, ctx_opt: ?[]const u8, comptime fmt: []const u8, args: ...) void { if (ctx_opt) |ctx| { - std.debug.warn("[line {}] Error on {}", line, ctx); + std.debug.warn("[line {}] Error on {}" , .{ line, ctx }); } else { - std.debug.warn("[line {}] Error", line); + std.debug.warn("[line {}] Error" , .{ line }); } std.debug.warn(fmt, args); - std.debug.warn("\n"); + std.debug.warn("\n" , .{ }); } diff --git a/src/main.zig b/src/main.zig index 5e91ab8..3c99ce7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -32,7 +32,7 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { if (tok.typ == .EOF) break; // TODO remove - std.debug.warn("{x}\n", tok); + std.debug.warn("{x}\n" , .{ tok }); } } @@ -47,13 +47,13 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { var root = root_opt.?; - std.debug.warn("parse tree\n"); + std.debug.warn("parse tree\n" , .{ }); printer.printNode(root, 0); var solver = try analysis.Analyzer.init(allocator); var ctx = try solver.pass(root); - std.debug.warn("symbol table\n"); + std.debug.warn("symbol table\n" , .{ }); printer.printContext(ctx); var cgen = codegen.llvm.Codegen.init(allocator, &ctx); @@ -94,7 +94,7 @@ pub fn main() anyerror!void { .ParseError, .CompileError, => { - std.debug.warn("error: {}\n", result); + std.debug.warn("error: {}\n" , .{ result }); std.os.exit(1); }, } diff --git a/src/parsers.zig b/src/parsers.zig index dbf3722..68cf653 100644 --- a/src/parsers.zig +++ b/src/parsers.zig @@ -107,15 +107,15 @@ pub const Parser = struct { fn doError(self: *Parser, comptime fmt: []const u8, args: ...) ParseError { self.hadError = true; - std.debug.warn("parser error at line {}", self.scanner.line); + std.debug.warn("parser error at line {}" , .{ self.scanner.line }); if (self.err_ctx) |ctx| { - std.debug.warn(" on {}", ctx); + std.debug.warn(" on {}" , .{ ctx }); } - std.debug.warn("\n\t"); + std.debug.warn("\n\t" , .{ }); std.debug.warn(fmt, args); - std.debug.warn("\n"); + std.debug.warn("\n" , .{ }); return ParseError.CompileError; } @@ -146,7 +146,7 @@ pub const Parser = struct { } fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError { - std.debug.warn("ctx: '{}'\n", self.err_ctx); + std.debug.warn("ctx: '{}'\n" , .{ self.err_ctx }); if (token.typ == .EOF) { ereport.report(token.line, " at end", self.err_ctx, msg); } else { @@ -177,7 +177,7 @@ pub const Parser = struct { } try self.tokens.append(token); - std.debug.warn("skip to {}\n", token); + std.debug.warn("skip to {}\n" , .{ token }); return token; } From 5ae47fb9620e3f106d3e4e88e7868c3ea4d161cc Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 1 Apr 2020 16:09:52 -0300 Subject: [PATCH 07/10] zig fmt pass --- src/analysis.zig | 20 ++++++++++---------- src/comp_ctx.zig | 14 +++++++------- src/errors.zig | 10 +++++----- src/main.zig | 8 ++++---- src/parsers.zig | 12 ++++++------ 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/analysis.zig b/src/analysis.zig index 4f92c4a..b2e30e5 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -45,18 +45,18 @@ pub const Analyzer = struct { fn doError(self: *@This(), comptime fmt: []const u8, args: ...) void { self.hadError = true; - std.debug.warn("analysis error" , .{ }); + std.debug.warn("analysis error", .{}); if (self.err_tok) |tok| { - std.debug.warn(" at line {}" , .{ tok.line }); + std.debug.warn(" at line {}", .{tok.line}); } if (self.err_ctx) |ctx| { - std.debug.warn(" on {}" , .{ ctx }); + std.debug.warn(" on {}", .{ctx}); } - std.debug.warn("\n\t" , .{ }); + std.debug.warn("\n\t", .{}); std.debug.warn(fmt, args); - std.debug.warn("\n" , .{ }); + std.debug.warn("\n", .{}); } /// Resolve a type in global scope @@ -108,7 +108,7 @@ pub const Analyzer = struct { ) !void { var actual_enum = @as(comp.SymbolUnderlyingTypeEnum, symbol_type); if (actual_enum != wanted_type_enum) { - std.debug.warn("Expected {}, got {}\n" , .{ wanted_type_enum, actual_enum }); + std.debug.warn("Expected {}, got {}\n", .{ wanted_type_enum, actual_enum }); return CompileError.TypeError; } } @@ -122,7 +122,7 @@ pub const Analyzer = struct { .Integer32, .Integer64, .Double => {}, else => { var actual_enum = @as(comp.SymbolUnderlyingTypeEnum, symbol_type); - std.debug.warn("Expected numeric, got {}\n" , .{ actual_enum }); + std.debug.warn("Expected numeric, got {}\n", .{actual_enum}); return CompileError.TypeError; }, } @@ -158,7 +158,7 @@ pub const Analyzer = struct { const expected_enum = @as(comp.SymbolUnderlyingTypeEnum, expected_type); if (symbol_enum != expected_enum) { - std.debug.warn("Expected {}, got {}\n" , .{ expected_enum, symbol_enum }); + std.debug.warn("Expected {}, got {}\n", .{ expected_enum, symbol_enum }); return CompileError.TypeError; } @@ -292,7 +292,7 @@ pub const Analyzer = struct { var target = get.target.*; const target_type = @as(ast.ExprType, target); if (target_type != .Variable) { - std.debug.warn("Expected Variable as get target, got {}\n" , .{ target_type }); + std.debug.warn("Expected Variable as get target, got {}\n", .{target_type}); return CompileError.TypeError; } @@ -475,7 +475,7 @@ pub const Analyzer = struct { self.setErrContext("function {}", name); var ret_type = self.resolveGlobalType(ctx, decl.return_type.lexeme); - std.debug.warn("start analysis of fn {}, ret type: {}\n" , .{ decl.func_name.lexeme, ret_type }); + std.debug.warn("start analysis of fn {}, ret type: {}\n", .{ decl.func_name.lexeme, ret_type }); var parameters = comp.TypeList.init(self.allocator); for (decl.params.toSlice()) |param| { diff --git a/src/comp_ctx.zig b/src/comp_ctx.zig index 751ef6c..6b69664 100644 --- a/src/comp_ctx.zig +++ b/src/comp_ctx.zig @@ -158,7 +158,7 @@ pub const VariableMetadata = struct { typ: SymbolUnderlyingType, ) !*VariableMetadata { var meta = try allocator.create(VariableMetadata); - std.debug.warn("VARMETA create from scope={}, meta={}\n" , .{ @ptrToInt(scope), @ptrToInt(meta) }); + std.debug.warn("VARMETA create from scope={}, meta={}\n", .{ @ptrToInt(scope), @ptrToInt(meta) }); meta.* = VariableMetadata{ .typ = typ, .from_scope = scope, .using = .Scope }; return meta; } @@ -169,7 +169,7 @@ pub const VariableMetadata = struct { typ: SymbolUnderlyingType, ) !*VariableMetadata { var meta = try allocator.create(VariableMetadata); - std.debug.warn("VARMETA create from fndecl={}, meta={}\n" , .{ @ptrToInt(func), @ptrToInt(meta) }); + std.debug.warn("VARMETA create from fndecl={}, meta={}\n", .{ @ptrToInt(func), @ptrToInt(meta) }); meta.* = VariableMetadata{ .typ = typ, .from_function = func, .using = .Function }; return meta; } @@ -204,7 +204,7 @@ pub const CompilationContext = struct { @panic("can't bump scope from null"); } - std.debug.warn("==scope bump== '{}'\n" , .{ scope_id }); + std.debug.warn("==scope bump== '{}'\n", .{scope_id}); var child = try self.current_scope.?.createChild(scope_id); self.current_scope = child; @@ -212,7 +212,7 @@ pub const CompilationContext = struct { /// Set a given scope as the current scope. pub fn setScope(self: *@This(), scope: *Scope) void { - std.debug.warn("==set== set scope to {}\n" , .{ scope.id }); + std.debug.warn("==set== set scope to {}\n", .{scope.id}); self.current_scope = scope; } @@ -349,7 +349,7 @@ pub const CompilationContext = struct { ) !*SymbolData { var sym_kv = self.symbol_table.get(identifier); if (sym_kv == null) { - std.debug.warn("Unknown {} '{}'\n" , .{ typ, identifier }); + std.debug.warn("Unknown {} '{}'\n", .{ typ, identifier }); return CompilationError.TypeError; } @@ -357,7 +357,7 @@ pub const CompilationContext = struct { var sym_typ = @as(SymbolType, value.*); if (sym_typ != typ) { - std.debug.warn("Expected {}, got {}\n" , .{ sym_typ, typ }); + std.debug.warn("Expected {}, got {}\n", .{ sym_typ, typ }); return CompilationError.TypeError; } @@ -417,7 +417,7 @@ pub const CompilationContext = struct { } } - std.debug.warn("Unknown name {}\n" , .{ name }); + std.debug.warn("Unknown name {}\n", .{name}); return CompilationError.UnknownName; } diff --git a/src/errors.zig b/src/errors.zig index 39528b6..d903dd3 100644 --- a/src/errors.zig +++ b/src/errors.zig @@ -2,9 +2,9 @@ const std = @import("std"); pub fn report(line: usize, where: []const u8, ctx_opt: ?[]const u8, message: []const u8) void { if (ctx_opt) |ctx| { - std.debug.warn("[line {}] Error{} on {}: {}" , .{ line, where, ctx, message }); + std.debug.warn("[line {}] Error{} on {}: {}", .{ line, where, ctx, message }); } else { - std.debug.warn("[line {}] Error{}: {}" , .{ line, where, message }); + std.debug.warn("[line {}] Error{}: {}", .{ line, where, message }); } } @@ -14,11 +14,11 @@ pub fn reportN(line: usize, message: []const u8) void { pub fn reportFmt(line: usize, ctx_opt: ?[]const u8, comptime fmt: []const u8, args: ...) void { if (ctx_opt) |ctx| { - std.debug.warn("[line {}] Error on {}" , .{ line, ctx }); + std.debug.warn("[line {}] Error on {}", .{ line, ctx }); } else { - std.debug.warn("[line {}] Error" , .{ line }); + std.debug.warn("[line {}] Error", .{line}); } std.debug.warn(fmt, args); - std.debug.warn("\n" , .{ }); + std.debug.warn("\n", .{}); } diff --git a/src/main.zig b/src/main.zig index 3c99ce7..1dc803a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -32,7 +32,7 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { if (tok.typ == .EOF) break; // TODO remove - std.debug.warn("{x}\n" , .{ tok }); + std.debug.warn("{x}\n", .{tok}); } } @@ -47,13 +47,13 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { var root = root_opt.?; - std.debug.warn("parse tree\n" , .{ }); + std.debug.warn("parse tree\n", .{}); printer.printNode(root, 0); var solver = try analysis.Analyzer.init(allocator); var ctx = try solver.pass(root); - std.debug.warn("symbol table\n" , .{ }); + std.debug.warn("symbol table\n", .{}); printer.printContext(ctx); var cgen = codegen.llvm.Codegen.init(allocator, &ctx); @@ -94,7 +94,7 @@ pub fn main() anyerror!void { .ParseError, .CompileError, => { - std.debug.warn("error: {}\n" , .{ result }); + std.debug.warn("error: {}\n", .{result}); std.os.exit(1); }, } diff --git a/src/parsers.zig b/src/parsers.zig index 68cf653..97c6bd7 100644 --- a/src/parsers.zig +++ b/src/parsers.zig @@ -107,15 +107,15 @@ pub const Parser = struct { fn doError(self: *Parser, comptime fmt: []const u8, args: ...) ParseError { self.hadError = true; - std.debug.warn("parser error at line {}" , .{ self.scanner.line }); + std.debug.warn("parser error at line {}", .{self.scanner.line}); if (self.err_ctx) |ctx| { - std.debug.warn(" on {}" , .{ ctx }); + std.debug.warn(" on {}", .{ctx}); } - std.debug.warn("\n\t" , .{ }); + std.debug.warn("\n\t", .{}); std.debug.warn(fmt, args); - std.debug.warn("\n" , .{ }); + std.debug.warn("\n", .{}); return ParseError.CompileError; } @@ -146,7 +146,7 @@ pub const Parser = struct { } fn tokenError(self: *Parser, token: Token, msg: []const u8) ParseError { - std.debug.warn("ctx: '{}'\n" , .{ self.err_ctx }); + std.debug.warn("ctx: '{}'\n", .{self.err_ctx}); if (token.typ == .EOF) { ereport.report(token.line, " at end", self.err_ctx, msg); } else { @@ -177,7 +177,7 @@ pub const Parser = struct { } try self.tokens.append(token); - std.debug.warn("skip to {}\n" , .{ token }); + std.debug.warn("skip to {}\n", .{token}); return token; } From a623d9b2ca83161f63eaafaf0f3c9e548ca7784f Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 1 Apr 2020 16:10:47 -0300 Subject: [PATCH 08/10] minor fixes on main file --- src/main.zig | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main.zig b/src/main.zig index 1dc803a..297ee9c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -19,11 +19,10 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { // do a full scan pass, then reset, then do it again (with parser) while (true) { var tok_opt = scan.nextToken() catch |err| { - std.debug.warn( - "error at '{}': {}\n", + std.debug.warn("error at '{}': {}\n", .{ scan.currentLexeme(), err, - ); + }); return Result.TokenizeError; }; @@ -76,7 +75,7 @@ pub fn main() anyerror!void { const filepath = try (args_it.next(allocator) orelse @panic("expected file path")); - var file = try std.fs.File.openRead(filepath); + var file = try std.fs.cwd().openFile(filepath, .{}); defer file.close(); const total_bytes = try file.getEndPos(); From 049a388660fc1cec66f073f8094d27bbbefb9d8d Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 1 Apr 2020 21:48:08 -0300 Subject: [PATCH 09/10] more fixes for latest zig --- src/analysis.zig | 28 +++++++++++++------------- src/ast_printer.zig | 38 +++++++++++++++++------------------ src/codegen/llvm.zig | 7 +++---- src/comp_ctx.zig | 5 ++--- src/errors.zig | 2 +- src/main.zig | 2 +- src/parsers.zig | 48 ++++++++++++++++++++++---------------------- 7 files changed, 63 insertions(+), 67 deletions(-) diff --git a/src/analysis.zig b/src/analysis.zig index b2e30e5..9094e38 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -25,7 +25,7 @@ pub const Analyzer = struct { }; } - fn setErrContext(self: *@This(), comptime fmt: ?[]const u8, args: ...) void { + fn setErrContext(self: *@This(), comptime fmt: ?[]const u8, args: var) void { if (fmt == null) { self.err_ctx = null; return; @@ -76,7 +76,7 @@ pub const Analyzer = struct { var sym = ctx.symbol_table.get(val); if (sym == null) { - self.doError("Unknown type: '{}'", val); + self.doError("Unknown type: '{}'", .{val}); return null; } @@ -244,7 +244,7 @@ pub const Analyzer = struct { const name = struc.name.lexeme; var typ = self.resolveGlobalType(ctx, name); if (typ == null) { - self.doError("Unknown struct name '{}'\n", name); + self.doError("Unknown struct name '{}'\n", .{name}); return CompileError.TypeError; } @@ -346,7 +346,7 @@ pub const Analyzer = struct { .Assign => |assign| { if (ctx.current_scope == null) { - self.doError("Can't assign without a scope"); + self.doError("Can't assign without a scope", .{}); return CompileError.Invalid; } @@ -355,7 +355,7 @@ pub const Analyzer = struct { ); if (var_type == null) { - self.doError("Assign target variable not found"); + self.doError("Assign target variable not found", .{}); return CompileError.Invalid; } @@ -393,7 +393,7 @@ pub const Analyzer = struct { var var_type = try self.resolveExprType(ctx, vardecl.value); if (ctx.current_scope == null) { - self.doError("Can't declare without a scope"); + self.doError("Can't declare without a scope", .{}); return CompileError.Invalid; } @@ -462,7 +462,7 @@ pub const Analyzer = struct { node: *ast.Node, ) !void { self.setErrToken(null); - self.setErrContext(null); + self.setErrContext(null, .{}); // always reset the contexts' current function ctx.cur_function = null; @@ -472,7 +472,7 @@ pub const Analyzer = struct { .FnDecl => |decl| { self.setErrToken(decl.return_type); const name = decl.func_name.lexeme; - self.setErrContext("function {}", name); + self.setErrContext("function {}", .{name}); var ret_type = self.resolveGlobalType(ctx, decl.return_type.lexeme); std.debug.warn("start analysis of fn {}, ret type: {}\n", .{ decl.func_name.lexeme, ret_type }); @@ -496,10 +496,10 @@ pub const Analyzer = struct { try ctx.insertFn(decl, ret_type.?, parameters, scope); } else { if (ret_type != null) - self.doError("Return type was not fully resolved"); + self.doError("Return type was not fully resolved", .{}); if (parameters.len != decl.params.len) - self.doError("Fully analyzed {} parameters, wanted {}", parameters.len, decl.params.len); + self.doError("Fully analyzed {} parameters, wanted {}", .{ parameters.len, decl.params.len }); return CompileError.TypeError; } @@ -520,7 +520,7 @@ pub const Analyzer = struct { .Struct => |struc| { self.setErrToken(struc.name); - self.setErrContext("struct {}", struc.name.lexeme); + self.setErrContext("struct {}", .{struc.name.lexeme}); var types = comp.TypeList.init(self.allocator); @@ -543,7 +543,7 @@ pub const Analyzer = struct { // TODO change enums to u32 .Enum => |enu| { self.setErrToken(enu.name); - self.setErrContext("enum {}", enu.name.lexeme); + self.setErrContext("enum {}", .{enu.name.lexeme}); try ctx.insertEnum(enu); }, @@ -551,7 +551,7 @@ pub const Analyzer = struct { .ConstDecl => |constlist| { for (constlist.toSlice()) |constdecl| { self.setErrToken(constdecl.name); - self.setErrContext("const {}", constdecl.name.lexeme); + self.setErrContext("const {}", .{constdecl.name.lexeme}); var expr_type = try self.resolveExprType(ctx, constdecl.expr); try ctx.insertConst(constdecl, expr_type); @@ -559,7 +559,7 @@ pub const Analyzer = struct { }, .Block => { - self.doError("Block can't be found at root"); + self.doError("Block can't be found at root", .{}); return CompileError.Invalid; }, } diff --git a/src/ast_printer.zig b/src/ast_printer.zig index 1bdc248..42f1d4d 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -14,7 +14,7 @@ fn printIdent(ident: usize) void { } } -fn print(ident: usize, comptime fmt: []const u8, args: ...) void { +fn print(ident: usize, comptime fmt: []const u8, args: var) void { printIdent(ident); std.debug.warn(fmt, args); } @@ -29,9 +29,9 @@ fn printBlock(ident: usize, block: var, endNewline: bool) void { } if (endNewline) { - print(ident - 1, ")\n"); + print(ident - 1, ")\n", .{}); } else { - print(ident - 1, ")"); + print(ident - 1, ")", .{}); } } @@ -63,7 +63,7 @@ pub fn printNode(node: *const Node, ident: usize) void { }, .ConstDecl => |consts| { - print(ident, "(const (\n"); + print(ident, "(const (\n", .{}); for (consts.toSlice()) |const_decl| { print( @@ -76,11 +76,11 @@ pub fn printNode(node: *const Node, ident: usize) void { std.debug.warn(")\n", .{}); } - print(ident, "))\n"); + print(ident, "))\n", .{}); }, .Enum => |decl| { - print(ident, "(enum {} (\n", decl.name.lexeme); + print(ident, "(enum {} (\n", .{decl.name.lexeme}); for (decl.fields.toSlice()) |field| { print( @@ -90,7 +90,7 @@ pub fn printNode(node: *const Node, ident: usize) void { ); } - print(ident, "))\n"); + print(ident, "))\n", .{}); }, .Root => { @@ -100,15 +100,15 @@ pub fn printNode(node: *const Node, ident: usize) void { }, .Struct => |struc| { - print(ident, "(struct {} (\n", struc.name.lexeme); + print(ident, "(struct {} (\n", .{struc.name.lexeme}); for (struc.fields.toSlice()) |field| { - print(ident + 1, "({} {})\n", field.name.lexeme, field.typ.lexeme); + print(ident + 1, "({} {})\n", .{ field.name.lexeme, field.typ.lexeme }); } - print(ident, "))\n"); + print(ident, "))\n", .{}); }, else => { - print(ident, "unknown node: {}\n", node); + print(ident, "unknown node: {}\n", .{node}); }, } } @@ -330,7 +330,7 @@ pub fn printStmt(ident: usize, stmt: *const Stmt) void { // very bad but be like that fn retWithName(prefix: []const u8, inner: []const u8) []const u8 { var ret_nam_buf = std.heap.direct_allocator.alloc(u8, 256) catch unreachable; - return std.fmt.bufPrint(ret_nam_buf[0..], "{}({})", prefix, inner) catch unreachable; + return std.fmt.bufPrint(ret_nam_buf[0..], "{}({})", .{ prefix, inner }) catch unreachable; } fn prettyType(typ: SymbolUnderlyingType) []const u8 { @@ -347,11 +347,11 @@ fn prettyType(typ: SymbolUnderlyingType) []const u8 { } pub fn printScope(scope: *Scope, ident: usize) void { - print(ident, "scope '{}' at addr {}\n", scope.id, @ptrToInt(scope)); + print(ident, "scope '{}' at addr {}\n", .{ scope.id, @ptrToInt(scope) }); var it = scope.env.iterator(); while (it.next()) |kv| { - print(ident + 1, "sym: {}, typ: {}\n", kv.key, prettyType(kv.value)); + print(ident + 1, "sym: {}, typ: {}\n", .{ kv.key, prettyType(kv.value) }); } for (scope.children.toSlice()) |child| { @@ -365,19 +365,17 @@ pub fn printContext(ctx: CompilationContext) void { while (it.next()) |kv| { switch (kv.value.*) { .Function => |fn_sym| { - std.debug.warn( - "function {} returns {}\n", + std.debug.warn("function {} returns {}\n", .{ kv.key, prettyType(fn_sym.return_type), - ); + }); for (fn_sym.decl.params.toSlice()) |param| { var param_kv = fn_sym.parameters.get(param.name.lexeme).?; - std.debug.warn( - "\tparameter {} typ {}\n", + std.debug.warn("\tparameter {} typ {}\n", .{ param_kv.key, prettyType(param_kv.value.typ), - ); + }); } // go through scopes diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 010dc1c..6aa092e 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5,7 +5,7 @@ const comp = @import("../comp_ctx.zig"); const CompileError = @import("../codegen.zig").CompileError; fn sliceify(non_slice: ?[*:0]const u8) []const u8 { - return non_slice.?[0..std.mem.len(u8, non_slice.?)]; + return non_slice.?[0..std.mem.len(non_slice.?)]; } fn mkLLVMBool(val: bool) llvm.LLVMValueRef { @@ -71,11 +71,10 @@ pub const Codegen = struct { .Enum => |map| { var val = map.get(get.name.lexeme); if (val == null) { - std.debug.warn( - "enum {} does not have field {}\n", + std.debug.warn("enum {} does not have field {}\n", .{ vari.lexeme, get.name.lexeme, - ); + }); } return llvm.LLVMConstInt(llvm.LLVMInt32Type(), val.?.value, 1); }, diff --git a/src/comp_ctx.zig b/src/comp_ctx.zig index 6b69664..44f377b 100644 --- a/src/comp_ctx.zig +++ b/src/comp_ctx.zig @@ -224,11 +224,10 @@ pub const CompilationContext = struct { const parent_id: ?[]const u8 = if (self.current_scope.?.parent == null) null else self.current_scope.?.parent.?.id; - std.debug.warn( - "==scope dump== {} to {}\n", + std.debug.warn("==scope dump== {} to {}\n", .{ self.current_scope.?.id, parent_id, - ); + }); self.current_scope = self.current_scope.?.parent; } diff --git a/src/errors.zig b/src/errors.zig index d903dd3..88c05f1 100644 --- a/src/errors.zig +++ b/src/errors.zig @@ -12,7 +12,7 @@ pub fn reportN(line: usize, message: []const u8) void { report(line, "", message); } -pub fn reportFmt(line: usize, ctx_opt: ?[]const u8, comptime fmt: []const u8, args: ...) void { +pub fn reportFmt(line: usize, ctx_opt: ?[]const u8, comptime fmt: []const u8, args: var) void { if (ctx_opt) |ctx| { std.debug.warn("[line {}] Error on {}", .{ line, ctx }); } else { diff --git a/src/main.zig b/src/main.zig index 297ee9c..ba5d105 100644 --- a/src/main.zig +++ b/src/main.zig @@ -69,7 +69,7 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result { } pub fn main() anyerror!void { - const allocator = std.heap.direct_allocator; + const allocator = std.heap.page_allocator; var args_it = std.process.args(); _ = args_it.skip(); diff --git a/src/parsers.zig b/src/parsers.zig index 97c6bd7..391b48e 100644 --- a/src/parsers.zig +++ b/src/parsers.zig @@ -94,7 +94,7 @@ pub const Parser = struct { self.tokens.deinit(); } - fn setErrContext(self: *Parser, comptime fmt: ?[]const u8, args: ...) void { + fn setErrContext(self: *Parser, comptime fmt: ?[]const u8, args: var) void { if (fmt == null) { self.err_ctx = null; return; @@ -104,7 +104,7 @@ pub const Parser = struct { self.err_ctx = std.fmt.bufPrint(buf, fmt.?, args) catch unreachable; } - fn doError(self: *Parser, comptime fmt: []const u8, args: ...) ParseError { + fn doError(self: *Parser, comptime fmt: []const u8, args: var) ParseError { self.hadError = true; std.debug.warn("parser error at line {}", .{self.scanner.line}); @@ -150,7 +150,10 @@ pub const Parser = struct { if (token.typ == .EOF) { ereport.report(token.line, " at end", self.err_ctx, msg); } else { - ereport.reportFmt(token.line, self.err_ctx, " at '{}': {}", token.lexeme, msg); + ereport.reportFmt(token.line, self.err_ctx, " at '{}': {}", .{ + token.lexeme, + msg, + }); } return ParseError.CompileError; @@ -203,12 +206,10 @@ pub const Parser = struct { // TODO maybe this could be entirely comptime? var buf_main: [1000]u8 = undefined; - var buf = try std.fmt.bufPrint( - buf_main[0..], - "expected {}, got {}", + var buf = try std.fmt.bufPrint(&buf_main, "expected {}, got {}", .{ ttype, self.peek().typ, - ); + }); return self.tokenError(self.peek(), buf); } @@ -466,7 +467,7 @@ pub const Parser = struct { break :blk orig_name; }; - self.setErrContext("function {}", name.lexeme); + self.setErrContext("function {}", .{name.lexeme}); _ = try self.consumeSingle(.LeftParen); @@ -529,14 +530,14 @@ pub const Parser = struct { var consts = ast.ConstList.init(self.allocator); errdefer consts.deinit(); - self.setErrContext("const"); + self.setErrContext("const", .{}); _ = try self.consumeSingle(.Const); _ = try self.consumeSingle(.LeftParen); while (self.peek().typ != .RightParen) { const const_name = try self.consumeSingle(.Identifier); - self.setErrContext("const {}", const_name); + self.setErrContext("const {}", .{const_name}); _ = try self.consumeSingle(.Equal); @@ -558,18 +559,18 @@ pub const Parser = struct { fn parseStructDecl(self: *@This()) !*Node { var fields = ast.FieldList.init(self.allocator); errdefer fields.deinit(); - self.setErrContext("struct"); + self.setErrContext("struct", .{}); _ = try self.consumeSingle(.Struct); var name = try self.consumeSingle(.Identifier); - self.setErrContext("struct {}", name); + self.setErrContext("struct {}", .{name}); _ = try self.consumeSingle(.LeftBrace); while (!self.check(.RightBrace)) { const field_name = try self.consumeSingle(.Identifier); - self.setErrContext("struct {} field {}", name, field_name); + self.setErrContext("struct {} field {}", .{ name, field_name }); const field_type = try self.consumeSingle(.Identifier); try fields.append(ast.StructField{ @@ -587,12 +588,12 @@ pub const Parser = struct { var fields = ast.TokenList.init(self.allocator); errdefer fields.deinit(); - self.setErrContext("enum"); + self.setErrContext("enum", .{}); _ = try self.consumeSingle(.Enum); const name = try self.consumeSingle(.Identifier); - self.setErrContext("enum {}", name); + self.setErrContext("enum {}", .{name}); _ = try self.consumeSingle(.LeftBrace); @@ -606,7 +607,7 @@ pub const Parser = struct { } fn parseTopDecl(self: *@This()) !*Node { - self.setErrContext(null); + self.setErrContext(null, .{}); return switch (self.peek().typ) { .Fn => try self.parseFnDecl(), @@ -615,7 +616,7 @@ pub const Parser = struct { .Enum => try self.parseEnumDecl(), else => |typ| blk: { - return self.doError("expected Fn, Const, Struct, got {}\n", typ); + return self.doError("expected Fn, Const, Struct, got {}\n", .{typ}); }, }; } @@ -837,7 +838,7 @@ pub const Parser = struct { switch (op_tok.typ) { // TODO remove .ColonEqual from language .ColonEqual => { - return self.doError("can not initialize struct field"); + return self.doError("can not initialize struct field", .{}); }, .Equal => return try self.mkSet(get.target, get.name, value), @@ -855,7 +856,7 @@ pub const Parser = struct { }, else => |expr_typ| { - return self.doError("Invalid assignment target {}", expr_typ); + return self.doError("Invalid assignment target {}", .{expr_typ}); }, } } @@ -1028,7 +1029,7 @@ pub const Parser = struct { // for this to work properly, must be Variable, since its a type. const expr_type = @as(ast.ExprType, expr.*); if (expr_type != .Variable) { - return self.doError("Expected variable for struct type, got {}", expr_type); + return self.doError("Expected variable for struct type, got {}", .{expr_type}); } var inits = ast.StructInitList.init(self.allocator); @@ -1065,11 +1066,10 @@ pub const Parser = struct { // parseInt(i64) on the catch block of parseInt(i32) var i32_num_opt: ?i32 = std.fmt.parseInt(i32, lexeme, 10) catch null; var i64_num: i64 = std.fmt.parseInt(i64, lexeme, 10) catch |err| { - return self.doError( - "Invalid integer (not 32bit or 64bit) '{}': {}", + return self.doError("Invalid integer (not 32bit or 64bit) '{}': {}", .{ lexeme, err, - ); + }); }; if (i32_num_opt) |i32_num| { @@ -1124,7 +1124,7 @@ pub const Parser = struct { }, else => blk: { - return self.doError("expected literal, got {}", curtype); + return self.doError("expected literal, got {}", .{curtype}); }, }; From 74e6beda671b6006848f6c967ae437715416e9b7 Mon Sep 17 00:00:00 2001 From: Luna Date: Wed, 1 Apr 2020 21:58:30 -0300 Subject: [PATCH 10/10] more fixes for latest zig --- src/analysis.zig | 32 +++++++++++++++----------------- src/ast_printer.zig | 26 ++++++++++---------------- src/codegen/llvm.zig | 4 ++-- 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/src/analysis.zig b/src/analysis.zig index 9094e38..bc35d32 100644 --- a/src/analysis.zig +++ b/src/analysis.zig @@ -42,7 +42,7 @@ pub const Analyzer = struct { self.err_tok = tok; } - fn doError(self: *@This(), comptime fmt: []const u8, args: ...) void { + fn doError(self: *@This(), comptime fmt: []const u8, args: var) void { self.hadError = true; std.debug.warn("analysis error", .{}); @@ -85,11 +85,10 @@ pub const Analyzer = struct { .Enum => SymbolUnderlyingType{ .Enum = val }, else => blk: { - self.doError( - "expected struct or enum for '{}', got {}", + self.doError("expected struct or enum for '{}', got {}", .{ val, @tagName(@as(comp.SymbolType, sym.?.value.*)), - ); + }); break :blk null; }, }; @@ -136,12 +135,11 @@ pub const Analyzer = struct { expected_ident: []const u8, ) !void { if (!std.mem.eql(u8, sym_ident, expected_ident)) { - self.doError( - "Expected {} {}, got {}", + self.doError("Expected {} {}, got {}", .{ @tagName(typ_enum), expected_ident, sym_ident, - ); + }); return CompileError.TypeError; } @@ -267,12 +265,11 @@ pub const Analyzer = struct { const param_type_val = @as(comp.SymbolUnderlyingTypeEnum, param_type); const arg_type_val = @as(comp.SymbolUnderlyingTypeEnum, arg_type); - self.doError( - "Expected parameter {} to be {}, got {}", + self.doError("Expected parameter {} to be {}, got {}", .{ idx, @tagName(param_type_val), @tagName(arg_type_val), - ); + }); return CompileError.TypeError; }; @@ -322,11 +319,10 @@ pub const Analyzer = struct { var kv = map.get(name); if (kv == null) { - self.doError( - "Field {} not found in enum {}", + self.doError("Field {} not found in enum {}", .{ name, lexeme, - ); + }); return CompileError.TypeError; } @@ -334,10 +330,9 @@ pub const Analyzer = struct { }, else => { - self.doError( - "Expected Struct/Enum as get target, got {}", + self.doError("Expected Struct/Enum as get target, got {}", .{ @as(comp.SymbolUnderlyingTypeEnum, global_typ), - ); + }); return CompileError.TypeError; }, @@ -475,7 +470,10 @@ pub const Analyzer = struct { self.setErrContext("function {}", .{name}); var ret_type = self.resolveGlobalType(ctx, decl.return_type.lexeme); - std.debug.warn("start analysis of fn {}, ret type: {}\n", .{ decl.func_name.lexeme, ret_type }); + std.debug.warn("start analysis of fn {}, ret type: {}\n", .{ + decl.func_name.lexeme, + ret_type, + }); var parameters = comp.TypeList.init(self.allocator); for (decl.params.toSlice()) |param| { diff --git a/src/ast_printer.zig b/src/ast_printer.zig index 42f1d4d..328f880 100644 --- a/src/ast_printer.zig +++ b/src/ast_printer.zig @@ -66,11 +66,9 @@ pub fn printNode(node: *const Node, ident: usize) void { print(ident, "(const (\n", .{}); for (consts.toSlice()) |const_decl| { - print( - ident + 1, - "({} ", + print(ident + 1, "({} ", .{ const_decl.name.lexeme, - ); + }); printExpr(const_decl.expr); std.debug.warn(")\n", .{}); @@ -83,11 +81,9 @@ pub fn printNode(node: *const Node, ident: usize) void { print(ident, "(enum {} (\n", .{decl.name.lexeme}); for (decl.fields.toSlice()) |field| { - print( - ident + 1, - "{}\n", + print(ident + 1, "{}\n", .{ field.lexeme, - ); + }); } print(ident, "))\n", .{}); @@ -249,7 +245,7 @@ pub fn printExpr(expr: *const Expr) void { .Get => |get| { warn("(", .{}); printExpr(get.target); - warn(".{})", get.name.lexeme); + warn(".{})", .{get.name.lexeme}); }, .Set => |set| { @@ -329,7 +325,7 @@ pub fn printStmt(ident: usize, stmt: *const Stmt) void { // very bad but be like that fn retWithName(prefix: []const u8, inner: []const u8) []const u8 { - var ret_nam_buf = std.heap.direct_allocator.alloc(u8, 256) catch unreachable; + var ret_nam_buf = std.heap.page_allocator.alloc(u8, 256) catch unreachable; return std.fmt.bufPrint(ret_nam_buf[0..], "{}({})", .{ prefix, inner }) catch unreachable; } @@ -387,19 +383,17 @@ pub fn printContext(ctx: CompilationContext) void { std.debug.warn("struct '{}'\n", .{kv.key}); var map_it = typemap.iterator(); while (map_it.next()) |map_kv| { - std.debug.warn( - "\tfield {} type {}\n", + std.debug.warn("\tfield {} type {}\n", .{ map_kv.key, prettyType(map_kv.value), - ); + }); } }, - .Variable => std.debug.warn( - "variable {} type {}\n", + .Variable => std.debug.warn("variable {} type {}\n", .{ kv.key, kv.value, - ), + }), .Enum => |identmap| { std.debug.warn("enum {}:", .{kv.key}); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 6aa092e..ff2d6f6 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -230,7 +230,7 @@ pub const Codegen = struct { var buf = try self.allocator.alloc(u8, 512); errdefer self.allocator.free(buf); - var load_str = try std.fmt.bufPrint(buf, "{}_loaded", vari.lexeme); + var load_str = try std.fmt.bufPrint(buf, "{}_loaded", .{vari.lexeme}); var load_cstr = try std.cstr.addNullByte(self.allocator, load_str); errdefer self.allocator.free(load_cstr); @@ -435,7 +435,7 @@ pub const Codegen = struct { _ = try self.llvm_table.put(name, func); var buf = try self.allocator.alloc(u8, 512); - var entry_lbl = try std.fmt.bufPrint(buf, "fn_{}_entry", name); + var entry_lbl = try std.fmt.bufPrint(buf, "fn_{}_entry", .{name}); var entry_lbl_cstr = try std.cstr.addNullByte(self.allocator, entry_lbl); var entry = llvm.LLVMAppendBasicBlock(func, entry_lbl_cstr.ptr);