diff --git a/examples/hello.ry b/examples/hello.ry index 5c23845..debd7e6 100644 --- a/examples/hello.ry +++ b/examples/hello.ry @@ -1,7 +1,7 @@ // import std; -fn add(a: i32, b: i32) i32 { - return a + b; +fn add() i32 { + return 1 + 1; } // type is void by default diff --git a/src/codegen.zig b/src/codegen.zig index 5ca193b..583a699 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -7,7 +7,10 @@ fn sliceify(non_slice: ?[*]const u8) []const u8 { return non_slice.?[0..std.mem.len(u8, non_slice.?)]; } -pub const CompileError = error{LLVMError}; +pub const CompileError = error{ + LLVMError, + EmitError, +}; pub const Codegen = struct { allocator: *std.mem.Allocator, @@ -16,7 +19,7 @@ pub const Codegen = struct { return Codegen{ .allocator = allocator }; } - fn genExpr(self: *Codegen, builder: var, expr: *const ast.Expr) !llvm.LLVMValueRef { + fn emitExpr(self: *Codegen, builder: var, expr: *const ast.Expr) anyerror!llvm.LLVMValueRef { // TODO if expr is Variable, we should do a variable lookup // in a symbol table, going up in scope, etc. @@ -24,32 +27,58 @@ pub const Codegen = struct { // TODO Assign modify symbol table // TODO Calls fetch symbol table, check arity of it at codegen level - switch (expr.*) { + return switch (expr.*) { // TODO handle all literals, construct llvm values for them - .Literal => |literal| {}, + .Literal => |literal| blk: { + break :blk switch (literal) { + // TODO other literals + .Integer => |val| blk2: { + var val_cstr = try std.cstr.addNullByte(self.allocator, val); + break :blk2 llvm.LLVMConstIntOfString(llvm.LLVMInt32Type(), val_cstr.ptr, 10); + }, + .Float => |val| blk2: { + var val_cstr = try std.cstr.addNullByte(self.allocator, val); + break :blk2 llvm.LLVMConstRealOfString(llvm.LLVMDoubleType(), val_cstr.ptr); + }, + else => unreachable, + }; + }, .Binary => |binary| { - var left = try self.genExpr(builder, binary.left); - var right = try self.genExpr(builder, binary.right); + var left = try self.emitExpr(builder, binary.left); + var right = try self.emitExpr(builder, binary.right); return switch (binary.op.lexeme[0]) { // TODO other operators '+' => llvm.LLVMBuildAdd(builder, left, right, c"addtmp"), // TODO codegen errors - else => @panic("invalid binary operator"), + else => { + std.debug.warn("Unexpected binary operator: '{}'\n", binary.op.lexeme); + return CompileError.EmitError; + }, }; }, // TODO codegen errors - else => @panic("invalid expr"), - } + else => { + std.debug.warn("Got unexpected expr {}\n", expr.*); + return CompileError.EmitError; + }, + }; } - fn genFuncStmt(self: *Codegen, builder: var, stmt: *const ast.Stmt) !void { + fn emitStmt(self: *Codegen, builder: var, stmt: *const ast.Stmt) !void { switch (stmt.*) { - .Expr => |expr| try self.genExpr(builder, expr), - else => unreachable, + .Expr => |expr| _ = try self.emitExpr(builder, expr), + .Return => |ret| { + var ret_expr = try self.emitExpr(builder, ret.value); + _ = llvm.LLVMBuildRet(builder, ret_expr); + }, + else => { + std.debug.warn("Got unexpected statement {}\n", stmt.*); + return CompileError.EmitError; + }, } } @@ -89,18 +118,17 @@ pub const Codegen = struct { for (decl.body.toSlice()) |stmt| { // TODO custom function context for us - try self.genFuncStmt(builder, stmt); + try self.emitStmt(builder, &stmt); } - // TODO codegen decl.body - var tmp = llvm.LLVMBuildAdd( - builder, - llvm.LLVMGetParam(func, 0), - llvm.LLVMGetParam(func, 1), - c"tmp", - ); + //var tmp = llvm.LLVMBuildAdd( + // builder, + // llvm.LLVMGetParam(func, 0), + // llvm.LLVMGetParam(func, 1), + // c"tmp", + //); - _ = llvm.LLVMBuildRet(builder, tmp); + //_ = llvm.LLVMBuildRet(builder, tmp); std.debug.warn("cgen: fn decl done\n"); }, else => { @@ -156,11 +184,9 @@ pub const Codegen = struct { var data_layout = llvm.LLVMCopyStringRepOfTargetData(target_data); llvm.LLVMSetDataLayout(mod, data_layout); - var outpath = try std.mem.dupe(self.allocator, u8, "output.o"); - var outpath_cstr = try std.cstr.addNullByte(self.allocator, outpath); + var outpath_cstr = try std.cstr.addNullByte(self.allocator, "outpath.o"); - //var asmpath = try std.mem.dupe(self.allocator, u8, "output.S"); - //var asmpath_cstr = try std.cstr.addNullByte(self.allocator, asmpath); + //var asmpath_cstr = try std.cstr.addNullByte(self.allocator, "output.S"); var desc = llvm.LLVMGetTargetDescription(target); var features = llvm.LLVMGetTargetMachineFeatureString(machine);