Use lbValue to represent values everywhere

This commit is contained in:
gingerBill
2020-02-01 23:52:22 +00:00
parent 6ed6a91a64
commit 5f1b397a05
2 changed files with 207 additions and 91 deletions
+202 -91
View File
@@ -4,11 +4,19 @@
#include "llvm-c/Analysis.h" #include "llvm-c/Analysis.h"
#include "llvm-c/Object.h" #include "llvm-c/Object.h"
#include "llvm-c/BitWriter.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 { struct lbModule {
LLVMModuleRef mod; LLVMModuleRef mod;
Map<LLVMValueRef> values; // Key: Entity * Map<lbValue> values; // Key: Entity *
}; };
struct lbGenerator { struct lbGenerator {
@@ -28,12 +36,14 @@ enum lbAddrKind {
lbAddr_SoaVariable, lbAddr_SoaVariable,
}; };
struct lbAddr { struct lbAddr {
lbAddrKind kind; lbAddrKind kind;
LLVMValueRef addr; lbValue addr;
union { union {
struct { struct {
LLVMValueRef key; lbValue key;
Type *type; Type *type;
Type *result; Type *result;
} map; } map;
@@ -44,7 +54,7 @@ struct lbAddr {
Selection sel; Selection sel;
} ctx; } ctx;
struct { struct {
LLVMValueRef index; lbValue index;
Ast *index_expr; Ast *index_expr;
} soa; } soa;
}; };
@@ -76,36 +86,41 @@ struct lbProcedure {
LLVMValueRef value; LLVMValueRef value;
LLVMBuilderRef builder; LLVMBuilderRef builder;
LLVMValueRef return_ptr; lbValue return_ptr;
Array<LLVMValueRef> params; Array<lbValue> params;
Array<lbBlock *> blocks; Array<lbBlock *> blocks;
Scope * curr_scope; Scope * curr_scope;
i32 scope_index; i32 scope_index;
lbBlock * decl_block; lbBlock * decl_block;
lbBlock * entry_block; lbBlock * entry_block;
lbBlock * curr_block; lbBlock * curr_block;
}; };
lbBlock * lb_create_block(lbProcedure *p, char const *name); lbBlock * lb_create_block(lbProcedure *p, char const *name);
LLVMTypeRef lb_type(Type *type); LLVMTypeRef lb_type(Type *type);
void lb_build_stmt (lbProcedure *p, Ast *stmt); 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}; lbAddr v = {lbAddr_Default, addr};
return v; return v;
} }
LLVMTypeRef lb_addr_type(lbAddr const &addr) { Type *lb_addr_type(lbAddr const &addr) {
return LLVMGetElementType(LLVMTypeOf(addr.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) { void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue const &value) {
if (addr.addr == nullptr) { if (addr.addr.value == nullptr) {
return; return;
} }
GB_ASSERT(value != nullptr); GB_ASSERT(value.value != nullptr);
LLVMBuildStore(p->builder, value, addr.addr); LLVMBuildStore(p->builder, value.value, addr.addr.value);
} }
LLVMTypeRef lb_type_internal(Type *type) { 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); LLVMPositionBuilderAtEnd(p->builder, p->curr_block->block);
lbValue val = {};
val.value = ptr;
val.type = alloc_type_pointer(type);
if (e != nullptr) { 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 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(&addrs));
defer (array_free(&values)); defer (array_free(&values));
@@ -492,13 +511,13 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
Entity *e = entity_of_ident(name); Entity *e = entity_of_ident(name);
addrs[i] = lb_add_local(p, e->type, e); addrs[i] = lb_add_local(p, e->type, e);
if (vd->values.count == 0) { 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) { 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); 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) { switch (value.kind) {
case ExactValue_Invalid: case ExactValue_Invalid:
return LLVMConstNull(lb_type(type)); return lbValue{LLVMConstNull(lb_type(type)), type};
case ExactValue_Bool: 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: 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: 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: 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: 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; break;
case ExactValue_Quaternion: 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; break;
case ExactValue_Pointer: 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: case ExactValue_Compound:
GB_PANIC("ExactValue_Compound"); GB_PANIC("ExactValue_Compound");
break; break;
@@ -544,50 +613,88 @@ LLVMValueRef lb_value_constant(Type *type, ExactValue const &value) {
} }
GB_PANIC("UNKNOWN ExactValue kind"); 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(); gbAllocator a = heap_allocator();
if (is_type_slice(type)) { if (is_type_slice(type)) {
GB_PANIC("lb_add_module_constant -> slice"); 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) { switch (op) {
case Token_Add: 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: 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: 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: 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: 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: case Token_ModMod:
case Token_And: if (is_type_unsigned(type)) {
return LLVMBuildAdd(p->builder, lhs, rhs, ""); return lbValue{LLVMBuildURem(p->builder, lhs.value, rhs.value, ""), type};
case Token_Or: } else {
return LLVMBuildOr(p->builder, lhs, rhs, ""); LLVMValueRef a = LLVMBuildSRem(p->builder, lhs.value, rhs.value, "");
case Token_Xor: LLVMValueRef b = LLVMBuildAdd(p->builder, a, rhs.value, "");
return LLVMBuildXor(p->builder, lhs, rhs, ""); LLVMValueRef c = LLVMBuildSRem(p->builder, b, rhs.value, "");
case Token_Shl: return lbValue{c, type};
return LLVMBuildShl(p->builder, lhs, rhs, ""); }
case Token_Shr:
case Token_And:
return lbValue{LLVMBuildAnd(p->builder, lhs.value, rhs.value, ""), type};
case Token_Or:
return lbValue{LLVMBuildOr(p->builder, lhs.value, rhs.value, ""), type};
case Token_Xor:
return lbValue{LLVMBuildXor(p->builder, lhs.value, rhs.value, ""), type};
case Token_Shl:
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: 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; break;
} }
GB_PANIC("unhandled operator of lb_emit_arith"); 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); ast_node(be, BinaryExpr, expr);
TypeAndValue tv = type_and_value_of_expr(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_Shl:
case Token_Shr: { case Token_Shr: {
Type *type = default_type(tv.type); Type *type = default_type(tv.type);
LLVMValueRef left = lb_build_expr(p, be->left); lbValue left = lb_build_expr(p, be->left);
LLVMValueRef right = lb_build_expr(p, be->right); lbValue right = lb_build_expr(p, be->right);
return lb_emit_arith(p, be->op.kind, left, right, type); return lb_emit_arith(p, be->op.kind, left, right, type);
} }
default: default:
GB_PANIC("Invalid binary expression"); GB_PANIC("Invalid binary expression");
break; break;
} }
return nullptr; return {};
} }
LLVMValueRef lb_build_expr(lbProcedure *p, Ast *expr) { lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
expr = unparen_expr(expr); expr = unparen_expr(expr);
TypeAndValue tv = type_and_value_of_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_end;
case_ast_node(u, Undef, expr); case_ast_node(u, Undef, expr);
return LLVMGetUndef(lb_type(tv.type)); return lbValue{LLVMGetUndef(lb_type(tv.type)), tv.type};
case_end; case_end;
case_ast_node(i, Ident, expr); 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" GB_PANIC("TODO(bill): ir_build_expr Entity_Builtin '%.*s'\n"
"\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name), "\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name),
LIT(token.pos.file), token.pos.line, token.pos.column); LIT(token.pos.file), token.pos.line, token.pos.column);
return nullptr; return {};
} else if (e->kind == Entity_Nil) { } 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)); auto *found = map_get(&p->module->values, hash_entity(e));
if (found) { if (found) {
LLVMValueRef v = *found; auto v = *found;
LLVMTypeKind kind = LLVMGetTypeKind(LLVMTypeOf(v)); LLVMTypeKind kind = LLVMGetTypeKind(LLVMTypeOf(v.value));
if (kind == LLVMFunctionTypeKind) { if (kind == LLVMFunctionTypeKind) {
return v; 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) { // } else if (e != nullptr && e->kind == Entity_Variable) {
// return ir_addr_load(proc, ir_build_addr(proc, expr)); // 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); 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_end;
case_ast_node(be, BinaryExpr, expr); case_ast_node(be, BinaryExpr, expr);
@@ -695,7 +802,7 @@ LLVMValueRef lb_build_expr(lbProcedure *p, Ast *expr) {
case_end; case_end;
} }
return nullptr; return {};
} }
@@ -718,8 +825,8 @@ void lb_generate_module(lbGenerator *gen) {
for_array(i, info->entities) { for_array(i, info->entities) {
arena_free_all(&temp_arena); // arena_free_all(&temp_arena);
gbAllocator a = temp_allocator; // gbAllocator a = temp_allocator;
Entity *e = info->entities[i]; Entity *e = info->entities[i];
String name = e->token.string; String name = e->token.string;
@@ -767,6 +874,7 @@ void lb_generate_module(lbGenerator *gen) {
lb_build_stmt(p, p->body); lb_build_stmt(p, p->body);
LLVMBuildRet(p->builder, nullptr); LLVMBuildRet(p->builder, nullptr);
// LLVMBuildRetVoid(p->builder);
} }
lb_end_procedure(p); lb_end_procedure(p);
@@ -794,38 +902,41 @@ void lb_generate_module(lbGenerator *gen) {
char *llvm_error = nullptr; char *llvm_error = nullptr;
defer (LLVMDisposeMessage(llvm_error)); defer (LLVMDisposeMessage(llvm_error));
// LLVMPassManagerRef pass_manager = LLVMCreatePassManager();
// defer (LLVMDisposePassManager(pass_manager));
// LLVMAddAggressiveInstCombinerPass(pass_manager);
// LLVMAddConstantMergePass(pass_manager);
// LLVMAddDeadArgEliminationPass(pass_manager);
// LLVMRunPassManager(pass_manager, mod);
LLVMVerifyModule(mod, LLVMAbortProcessAction, &llvm_error); LLVMVerifyModule(mod, LLVMAbortProcessAction, &llvm_error);
llvm_error = nullptr; llvm_error = nullptr;
LLVMDumpModule(mod); LLVMDumpModule(mod);
// LLVMInitializeAllTargetInfos();
// LLVMInitializeAllTargets();
// LLVMInitializeAllTargetMCs();
// LLVMInitializeAllAsmParsers();
// LLVMInitializeAllAsmPrinters();
LLVMPassManagerRef pass_manager = LLVMCreatePassManager(); // char const *target_triple = "x86_64-pc-windows-msvc";
defer (LLVMDisposePassManager(pass_manager)); // char const *target_data_layout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128";
// LLVMSetTarget(mod, target_triple);
LLVMRunPassManager(pass_manager, mod); // LLVMTargetRef target = {};
LLVMFinalizeFunctionPassManager(pass_manager); // LLVMGetTargetFromTriple(target_triple, &target, &llvm_error);
// GB_ASSERT(target != nullptr);
LLVMInitializeAllTargetInfos(); // LLVMTargetMachineRef target_machine = LLVMCreateTargetMachine(target, target_triple, "generic", "", LLVMCodeGenLevelNone, LLVMRelocDefault, LLVMCodeModelDefault);
LLVMInitializeAllTargets(); // defer (LLVMDisposeTargetMachine(target_machine));
LLVMInitializeAllTargetMCs();
LLVMInitializeAllAsmParsers();
LLVMInitializeAllAsmPrinters();
char const *target_triple = "x86_64-pc-windows-msvc"; // LLVMBool ok = LLVMTargetMachineEmitToFile(target_machine, mod, "llvm_demo.obj", LLVMObjectFile, &llvm_error);
char const *target_data_layout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"; // if (ok) {
LLVMSetTarget(mod, target_triple); // gb_printf_err("LLVM Error: %s\n", llvm_error);
// return;
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));
LLVMBool ok = LLVMTargetMachineEmitToFile(target_machine, mod, "llvm_demo.obj", LLVMObjectFile, &llvm_error);
if (ok) {
gb_printf_err("LLVM Error: %s\n", llvm_error);
return;
}
} }
+5
View File
@@ -1275,11 +1275,16 @@ int main(int arg_count, char const **arg_ptr) {
} }
if (build_context.use_llvm_api) { if (build_context.use_llvm_api) {
timings_start_section(timings, str_lit("LLVM API Code Gen"));
lbGenerator gen = {}; lbGenerator gen = {};
if (!lb_init_generator(&gen, &checker)) { if (!lb_init_generator(&gen, &checker)) {
return 1; return 1;
} }
lb_generate_module(&gen); lb_generate_module(&gen);
if (build_context.show_timings) {
show_timings(&checker, timings);
}
return 0; return 0;
} }