Browse Source

Change how abs, min, max, and clamp are implemented for floats

gingerBill 7 years ago
parent
commit
3aea08df78
5 changed files with 88 additions and 84 deletions
  1. 14 4
      core/_preload.odin
  2. 4 1
      core/raw.odin
  3. 7 4
      src/check_expr.cpp
  4. 52 64
      src/ir.cpp
  5. 11 11
      src/ir_print.cpp

+ 14 - 4
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);

+ 4 - 1
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;
 }

+ 7 - 4
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<Entity *> procs = pge->entities;
+				Array<Entity *> 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;

+ 52 - 64
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;
 	}
 	}
 

+ 11 - 11
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');