From 3aea08df7869f39c12a4d787be25306944d68e70 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 11 Dec 2017 11:06:43 +0000 Subject: [PATCH] Change how abs, min, max, and clamp are implemented for floats --- core/_preload.odin | 18 +++++-- core/raw.odin | 5 +- src/check_expr.cpp | 11 +++-- src/ir.cpp | 116 ++++++++++++++++++++------------------------- src/ir_print.cpp | 22 ++++----- 5 files changed, 88 insertions(+), 84 deletions(-) diff --git a/core/_preload.odin b/core/_preload.odin index 6317c4a36..1e7c75ab1 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -240,18 +240,19 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info { +@(default_calling_convention = "c") foreign __llvm_core { @(link_name="llvm.assume") - assume :: proc "c" (cond: bool) ---; + assume :: proc(cond: bool) ---; @(link_name="llvm.debugtrap") - __debug_trap :: proc "c" () ---; + __debug_trap :: proc() ---; @(link_name="llvm.trap") - __trap :: proc "c" () ---; + __trap :: proc() ---; @(link_name="llvm.readcyclecounter") - read_cycle_counter :: proc "c" () -> u64 ---; + read_cycle_counter :: proc() -> u64 ---; } @@ -776,6 +777,7 @@ __mem_compare :: proc "contextless" (a, b: ^byte, n: int) -> int { return 0; } +@(default_calling_convention = "c") foreign __llvm_core { @(link_name="llvm.sqrt.f32") __sqrt_f32 :: proc(x: f32) -> f32 ---; @(link_name="llvm.sqrt.f64") __sqrt_f64 :: proc(x: f64) -> f64 ---; @@ -791,6 +793,14 @@ foreign __llvm_core { @(link_name="llvm.fmuladd.f32") fmuladd32 :: proc(a, b, c: f32) -> f32 ---; @(link_name="llvm.fmuladd.f64") fmuladd64 :: proc(a, b, c: f64) -> f64 ---; + + @(link_name="llvm.fabs.f32") __abs_f32 :: proc(x: f32) -> f32 ---; + @(link_name="llvm.fabs.f64") __abs_f64 :: proc(x: f64) -> f32 ---; + + @(link_name="llvm.minnum.f32") __min_f32 :: proc(a, b: f32) -> f32 ---; + @(link_name="llvm.minnum.f64") __min_f64 :: proc(a, b: f64) -> f32 ---; + @(link_name="llvm.maxnum.f32") __max_f32 :: proc(a, b: f32) -> f32 ---; + @(link_name="llvm.maxnum.f64") __max_f64 :: proc(a, b: f64) -> f32 ---; } __abs_complex64 :: inline proc "contextless" (x: complex64) -> f32 { r, i := real(x), imag(x); diff --git a/core/raw.odin b/core/raw.odin index a8184026e..ac5482233 100644 --- a/core/raw.odin +++ b/core/raw.odin @@ -25,10 +25,13 @@ Map :: struct #ordered { entries: Dynamic_Array, } +make_any :: inline proc(data: rawptr, type_info: ^Type_Info) -> any { + return transmute(any)Any{data, type_info}; +} + string_data :: inline proc(s: $T/string) -> ^byte { return (^String)(&s).data; } - slice_data :: inline proc(a: $T/[]$E) -> ^E { return cast(^E)(^Slice)(&a).data; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 9b33dabcd..da830aab1 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2527,8 +2527,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h } if (entity->kind == Entity_ProcGroup) { - auto *pge = &entity->ProcGroup; - Array procs = pge->entities; + Array procs = entity->ProcGroup.entities; bool skip = false; for_array(i, procs) { Entity *p = procs[i]; @@ -5460,8 +5459,12 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t max = index; } - if (t->kind == Type_Array && is_to_be_determined_array_count) { - t->Array.count = max; + if (t->kind == Type_Array) { + if (is_to_be_determined_array_count) { + t->Array.count = max; + } else if (0 < max && max < t->Array.count) { + error(node, "Expected %lld values for this array literal, got %lld", cast(long long)t->Array.count, cast(long long)max); + } } break; diff --git a/src/ir.cpp b/src/ir.cpp index bf0378743..c05fb0bf3 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -1602,6 +1602,7 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, irValue **args, isize arg_ if (e->kind != Entity_Variable) { continue; } + GB_ASSERT(e->flags & EntityFlag_Param); Type *original_type = e->type; Type *new_type = pt->Proc.abi_compat_params[i]; if (original_type != new_type) { @@ -3873,19 +3874,48 @@ void ir_build_defer_stmt(irProcedure *proc, irDefer d) { } } +irValue *ir_emit_min(irProcedure *proc, Type *t, irValue *x, irValue *y) { + x = ir_emit_conv(proc, x, t); + y = ir_emit_conv(proc, y, t); + + if (is_type_float(t)) { + gbAllocator a = proc->module->allocator; + i64 sz = 8*type_size_of(a, t); + irValue **args = gb_alloc_array(a, irValue *, 1); + args[0] = x; + switch (sz) { + case 32: return ir_emit_global_call(proc, "__min_f32", args, 1); + case 64: return ir_emit_global_call(proc, "__min_f64", args, 1); + } + GB_PANIC("Unknown float type"); + } + return ir_emit_select(proc, ir_emit_comp(proc, Token_Lt, x, y), x, y); +} +irValue *ir_emit_max(irProcedure *proc, Type *t, irValue *x, irValue *y) { + x = ir_emit_conv(proc, x, t); + y = ir_emit_conv(proc, y, t); + + if (is_type_float(t)) { + gbAllocator a = proc->module->allocator; + i64 sz = 8*type_size_of(a, t); + irValue **args = gb_alloc_array(a, irValue *, 1); + args[0] = x; + switch (sz) { + case 32: return ir_emit_global_call(proc, "__max_f32", args, 1); + case 64: return ir_emit_global_call(proc, "__max_f64", args, 1); + } + GB_PANIC("Unknown float type"); + } + return ir_emit_select(proc, ir_emit_comp(proc, Token_Gt, x, y), x, y); +} + irValue *ir_emit_clamp(irProcedure *proc, Type *t, irValue *x, irValue *min, irValue *max) { - irValue *cond = nullptr; ir_emit_comment(proc, str_lit("clamp")); - x = ir_emit_conv(proc, x, t); - min = ir_emit_conv(proc, min, t); - max = ir_emit_conv(proc, max, t); - - cond = ir_emit_comp(proc, Token_Gt, min, x); - x = ir_emit_select(proc, cond, min, x); - cond = ir_emit_comp(proc, Token_Lt, max, x); - x = ir_emit_select(proc, cond, max, x); - return x; + irValue *z = nullptr; + z = ir_emit_max(proc, t, x, min); + z = ir_emit_min(proc, t, z, max); + return z; } @@ -4543,46 +4573,6 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv break; } - #if 0 - case BuiltinProc_slice_ptr: { - ir_emit_comment(proc, str_lit("slice_ptr")); - irValue *ptr = ir_build_expr(proc, ce->args[0]); - irValue *count = ir_build_expr(proc, ce->args[1]); - count = ir_emit_conv(proc, count, t_int); - irValue *capacity = count; - if (ce->args.count > 2) { - capacity = ir_build_expr(proc, ce->args[2]); - capacity = ir_emit_conv(proc, capacity, t_int); - } - - Type *slice_type = make_type_slice(proc->module->allocator, type_deref(ir_type(ptr))); - irValue *slice = ir_add_local_generated(proc, slice_type); - ir_fill_slice(proc, slice, ptr, count, capacity); - return ir_emit_load(proc, slice); - break; - } - - case BuiltinProc_slice_to_bytes: { - ir_emit_comment(proc, str_lit("slice_to_bytes")); - irValue *s = ir_build_expr(proc, ce->args[0]); - Type *t = base_type(ir_type(s)); - if (is_type_u8_slice(t)) { - return ir_emit_conv(proc, s, tv.type); - } - irValue *slice = ir_add_local_generated(proc, tv.type); - i64 elem_size = type_size_of(proc->module->allocator, t->Slice.elem); - - irValue *ptr = ir_emit_conv(proc, ir_slice_elem(proc, s), t_u8_ptr); - irValue *count = ir_slice_count(proc, s); - irValue *capacity = ir_slice_capacity(proc, s); - count = ir_emit_arith(proc, Token_Mul, count, ir_const_int(proc->module->allocator, elem_size), t_int); - capacity = ir_emit_arith(proc, Token_Mul, capacity, ir_const_int(proc->module->allocator, elem_size), t_int); - ir_fill_slice(proc, slice, ptr, count, capacity); - return ir_emit_load(proc, slice); - break; - } - #endif - case BuiltinProc_expand_to_tuple: { ir_emit_comment(proc, str_lit("expand_to_tuple")); irValue *s = ir_build_expr(proc, ce->args[0]); @@ -4600,35 +4590,26 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv ir_emit_store(proc, ep, f); } return ir_emit_load(proc, tuple); - break; } case BuiltinProc_min: { ir_emit_comment(proc, str_lit("min")); Type *t = type_of_expr(proc->module->info, expr); - irValue *x = ir_emit_conv(proc, ir_build_expr(proc, ce->args[0]), t); - irValue *y = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t); - irValue *cond = ir_emit_comp(proc, Token_Lt, x, y); - return ir_emit_select(proc, cond, x, y); - break; + return ir_emit_min(proc, t, ir_build_expr(proc, ce->args[0]), ir_build_expr(proc, ce->args[1])); } case BuiltinProc_max: { ir_emit_comment(proc, str_lit("max")); Type *t = type_of_expr(proc->module->info, expr); - irValue *x = ir_emit_conv(proc, ir_build_expr(proc, ce->args[0]), t); - irValue *y = ir_emit_conv(proc, ir_build_expr(proc, ce->args[1]), t); - irValue *cond = ir_emit_comp(proc, Token_Gt, x, y); - return ir_emit_select(proc, cond, x, y); - break; + return ir_emit_max(proc, t, ir_build_expr(proc, ce->args[0]), ir_build_expr(proc, ce->args[1])); } case BuiltinProc_abs: { ir_emit_comment(proc, str_lit("abs")); + gbAllocator a = proc->module->allocator; irValue *x = ir_build_expr(proc, ce->args[0]); Type *t = ir_type(x); if (is_type_complex(t)) { - gbAllocator a = proc->module->allocator; i64 sz = 8*type_size_of(a, t); irValue **args = gb_alloc_array(a, irValue *, 1); args[0] = x; @@ -4637,12 +4618,20 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv case 128: return ir_emit_global_call(proc, "__abs_complex128", args, 1); } GB_PANIC("Unknown complex type"); + } else if (is_type_float(t)) { + i64 sz = 8*type_size_of(a, t); + irValue **args = gb_alloc_array(a, irValue *, 1); + args[0] = x; + switch (sz) { + case 32: return ir_emit_global_call(proc, "__abs_f32", args, 1); + case 64: return ir_emit_global_call(proc, "__abs_f64", args, 1); + } + GB_PANIC("Unknown float type"); } irValue *zero = ir_emit_conv(proc, v_zero, t); irValue *cond = ir_emit_comp(proc, Token_Lt, x, zero); irValue *neg = ir_emit(proc, ir_instr_unary_op(proc, Token_Sub, x, t)); return ir_emit_select(proc, cond, neg, x); - break; } case BuiltinProc_clamp: { @@ -4652,7 +4641,6 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv ir_build_expr(proc, ce->args[0]), ir_build_expr(proc, ce->args[1]), ir_build_expr(proc, ce->args[2])); - break; } } diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 255611fb8..8a67cb6e2 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1826,29 +1826,29 @@ void print_llvm_ir(irGen *ir) { } ir_print_encoded_local(f, str_lit("..opaque")); - ir_write_string(f, str_lit(" = type {};\n")); + ir_write_string(f, " = type {};\n"); ir_print_encoded_local(f, str_lit("..string")); - ir_write_string(f, str_lit(" = type {i8*, ")); + ir_write_string(f, " = type {i8*, "); ir_print_type(f, m, t_int); - ir_write_string(f, str_lit("} ; Basic_string\n")); + ir_write_string(f, "} ; Basic_string\n"); ir_print_encoded_local(f, str_lit("..rawptr")); - ir_write_string(f, str_lit(" = type i8* ; Basic_rawptr\n")); + ir_write_string(f, " = type i8* ; Basic_rawptr\n"); ir_print_encoded_local(f, str_lit("..complex32")); - ir_write_string(f, str_lit(" = type {half, half} ; Basic_complex32\n")); + ir_write_string(f, " = type {half, half} ; Basic_complex32\n"); ir_print_encoded_local(f, str_lit("..complex64")); - ir_write_string(f, str_lit(" = type {float, float} ; Basic_complex64\n")); + ir_write_string(f, " = type {float, float} ; Basic_complex64\n"); ir_print_encoded_local(f, str_lit("..complex128")); - ir_write_string(f, str_lit(" = type {double, double} ; Basic_complex128\n")); + ir_write_string(f, " = type {double, double} ; Basic_complex128\n"); ir_print_encoded_local(f, str_lit("..any")); - ir_write_string(f, str_lit(" = type {")); + ir_write_string(f, " = type {"); ir_print_type(f, m, t_rawptr); - ir_write_string(f, str_lit(", ")); + ir_write_string(f, ", "); ir_print_type(f, m, t_type_info_ptr); - ir_write_string(f, str_lit("} ; Basic_any\n")); + ir_write_string(f, "} ; Basic_any\n"); - ir_write_string(f, str_lit("declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone \n")); + ir_write_string(f, "declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone \n"); ir_write_byte(f, '\n');