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;
fn add(a: i32, b: i32) i32 {
return a + b;
fn add() i32 {
return 1 + 1;
}
// 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.?)];
}
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);