diff options
| author | gingerBill <bill@gingerbill.org> | 2020-05-15 17:37:00 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2020-05-15 17:37:00 +0100 |
| commit | ff92eb911271fd9ad3b7c4261897fcf20899918c (patch) | |
| tree | 29f98d87c03b1a32cb96875e916959b3009e8f66 /src/llvm_backend.cpp | |
| parent | 8b066b24563a7b2644c1128d267d90f16c7b5a73 (diff) | |
Relative pointers
Diffstat (limited to 'src/llvm_backend.cpp')
| -rw-r--r-- | src/llvm_backend.cpp | 173 |
1 files changed, 152 insertions, 21 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 06209a35e..48ae4705b 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -56,6 +56,10 @@ LLVMValueRef llvm_cstring(lbModule *m, String const &str) { lbAddr lb_addr(lbValue addr) { lbAddr v = {lbAddr_Default, addr}; + if (is_type_relative_pointer(type_deref(addr.type))) { + GB_ASSERT(is_type_pointer(addr.type)); + v.kind = lbAddr_RelativePointer; + } return v; } @@ -160,7 +164,29 @@ void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue value) { value.value = LLVMConstNull(lb_type(p->module, t)); } - if (addr.kind == lbAddr_AtomOp_index_set) { + if (addr.kind == lbAddr_RelativePointer) { + Type *rel_ptr = base_type(lb_addr_type(addr)); + GB_ASSERT(rel_ptr->kind == Type_RelativePointer); + + value = lb_emit_conv(p, value, rel_ptr->RelativePointer.pointer_type); + + GB_ASSERT(is_type_pointer(addr.addr.type)); + lbValue ptr = lb_emit_conv(p, addr.addr, t_uintptr); + lbValue val_ptr = lb_emit_conv(p, value, t_uintptr); + lbValue offset = {}; + offset.value = LLVMBuildSub(p->builder, val_ptr.value, ptr.value, ""); + offset.type = t_uintptr; + + if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) { + offset = lb_emit_conv(p, offset, t_i64); + } + offset = lb_emit_conv(p, offset, rel_ptr->RelativePointer.base_integer); + + lbValue offset_ptr = lb_emit_conv(p, addr.addr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + LLVMBuildStore(p->builder, offset.value, offset_ptr.value); + return; + + } else if (addr.kind == lbAddr_AtomOp_index_set) { lbValue ptr = addr.addr; lbValue index = addr.index_set.index; Ast *node = addr.index_set.node; @@ -341,7 +367,34 @@ lbValue lb_emit_load(lbProcedure *p, lbValue value) { lbValue lb_addr_load(lbProcedure *p, lbAddr const &addr) { GB_ASSERT(addr.addr.value != nullptr); - if (addr.kind == lbAddr_Map) { + + if (addr.kind == lbAddr_RelativePointer) { + Type *rel_ptr = base_type(lb_addr_type(addr)); + GB_ASSERT(rel_ptr->kind == Type_RelativePointer); + + lbValue ptr = lb_emit_conv(p, addr.addr, t_uintptr); + lbValue offset = lb_emit_conv(p, ptr, alloc_type_pointer(rel_ptr->RelativePointer.base_integer)); + offset = lb_emit_load(p, offset); + + + if (!is_type_unsigned(rel_ptr->RelativePointer.base_integer)) { + offset = lb_emit_conv(p, offset, t_i64); + } + offset = lb_emit_conv(p, offset, t_uintptr); + lbValue absolute_ptr = lb_emit_arith(p, Token_Add, ptr, offset, t_uintptr); + absolute_ptr = lb_emit_conv(p, absolute_ptr, rel_ptr->RelativePointer.pointer_type); + + lbValue cond = lb_emit_comp(p, Token_CmpEq, offset, lb_const_nil(p->module, rel_ptr->RelativePointer.base_integer)); + + // NOTE(bill): nil check + lbValue nil_ptr = lb_const_nil(p->module, rel_ptr->RelativePointer.pointer_type); + lbValue final_ptr = {}; + final_ptr.type = absolute_ptr.type; + final_ptr.value = LLVMBuildSelect(p->builder, cond.value, nil_ptr.value, absolute_ptr.value, ""); + + return lb_emit_load(p, final_ptr); + + } else if (addr.kind == lbAddr_Map) { Type *map_type = base_type(addr.map.type); lbAddr v = lb_add_local_generated(p, map_type->Map.lookup_result_type, true); lbValue h = lb_gen_map_header(p, addr.addr, map_type); @@ -1181,6 +1234,20 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return LLVMX86MMXTypeInContext(ctx); } return LLVMVectorType(lb_type(m, type->SimdVector.elem), cast(unsigned)type->SimdVector.count); + + case Type_RelativePointer: + return lb_type_internal(m, type->RelativePointer.base_integer); + + case Type_RelativeSlice: + { + LLVMTypeRef base_integer = lb_type_internal(m, type->RelativeSlice.base_integer); + + unsigned field_count = 2; + LLVMTypeRef *fields = gb_alloc_array(heap_allocator(), LLVMTypeRef, field_count); + fields[0] = base_integer; + fields[1] = base_integer; + return LLVMStructTypeInContext(ctx, fields, field_count, false); + } } GB_PANIC("Invalid type %s", type_to_string(type)); @@ -3970,7 +4037,7 @@ void lb_build_stmt(lbProcedure *p, Ast *node) { } lb_emit_defer_stmts(p, lbDeferExit_Return, nullptr); - + LLVMBuildRet(p->builder, res.value); } case_end; @@ -4323,19 +4390,23 @@ lbValue lb_typeid(lbModule *m, Type *type, Type *typeid_type) { if (flags & BasicFlag_String) kind = Typeid_String; if (flags & BasicFlag_Rune) kind = Typeid_Rune; } break; - case Type_Pointer: kind = Typeid_Pointer; break; - case Type_Array: kind = Typeid_Array; break; + case Type_Pointer: kind = Typeid_Pointer; break; + case Type_Array: kind = Typeid_Array; break; case Type_EnumeratedArray: kind = Typeid_Enumerated_Array; break; - case Type_Slice: kind = Typeid_Slice; break; - case Type_DynamicArray: kind = Typeid_Dynamic_Array; break; - case Type_Map: kind = Typeid_Map; break; - case Type_Struct: kind = Typeid_Struct; break; - case Type_Enum: kind = Typeid_Enum; break; - case Type_Union: kind = Typeid_Union; break; - case Type_Tuple: kind = Typeid_Tuple; break; - case Type_Proc: kind = Typeid_Procedure; break; - case Type_BitField: kind = Typeid_Bit_Field; break; - case Type_BitSet: kind = Typeid_Bit_Set; break; + case Type_Slice: kind = Typeid_Slice; break; + case Type_DynamicArray: kind = Typeid_Dynamic_Array; break; + case Type_Map: kind = Typeid_Map; break; + case Type_Struct: kind = Typeid_Struct; break; + case Type_Enum: kind = Typeid_Enum; break; + case Type_Union: kind = Typeid_Union; break; + case Type_Tuple: kind = Typeid_Tuple; break; + case Type_Proc: kind = Typeid_Procedure; break; + case Type_BitField: kind = Typeid_Bit_Field; break; + case Type_BitSet: kind = Typeid_Bit_Set; break; + case Type_Opaque: kind = Typeid_Opaque; break; + case Type_SimdVector: kind = Typeid_Simd_Vector; break; + case Type_RelativePointer: kind = Typeid_Relative_Pointer; break; + case Type_RelativeSlice: kind = Typeid_Relative_Slice; break; } if (is_type_cstring(type)) { @@ -4495,7 +4566,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value) { res.value = LLVMConstArray(lb_type(m, elem), elems, cast(unsigned)count); return res; - } + } switch (value.kind) { case ExactValue_Invalid: @@ -9723,6 +9794,10 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { case_end; case_ast_node(de, DerefExpr, expr); + if (is_type_relative_pointer(type_of_expr(de->expr))) { + lbAddr addr = lb_build_addr(p, de->expr); + return addr; + } lbValue addr = lb_build_expr(p, de->expr); return lb_addr(addr); case_end; @@ -11192,6 +11267,36 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lb_emit_store(p, tag, res); } break; + + case Type_RelativePointer: + { + tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_relative_pointer_ptr); + LLVMValueRef vals[2] = { + lb_get_type_info_ptr(m, t->RelativePointer.pointer_type).value, + lb_get_type_info_ptr(m, t->RelativePointer.base_integer).value, + }; + + lbValue res = {}; + res.type = type_deref(tag.type); + res.value = LLVMConstNamedStruct(lb_type(m, res.type), vals, gb_count_of(vals)); + lb_emit_store(p, tag, res); + } + break; + case Type_RelativeSlice: + { + tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_relative_slice_ptr); + LLVMValueRef vals[2] = { + lb_get_type_info_ptr(m, t->RelativeSlice.slice_type).value, + lb_get_type_info_ptr(m, t->RelativeSlice.base_integer).value, + }; + + lbValue res = {}; + res.type = type_deref(tag.type); + res.value = LLVMConstNamedStruct(lb_type(m, res.type), vals, gb_count_of(vals)); + lb_emit_store(p, tag, res); + } + break; + } @@ -11554,6 +11659,25 @@ void lb_generate_code(lbGenerator *gen) { LLVMAddMergedLoadStoreMotionPass(default_function_pass_manager); LLVMAddPromoteMemoryToRegisterPass(default_function_pass_manager); // LLVMAddUnifyFunctionExitNodesPass(default_function_pass_manager); + if (build_context.optimization_level >= 2) { + LLVMAddAggressiveInstCombinerPass(default_function_pass_manager); + LLVMAddEarlyCSEPass(default_function_pass_manager); + LLVMAddEarlyCSEMemSSAPass(default_function_pass_manager); + LLVMAddLowerExpectIntrinsicPass(default_function_pass_manager); + + LLVMAddAlignmentFromAssumptionsPass(default_function_pass_manager); + LLVMAddLoopRotatePass(default_function_pass_manager); + LLVMAddDeadStoreEliminationPass(default_function_pass_manager); + LLVMAddScalarizerPass(default_function_pass_manager); + LLVMAddReassociatePass(default_function_pass_manager); + LLVMAddAddDiscriminatorsPass(default_function_pass_manager); + LLVMAddPromoteMemoryToRegisterPass(default_function_pass_manager); + LLVMAddCorrelatedValuePropagationPass(default_function_pass_manager); + + LLVMAddSLPVectorizePass(default_function_pass_manager); + LLVMAddLoopVectorizePass(default_function_pass_manager); + + } } LLVMPassManagerRef default_function_pass_manager_without_memcpy = LLVMCreateFunctionPassManagerForModule(mod); @@ -11784,10 +11908,12 @@ void lb_generate_code(lbGenerator *gen) { for_array(i, m->procedures_to_generate) { lbProcedure *p = m->procedures_to_generate[i]; if (p->body != nullptr) { // Build Procedure - if (p->flags & lbProcedureFlag_WithoutMemcpyPass) { - LLVMRunFunctionPassManager(default_function_pass_manager_without_memcpy, p->value); - } else { - LLVMRunFunctionPassManager(default_function_pass_manager, p->value); + for (i32 i = 0; i <= build_context.optimization_level; i++) { + if (p->flags & lbProcedureFlag_WithoutMemcpyPass) { + LLVMRunFunctionPassManager(default_function_pass_manager_without_memcpy, p->value); + } else { + LLVMRunFunctionPassManager(default_function_pass_manager, p->value); + } } } } @@ -11799,7 +11925,12 @@ void lb_generate_code(lbGenerator *gen) { defer (LLVMDisposePassManager(module_pass_manager)); LLVMAddAlwaysInlinerPass(module_pass_manager); LLVMAddStripDeadPrototypesPass(module_pass_manager); - // LLVMAddConstantMergePass(module_pass_manager); + // if (build_context.optimization_level >= 2) { + // LLVMAddArgumentPromotionPass(module_pass_manager); + // LLVMAddConstantMergePass(module_pass_manager); + // LLVMAddGlobalDCEPass(module_pass_manager); + // LLVMAddDeadArgEliminationPass(module_pass_manager); + // } LLVMPassManagerBuilderRef pass_manager_builder = LLVMPassManagerBuilderCreate(); defer (LLVMPassManagerBuilderDispose(pass_manager_builder)); |