Compare commits

...

3 commits

2 changed files with 69 additions and 14 deletions

View file

@ -7,6 +7,8 @@ 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 Codegen = struct { pub const Codegen = struct {
allocator: *std.mem.Allocator, allocator: *std.mem.Allocator,
@ -14,6 +16,43 @@ pub const Codegen = struct {
return Codegen{ .allocator = allocator }; return Codegen{ .allocator = allocator };
} }
fn genExpr(self: *Codegen, builder: var, expr: *const ast.Expr) !llvm.LLVMValueRef {
// TODO if expr is Variable, we should do a variable lookup
// in a symbol table, going up in scope, etc.
// TODO VarDecl add things to the symbol table
// TODO Assign modify symbol table
// TODO Calls fetch symbol table, check arity of it at codegen level
switch (expr.*) {
// TODO handle all literals, construct llvm values for them
.Literal => |literal| {},
.Binary => |binary| {
var left = try self.genExpr(builder, binary.left);
var right = try self.genExpr(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"),
};
},
// TODO codegen errors
else => @panic("invalid expr"),
}
}
fn genFuncStmt(self: *Codegen, builder: var, stmt: *const ast.Stmt) !void {
switch (stmt.*) {
.Expr => |expr| try self.genExpr(builder, expr),
else => unreachable,
}
}
fn genNode( fn genNode(
self: *Codegen, self: *Codegen,
mod: llvm.LLVMModuleRef, mod: llvm.LLVMModuleRef,
@ -48,6 +87,11 @@ pub const Codegen = struct {
var builder = llvm.LLVMCreateBuilder(); var builder = llvm.LLVMCreateBuilder();
llvm.LLVMPositionBuilderAtEnd(builder, entry); llvm.LLVMPositionBuilderAtEnd(builder, entry);
for (decl.body.toSlice()) |stmt| {
// TODO custom function context for us
try self.genFuncStmt(builder, stmt);
}
// TODO codegen decl.body // TODO codegen decl.body
var tmp = llvm.LLVMBuildAdd( var tmp = llvm.LLVMBuildAdd(
builder, builder,
@ -89,23 +133,19 @@ pub const Codegen = struct {
if (llvm.LLVMWriteBitcodeToFile(mod, c"awoo.bc") != 0) { if (llvm.LLVMWriteBitcodeToFile(mod, c"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.LLVMError;
// TODO return error value
@panic("compile error");
} }
//llvm.InitializeAllTargetInfos(); llvm.LLVMInitializeAllTargetInfos();
//llvm.InitializeAllTargets(); llvm.LLVMInitializeAllTargets();
//llvm.InitializeAllTargetMCs(); llvm.LLVMInitializeAllTargetMCs();
//llvm.InitializeAllAsmParsers(); llvm.LLVMInitializeAllAsmParsers();
//llvm.InitializeAllAsmPrinters(); llvm.LLVMInitializeAllAsmPrinters();
var engine: llvm.LLVMExecutionEngineRef = undefined; var engine: llvm.LLVMExecutionEngineRef = undefined;
if (llvm.LLVMCreateExecutionEngineForModule(&engine, mod, &err) != 0) { 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.LLVMError;
// TODO return error value
@panic("compile error");
} }
var machine = llvm.LLVMGetExecutionEngineTargetMachine(engine); var machine = llvm.LLVMGetExecutionEngineTargetMachine(engine);
@ -119,6 +159,9 @@ pub const Codegen = struct {
var outpath = try std.mem.dupe(self.allocator, u8, "output.o"); 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);
//var asmpath = try std.mem.dupe(self.allocator, u8, "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);
var triple = llvm.LLVMGetTargetMachineTriple(machine); var triple = llvm.LLVMGetTargetMachineTriple(machine);
@ -127,6 +170,17 @@ pub const Codegen = struct {
std.debug.warn("triple: {}\n", sliceify(triple)); std.debug.warn("triple: {}\n", sliceify(triple));
std.debug.warn("features: {}\n", sliceify(features)); 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( if (llvm.LLVMTargetMachineEmitToFile(
machine, machine,
mod, mod,
@ -135,9 +189,7 @@ pub const Codegen = struct {
&err, &err,
) != 0) { ) != 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.LLVMError;
// TODO return error value
@panic("compile error");
} }
} }
}; };

View file

@ -46,6 +46,9 @@ pub fn run(allocator: *std.mem.Allocator, slice: []const u8) !Result {
std.debug.warn("parse tree\n"); std.debug.warn("parse tree\n");
printer.printNode(root.?, 0); printer.printNode(root.?, 0);
// TODO type pass
// TODO variable pass
var cgen = codegen.Codegen.init(allocator); var cgen = codegen.Codegen.init(allocator);
try cgen.gen(root.?); try cgen.gen(root.?);