add emitting of integer and float literals

- remove panics
 - add emitting for return statements
 - remove default emitting of return a+b;
This commit is contained in:
Luna 2019-09-23 22:07:19 -03:00
parent 4c1bdb5f91
commit 013aafa8a4
2 changed files with 53 additions and 27 deletions

View file

@ -1,7 +1,7 @@
// import std; // import std;
fn add(a: i32, b: i32) i32 { fn add() i32 {
return a + b; return 1 + 1;
} }
// type is void by default // type is void by default

View file

@ -7,7 +7,10 @@ fn sliceify(non_slice: ?[*]const u8) []const u8 {
return non_slice.?[0..std.mem.len(u8, non_slice.?)]; 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 { pub const Codegen = struct {
allocator: *std.mem.Allocator, allocator: *std.mem.Allocator,
@ -16,7 +19,7 @@ pub const Codegen = struct {
return Codegen{ .allocator = allocator }; 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 // TODO if expr is Variable, we should do a variable lookup
// in a symbol table, going up in scope, etc. // in a symbol table, going up in scope, etc.
@ -24,32 +27,58 @@ pub const Codegen = struct {
// TODO Assign modify symbol table // TODO Assign modify symbol table
// TODO Calls fetch symbol table, check arity of it at codegen level // 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 // 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| { .Binary => |binary| {
var left = try self.genExpr(builder, binary.left); var left = try self.emitExpr(builder, binary.left);
var right = try self.genExpr(builder, binary.right); var right = try self.emitExpr(builder, binary.right);
return switch (binary.op.lexeme[0]) { return switch (binary.op.lexeme[0]) {
// TODO other operators // TODO other operators
'+' => llvm.LLVMBuildAdd(builder, left, right, c"addtmp"), '+' => llvm.LLVMBuildAdd(builder, left, right, c"addtmp"),
// TODO codegen errors // 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 // 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.*) { switch (stmt.*) {
.Expr => |expr| try self.genExpr(builder, expr), .Expr => |expr| _ = try self.emitExpr(builder, expr),
else => unreachable, .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| { for (decl.body.toSlice()) |stmt| {
// TODO custom function context for us // TODO custom function context for us
try self.genFuncStmt(builder, stmt); try self.emitStmt(builder, &stmt);
} }
// TODO codegen decl.body //var tmp = llvm.LLVMBuildAdd(
var tmp = llvm.LLVMBuildAdd( // builder,
builder, // llvm.LLVMGetParam(func, 0),
llvm.LLVMGetParam(func, 0), // llvm.LLVMGetParam(func, 1),
llvm.LLVMGetParam(func, 1), // c"tmp",
c"tmp", //);
);
_ = llvm.LLVMBuildRet(builder, tmp); //_ = llvm.LLVMBuildRet(builder, tmp);
std.debug.warn("cgen: fn decl done\n"); std.debug.warn("cgen: fn decl done\n");
}, },
else => { else => {
@ -156,11 +184,9 @@ pub const Codegen = struct {
var data_layout = llvm.LLVMCopyStringRepOfTargetData(target_data); var data_layout = llvm.LLVMCopyStringRepOfTargetData(target_data);
llvm.LLVMSetDataLayout(mod, data_layout); 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.o");
var outpath_cstr = try std.cstr.addNullByte(self.allocator, outpath);
//var asmpath = try std.mem.dupe(self.allocator, u8, "output.S"); //var asmpath_cstr = try std.cstr.addNullByte(self.allocator, "output.S");
//var asmpath_cstr = try std.cstr.addNullByte(self.allocator, asmpath);
var desc = llvm.LLVMGetTargetDescription(target); var desc = llvm.LLVMGetTargetDescription(target);
var features = llvm.LLVMGetTargetMachineFeatureString(machine); var features = llvm.LLVMGetTargetMachineFeatureString(machine);