aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-02-01 23:52:22 +0000
committergingerBill <bill@gingerbill.org>2020-02-01 23:52:22 +0000
commit5f1b397a055be3cc58789281abdb7a390e2b18d5 (patch)
tree20d477e3f4e5311b937901d0950f0397589dfa3e /src/llvm_backend.cpp
parent6ed6a91a6434a944010d8f2c6752e70a372b5296 (diff)
Use `lbValue` to represent values everywhere
Diffstat (limited to 'src/llvm_backend.cpp')
-rw-r--r--src/llvm_backend.cpp285
1 files changed, 198 insertions, 87 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index b2ab67442..eb66db696 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -4,11 +4,19 @@
#include "llvm-c/Analysis.h"
#include "llvm-c/Object.h"
#include "llvm-c/BitWriter.h"
+#include "llvm-c/Transforms/AggressiveInstCombine.h"
+#include "llvm-c/Transforms/InstCombine.h"
+#include "llvm-c/Transforms/IPO.h"
+
+struct lbValue {
+ LLVMValueRef value;
+ Type *type;
+};
struct lbModule {
LLVMModuleRef mod;
- Map<LLVMValueRef> values; // Key: Entity *
+ Map<lbValue> values; // Key: Entity *
};
struct lbGenerator {
@@ -28,12 +36,14 @@ enum lbAddrKind {
lbAddr_SoaVariable,
};
+
+
struct lbAddr {
lbAddrKind kind;
- LLVMValueRef addr;
+ lbValue addr;
union {
struct {
- LLVMValueRef key;
+ lbValue key;
Type *type;
Type *result;
} map;
@@ -44,7 +54,7 @@ struct lbAddr {
Selection sel;
} ctx;
struct {
- LLVMValueRef index;
+ lbValue index;
Ast *index_expr;
} soa;
};
@@ -76,36 +86,41 @@ struct lbProcedure {
LLVMValueRef value;
LLVMBuilderRef builder;
- LLVMValueRef return_ptr;
- Array<LLVMValueRef> params;
- Array<lbBlock *> blocks;
- Scope * curr_scope;
- i32 scope_index;
- lbBlock * decl_block;
- lbBlock * entry_block;
- lbBlock * curr_block;
+ lbValue return_ptr;
+ Array<lbValue> params;
+ Array<lbBlock *> blocks;
+ Scope * curr_scope;
+ i32 scope_index;
+ lbBlock * decl_block;
+ lbBlock * entry_block;
+ lbBlock * curr_block;
};
lbBlock * lb_create_block(lbProcedure *p, char const *name);
LLVMTypeRef lb_type(Type *type);
void lb_build_stmt (lbProcedure *p, Ast *stmt);
-LLVMValueRef lb_build_expr (lbProcedure *p, Ast *expr);
+lbValue lb_build_expr (lbProcedure *p, Ast *expr);
+lbValue lb_constant_nil(Type *type);
+
-lbAddr lb_addr(LLVMValueRef addr) {
+lbAddr lb_addr(lbValue addr) {
lbAddr v = {lbAddr_Default, addr};
return v;
}
-LLVMTypeRef lb_addr_type(lbAddr const &addr) {
- return LLVMGetElementType(LLVMTypeOf(addr.addr));
+Type *lb_addr_type(lbAddr const &addr) {
+ return type_deref(addr.addr.type);
+}
+LLVMTypeRef lb_addr_lb_type(lbAddr const &addr) {
+ return LLVMGetElementType(LLVMTypeOf(addr.addr.value));
}
-void lb_addr_store(lbProcedure *p, lbAddr const &addr, LLVMValueRef value) {
- if (addr.addr == nullptr) {
+void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue const &value) {
+ if (addr.addr.value == nullptr) {
return;
}
- GB_ASSERT(value != nullptr);
- LLVMBuildStore(p->builder, value, addr.addr);
+ GB_ASSERT(value.value != nullptr);
+ LLVMBuildStore(p->builder, value.value, addr.addr.value);
}
LLVMTypeRef lb_type_internal(Type *type) {
@@ -380,11 +395,15 @@ lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e=nullptr) {
LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block);
+ lbValue val = {};
+ val.value = ptr;
+ val.type = alloc_type_pointer(type);
+
if (e != nullptr) {
- map_set(&p->module->values, hash_entity(e), ptr);
+ map_set(&p->module->values, hash_entity(e), val);
}
- return lb_addr(ptr);
+ return lb_addr(val);
}
@@ -482,7 +501,7 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
auto addrs = array_make<lbAddr>(heap_allocator(), vd->names.count);
- auto values = array_make<LLVMValueRef>(heap_allocator(), 0, vd->names.count);
+ auto values = array_make<lbValue>(heap_allocator(), 0, vd->names.count);
defer (array_free(&addrs));
defer (array_free(&values));
@@ -492,13 +511,13 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
Entity *e = entity_of_ident(name);
addrs[i] = lb_add_local(p, e->type, e);
if (vd->values.count == 0) {
- lb_addr_store(p, addrs[i], LLVMConstNull(lb_addr_type(addrs[i])));
+ lb_addr_store(p, addrs[i], lb_constant_nil(lb_addr_type(addrs[i])));
}
}
}
for_array(i, vd->values) {
- LLVMValueRef value = lb_build_expr(p, vd->values[i]);
+ lbValue value = lb_build_expr(p, vd->values[i]);
array_add(&values, value);
}
@@ -510,28 +529,78 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
}
}
-LLVMValueRef lb_value_constant(Type *type, ExactValue const &value) {
+lbValue lb_constant_nil(Type *type) {
+ LLVMValueRef v = LLVMConstNull(lb_type(type));
+ return lbValue{v, type};
+}
+
+LLVMValueRef llvm_const_f32(f32 f, Type *type=t_f32) {
+ u32 u = bit_cast<u32>(f);
+ LLVMValueRef i = LLVMConstInt(LLVMInt32Type(), u, false);
+ return LLVMConstBitCast(i, lb_type(type));
+}
+
+lbValue lb_constant_value(Type *type, ExactValue const &value) {
switch (value.kind) {
case ExactValue_Invalid:
- return LLVMConstNull(lb_type(type));
+ return lbValue{LLVMConstNull(lb_type(type)), type};
case ExactValue_Bool:
- return LLVMConstInt(lb_type(type), value.value_bool, false);
+ return lbValue{LLVMConstInt(lb_type(type), value.value_bool, false), type};
case ExactValue_String:
- return LLVMConstInt(lb_type(type), value.value_bool, false);
+ return lbValue{LLVMConstInt(lb_type(type), value.value_bool, false), type};
case ExactValue_Integer:
- return LLVMConstIntOfArbitraryPrecision(lb_type(type), cast(unsigned)value.value_integer.len, big_int_ptr(&value.value_integer));
+ return lbValue{LLVMConstIntOfArbitraryPrecision(lb_type(type), cast(unsigned)value.value_integer.len, big_int_ptr(&value.value_integer)), type};
case ExactValue_Float:
- return LLVMConstReal(lb_type(type), value.value_float);
+ if (type_size_of(type) == 4) {
+ f32 f = cast(f32)value.value_float;
+ return lbValue{llvm_const_f32(f, type), type};
+ }
+ return lbValue{LLVMConstReal(lb_type(type), value.value_float), type};
case ExactValue_Complex:
- GB_PANIC("ExactValue_Complex");
+ {
+ LLVMValueRef values[2] = {};
+ switch (8*type_size_of(type)) {
+ case 64:
+ values[0] = llvm_const_f32(cast(f32)value.value_complex.real);
+ values[1] = llvm_const_f32(cast(f32)value.value_complex.imag);
+ break;
+ case 128:
+ values[0] = LLVMConstReal(lb_type(t_f64), value.value_complex.real);
+ values[1] = LLVMConstReal(lb_type(t_f64), value.value_complex.imag);
+ break;
+ }
+
+ return lbValue{LLVMConstStruct(values, 2, false)};
+ }
break;
case ExactValue_Quaternion:
- GB_PANIC("ExactValue_Quaternion");
+ {
+ LLVMValueRef values[4] = {};
+ switch (8*type_size_of(type)) {
+ case 128:
+ // @QuaternionLayout
+ values[3] = llvm_const_f32(cast(f32)value.value_quaternion.real);
+ values[0] = llvm_const_f32(cast(f32)value.value_quaternion.imag);
+ values[1] = llvm_const_f32(cast(f32)value.value_quaternion.jmag);
+ values[2] = llvm_const_f32(cast(f32)value.value_quaternion.kmag);
+ break;
+ case 256:
+ // @QuaternionLayout
+ values[3] = LLVMConstReal(lb_type(t_f64), value.value_quaternion.real);
+ values[0] = LLVMConstReal(lb_type(t_f64), value.value_quaternion.imag);
+ values[1] = LLVMConstReal(lb_type(t_f64), value.value_quaternion.jmag);
+ values[2] = LLVMConstReal(lb_type(t_f64), value.value_quaternion.kmag);
+ break;
+ }
+
+ return lbValue{LLVMConstStruct(values, 4, false)};
+ }
break;
case ExactValue_Pointer:
- return LLVMConstBitCast(LLVMConstInt(lb_type(t_uintptr), value.value_pointer, false), lb_type(type));
+ return lbValue{LLVMConstBitCast(LLVMConstInt(lb_type(t_uintptr), value.value_pointer, false), lb_type(type)), type};
+
case ExactValue_Compound:
GB_PANIC("ExactValue_Compound");
break;
@@ -544,50 +613,88 @@ LLVMValueRef lb_value_constant(Type *type, ExactValue const &value) {
}
GB_PANIC("UNKNOWN ExactValue kind");
- return nullptr;
+ return lbValue{nullptr, type};
}
-LLVMValueRef lb_add_module_constant(lbModule *m, Type *type, ExactValue const &value) {
+lbValue lb_add_module_constant(lbModule *m, Type *type, ExactValue const &value) {
gbAllocator a = heap_allocator();
if (is_type_slice(type)) {
GB_PANIC("lb_add_module_constant -> slice");
}
- return lb_value_constant(type, value);
+ return lb_constant_value(type, value);
}
-LLVMValueRef lb_emit_arith(lbProcedure *p, TokenKind op, LLVMValueRef lhs, LLVMValueRef rhs, Type *type) {
+lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type) {
switch (op) {
case Token_Add:
- return LLVMBuildAdd(p->builder, lhs, rhs, "");
+ if (is_type_float(type)) {
+ return lbValue{LLVMBuildFAdd(p->builder, lhs.value, rhs.value, ""), type};
+ }
+ return lbValue{LLVMBuildAdd(p->builder, lhs.value, rhs.value, ""), type};
case Token_Sub:
- return LLVMBuildSub(p->builder, lhs, rhs, "");
+ if (is_type_float(type)) {
+ return lbValue{LLVMBuildFSub(p->builder, lhs.value, rhs.value, ""), type};
+ }
+ return lbValue{LLVMBuildSub(p->builder, lhs.value, rhs.value, ""), type};
case Token_Mul:
- return LLVMBuildMul(p->builder, lhs, rhs, "");
+ if (is_type_float(type)) {
+ return lbValue{LLVMBuildFMul(p->builder, lhs.value, rhs.value, ""), type};
+ }
+ return lbValue{LLVMBuildMul(p->builder, lhs.value, rhs.value, ""), type};
case Token_Quo:
+ if (is_type_float(type)) {
+ return lbValue{LLVMBuildFDiv(p->builder, lhs.value, rhs.value, ""), type};
+ } else if (is_type_unsigned(type)) {
+ return lbValue{LLVMBuildUDiv(p->builder, lhs.value, rhs.value, ""), type};
+ }
+ return lbValue{LLVMBuildSDiv(p->builder, lhs.value, rhs.value, ""), type};
case Token_Mod:
+ if (is_type_float(type)) {
+ return lbValue{LLVMBuildFRem(p->builder, lhs.value, rhs.value, ""), type};
+ } else if (is_type_unsigned(type)) {
+ return lbValue{LLVMBuildURem(p->builder, lhs.value, rhs.value, ""), type};
+ }
+ return lbValue{LLVMBuildSRem(p->builder, lhs.value, rhs.value, ""), type};
case Token_ModMod:
+ if (is_type_unsigned(type)) {
+ return lbValue{LLVMBuildURem(p->builder, lhs.value, rhs.value, ""), type};
+ } else {
+ LLVMValueRef a = LLVMBuildSRem(p->builder, lhs.value, rhs.value, "");
+ LLVMValueRef b = LLVMBuildAdd(p->builder, a, rhs.value, "");
+ LLVMValueRef c = LLVMBuildSRem(p->builder, b, rhs.value, "");
+ return lbValue{c, type};
+ }
+
case Token_And:
- return LLVMBuildAdd(p->builder, lhs, rhs, "");
+ return lbValue{LLVMBuildAnd(p->builder, lhs.value, rhs.value, ""), type};
case Token_Or:
- return LLVMBuildOr(p->builder, lhs, rhs, "");
+ return lbValue{LLVMBuildOr(p->builder, lhs.value, rhs.value, ""), type};
case Token_Xor:
- return LLVMBuildXor(p->builder, lhs, rhs, "");
+ return lbValue{LLVMBuildXor(p->builder, lhs.value, rhs.value, ""), type};
case Token_Shl:
- return LLVMBuildShl(p->builder, lhs, rhs, "");
+ return lbValue{LLVMBuildShl(p->builder, lhs.value, rhs.value, ""), type};
case Token_Shr:
-
+ if (is_type_unsigned(type)) {
+ return lbValue{LLVMBuildLShr(p->builder, lhs.value, rhs.value, ""), type};
+ }
+ return lbValue{LLVMBuildAShr(p->builder, lhs.value, rhs.value, ""), type};
case Token_AndNot:
+ {
+ LLVMValueRef all_ones = LLVMConstAllOnes(lb_type(type));
+ LLVMValueRef new_rhs = LLVMBuildXor(p->builder, all_ones, rhs.value, "");
+ return lbValue{LLVMBuildAnd(p->builder, lhs.value, new_rhs, ""), type};
+ }
break;
}
GB_PANIC("unhandled operator of lb_emit_arith");
- return nullptr;
+ return {};
}
-LLVMValueRef lb_build_binary_expr(lbProcedure *p, Ast *expr) {
+lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
ast_node(be, BinaryExpr, expr);
TypeAndValue tv = type_and_value_of_expr(expr);
@@ -606,18 +713,18 @@ LLVMValueRef lb_build_binary_expr(lbProcedure *p, Ast *expr) {
case Token_Shl:
case Token_Shr: {
Type *type = default_type(tv.type);
- LLVMValueRef left = lb_build_expr(p, be->left);
- LLVMValueRef right = lb_build_expr(p, be->right);
+ lbValue left = lb_build_expr(p, be->left);
+ lbValue right = lb_build_expr(p, be->right);
return lb_emit_arith(p, be->op.kind, left, right, type);
}
default:
GB_PANIC("Invalid binary expression");
break;
}
- return nullptr;
+ return {};
}
-LLVMValueRef lb_build_expr(lbProcedure *p, Ast *expr) {
+lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
expr = unparen_expr(expr);
TypeAndValue tv = type_and_value_of_expr(expr);
@@ -659,7 +766,7 @@ LLVMValueRef lb_build_expr(lbProcedure *p, Ast *expr) {
// case_end;
case_ast_node(u, Undef, expr);
- return LLVMGetUndef(lb_type(tv.type));
+ return lbValue{LLVMGetUndef(lb_type(tv.type)), tv.type};
case_end;
case_ast_node(i, Ident, expr);
@@ -670,24 +777,24 @@ LLVMValueRef lb_build_expr(lbProcedure *p, Ast *expr) {
GB_PANIC("TODO(bill): ir_build_expr Entity_Builtin '%.*s'\n"
"\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name),
LIT(token.pos.file), token.pos.line, token.pos.column);
- return nullptr;
+ return {};
} else if (e->kind == Entity_Nil) {
- return LLVMConstNull(lb_type(tv.type));
+ return lb_constant_nil(tv.type);
}
auto *found = map_get(&p->module->values, hash_entity(e));
if (found) {
- LLVMValueRef v = *found;
- LLVMTypeKind kind = LLVMGetTypeKind(LLVMTypeOf(v));
+ auto v = *found;
+ LLVMTypeKind kind = LLVMGetTypeKind(LLVMTypeOf(v.value));
if (kind == LLVMFunctionTypeKind) {
return v;
}
- return LLVMBuildLoad2(p->builder, LLVMGetElementType(LLVMTypeOf(v)), v, "");
+ return lbValue{LLVMBuildLoad2(p->builder, lb_type(type_deref(v.type)), v.value, ""), e->type};
// } else if (e != nullptr && e->kind == Entity_Variable) {
// return ir_addr_load(proc, ir_build_addr(proc, expr));
}
GB_PANIC("nullptr value for expression from identifier: %.*s : %s @ %p", LIT(i->token.string), type_to_string(e->type), expr);
- return nullptr;
+ return {};
case_end;
case_ast_node(be, BinaryExpr, expr);
@@ -695,7 +802,7 @@ LLVMValueRef lb_build_expr(lbProcedure *p, Ast *expr) {
case_end;
}
- return nullptr;
+ return {};
}
@@ -718,8 +825,8 @@ void lb_generate_module(lbGenerator *gen) {
for_array(i, info->entities) {
- arena_free_all(&temp_arena);
- gbAllocator a = temp_allocator;
+ // arena_free_all(&temp_arena);
+ // gbAllocator a = temp_allocator;
Entity *e = info->entities[i];
String name = e->token.string;
@@ -767,6 +874,7 @@ void lb_generate_module(lbGenerator *gen) {
lb_build_stmt(p, p->body);
LLVMBuildRet(p->builder, nullptr);
+ // LLVMBuildRetVoid(p->builder);
}
lb_end_procedure(p);
@@ -794,38 +902,41 @@ void lb_generate_module(lbGenerator *gen) {
char *llvm_error = nullptr;
defer (LLVMDisposeMessage(llvm_error));
- LLVMVerifyModule(mod, LLVMAbortProcessAction, &llvm_error);
- llvm_error = nullptr;
- LLVMDumpModule(mod);
+ // LLVMPassManagerRef pass_manager = LLVMCreatePassManager();
+ // defer (LLVMDisposePassManager(pass_manager));
+
+ // LLVMAddAggressiveInstCombinerPass(pass_manager);
+ // LLVMAddConstantMergePass(pass_manager);
+ // LLVMAddDeadArgEliminationPass(pass_manager);
+ // LLVMRunPassManager(pass_manager, mod);
- LLVMPassManagerRef pass_manager = LLVMCreatePassManager();
- defer (LLVMDisposePassManager(pass_manager));
+ LLVMVerifyModule(mod, LLVMAbortProcessAction, &llvm_error);
+ llvm_error = nullptr;
- LLVMRunPassManager(pass_manager, mod);
- LLVMFinalizeFunctionPassManager(pass_manager);
+ LLVMDumpModule(mod);
- LLVMInitializeAllTargetInfos();
- LLVMInitializeAllTargets();
- LLVMInitializeAllTargetMCs();
- LLVMInitializeAllAsmParsers();
- LLVMInitializeAllAsmPrinters();
+ // LLVMInitializeAllTargetInfos();
+ // LLVMInitializeAllTargets();
+ // LLVMInitializeAllTargetMCs();
+ // LLVMInitializeAllAsmParsers();
+ // LLVMInitializeAllAsmPrinters();
- char const *target_triple = "x86_64-pc-windows-msvc";
- char const *target_data_layout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128";
- LLVMSetTarget(mod, target_triple);
+ // char const *target_triple = "x86_64-pc-windows-msvc";
+ // char const *target_data_layout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128";
+ // LLVMSetTarget(mod, target_triple);
- LLVMTargetRef target = {};
- LLVMGetTargetFromTriple(target_triple, &target, &llvm_error);
- GB_ASSERT(target != nullptr);
+ // LLVMTargetRef target = {};
+ // LLVMGetTargetFromTriple(target_triple, &target, &llvm_error);
+ // GB_ASSERT(target != nullptr);
- LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(target, target_triple, "generic", "", LLVMCodeGenLevelNone, LLVMRelocDefault, LLVMCodeModelDefault);
- defer (LLVMDisposeTargetMachine(target_machine));
+ // LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(target, target_triple, "generic", "", LLVMCodeGenLevelNone, LLVMRelocDefault, LLVMCodeModelDefault);
+ // defer (LLVMDisposeTargetMachine(target_machine));
- LLVMBool ok = LLVMTargetMachineEmitToFile(target_machine, mod, "llvm_demo.obj", LLVMObjectFile, &llvm_error);
- if (ok) {
- gb_printf_err("LLVM Error: %s\n", llvm_error);
- return;
- }
+ // LLVMBool ok = LLVMTargetMachineEmitToFile(target_machine, mod, "llvm_demo.obj", LLVMObjectFile, &llvm_error);
+ // if (ok) {
+ // gb_printf_err("LLVM Error: %s\n", llvm_error);
+ // return;
+ // }
}