Browse Source

Add i128/u128 support for bit sets

gingerBill 6 years ago
parent
commit
c40acd008e
6 changed files with 43 additions and 32 deletions
  1. 11 7
      core/fmt/fmt.odin
  2. 8 1
      core/math/bits/bits.odin
  3. 2 0
      core/runtime/internal.odin
  4. 1 16
      examples/demo/demo.odin
  5. 2 2
      src/check_expr.cpp
  6. 19 6
      src/check_type.cpp

+ 11 - 7
core/fmt/fmt.odin

@@ -912,8 +912,8 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "") {
 		fmt_bit_set(fi, val, info.name);
 
 	case runtime.Type_Info_Bit_Set:
-		bits: u64;
-		bit_size := u64(8*type_info.size);
+		bits: u128;
+		bit_size := u128(8*type_info.size);
 
 		do_byte_swap := is_bit_set_different_endian_to_platform(info.underlying);
 
@@ -921,19 +921,23 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "") {
 		case  0: bits = 0;
 		case  8:
 			x := (^u8)(v.data)^;
-			bits = u64(x);
+			bits = u128(x);
 		case 16:
 			x := (^u16)(v.data)^;
 			if do_byte_swap do x = byte_swap(x);
-			bits = u64(x);
+			bits = u128(x);
 		case 32:
 			x := (^u32)(v.data)^;
 			if do_byte_swap do x = byte_swap(x);
-			bits = u64(x);
+			bits = u128(x);
 		case 64:
 			x := (^u64)(v.data)^;
 			if do_byte_swap do x = byte_swap(x);
-			bits = u64(x);
+			bits = u128(x);
+		case 128:
+			x := (^u128)(v.data)^;
+			if do_byte_swap do x = byte_swap(x);
+			bits = u128(x);
 		case: panic("unknown bit_size size");
 		}
 
@@ -958,7 +962,7 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "") {
 
 			if is_enum do for ev, evi in e.values {
 				v := enum_value_to_u64(ev);
-				if v == i {
+				if v == u64(i) {
 					strings.write_string(fi.buf, e.names[evi]);
 					commas += 1;
 					continue loop;

+ 8 - 1
core/math/bits/bits.odin

@@ -22,6 +22,7 @@ I16_MAX :: 1 << 15 - 1;
 I32_MAX :: 1 << 31 - 1;
 I64_MAX :: 1 << 63 - 1;
 
+@(default_calling_convention="none")
 foreign {
 	@(link_name="llvm.ctpop.i8")        count_ones8  :: proc(i:  u8) ->  u8 ---
 	@(link_name="llvm.ctpop.i16")       count_ones16 :: proc(i: u16) -> u16 ---
@@ -49,6 +50,8 @@ foreign {
 	@(link_name="llvm.bswap.i16")       byte_swap_i16 :: proc(i16) -> i16 ---
 	@(link_name="llvm.bswap.i32")       byte_swap_i32 :: proc(i32) -> i32 ---
 	@(link_name="llvm.bswap.i64")       byte_swap_i64 :: proc(i64) -> i64 ---
+	@(link_name="llvm.bswap.i128")      byte_swap_u128 :: proc(u128) -> u128 ---
+	@(link_name="llvm.bswap.i128")      byte_swap_i128 :: proc(i128) -> i128 ---
 }
 
 byte_swap_uint :: proc(i: uint) -> uint {
@@ -70,9 +73,11 @@ byte_swap :: proc{
 	byte_swap_u16,
 	byte_swap_u32,
 	byte_swap_u64,
+	byte_swap_u128,
 	byte_swap_i16,
 	byte_swap_i32,
 	byte_swap_i64,
+	byte_swap_i128,
 	byte_swap_uint,
 	byte_swap_int,
 };
@@ -120,6 +125,7 @@ to_le_u64  :: proc(i:  u64) ->  u64 { when os.ENDIAN == "little" { return i; } e
 to_le_uint :: proc(i: uint) -> uint { when os.ENDIAN == "little" { return i; } else { return byte_swap(i); } }
 
 
+@(default_calling_convention="none")
 foreign {
 	@(link_name="llvm.uadd.with.overflow.i8")  overflowing_add_u8  :: proc(lhs, rhs:  u8) -> (u8, bool)  ---
 	@(link_name="llvm.sadd.with.overflow.i8")  overflowing_add_i8  :: proc(lhs, rhs:  i8) -> (i8, bool)  ---
@@ -158,6 +164,7 @@ overflowing_add :: proc{
 	overflowing_add_uint, overflowing_add_int,
 };
 
+@(default_calling_convention="none")
 foreign {
 	@(link_name="llvm.usub.with.overflow.i8")  overflowing_sub_u8  :: proc(lhs, rhs:  u8) -> (u8, bool)  ---
 	@(link_name="llvm.ssub.with.overflow.i8")  overflowing_sub_i8  :: proc(lhs, rhs:  i8) -> (i8, bool)  ---
@@ -195,7 +202,7 @@ overflowing_sub :: proc{
 	overflowing_sub_uint, overflowing_sub_int,
 };
 
-
+@(default_calling_convention="none")
 foreign {
 	@(link_name="llvm.umul.with.overflow.i8")  overflowing_mul_u8  :: proc(lhs, rhs:  u8) -> (u8, bool)  ---
 	@(link_name="llvm.smul.with.overflow.i8")  overflowing_mul_i8  :: proc(lhs, rhs:  i8) -> (i8, bool)  ---

+ 2 - 0
core/runtime/internal.odin

@@ -510,6 +510,7 @@ quo_complex128 :: proc(n, m: complex128) -> complex128 {
 	return complex(e, f);
 }
 
+@(default_calling_convention="none")
 foreign {
 	@(link_name="llvm.cttz.i8")  _ctz_u8  :: proc(i:  u8,  is_zero_undef := false) ->  u8 ---
 	@(link_name="llvm.cttz.i16") _ctz_u16 :: proc(i: u16,  is_zero_undef := false) -> u16 ---
@@ -523,6 +524,7 @@ _ctz :: proc{
 	_ctz_u64,
 };
 
+@(default_calling_convention="none")
 foreign {
 	@(link_name="llvm.ctlz.i8")  _clz_u8  :: proc(i:  u8,  is_zero_undef := false) ->  u8 ---
 	@(link_name="llvm.ctlz.i16") _clz_u16 :: proc(i: u16,  is_zero_undef := false) -> u16 ---

+ 1 - 16
examples/demo/demo.odin

@@ -946,22 +946,7 @@ deferred_procedure_associations :: proc() {
 }
 
 main :: proc() {
-	x: u128 = 1233456453347654617;
-	y: u128 = 19;
-	z := x * y;
-	w := z / 120;
-
-	assert(z == 23435672613605437723);
-	// assert(w == 195297271780045314);
-
-
-	fmt.println(x);
-	fmt.println(y);
-	fmt.println(z, u128(23435672613605437723));
-	fmt.println(w, u128(195297271780045314));
-	fmt.println(x % 33774564533476546);
-
-	when false {
+	when true {
 		general_stuff();
 		union_type();
 		parametric_polymorphism();

+ 2 - 2
src/check_expr.cpp

@@ -86,8 +86,8 @@ CallArgumentData check_call_arguments   (CheckerContext *c, Operand *operand, Ty
 Type *           check_init_variable    (CheckerContext *c, Entity *e, Operand *operand, String context_name);
 
 
-Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type);
-Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type);
+Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type, ProcCallingConvention cc);
+Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type, ProcCallingConvention cc);
 bool abi_compat_return_by_pointer(gbAllocator a, ProcCallingConvention cc, Type *abi_return_type);
 void set_procedure_abi_types(CheckerContext *c, Type *type);
 

+ 19 - 6
src/check_type.cpp

@@ -746,6 +746,11 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast
 		return;
 	}
 
+	if (is_type_integer_128bit(base_type)) {
+		error(node, "Base type for enumeration cannot be a 128-bit integer");
+		return;
+	}
+
 	// NOTE(bill): Must be up here for the 'check_init_constant' system
 	enum_type->Enum.base_type = base_type;
 	enum_type->Enum.scope = ctx->scope;
@@ -1825,7 +1830,7 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) {
 	return tuple;
 }
 
-Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
+Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type, ProcCallingConvention cc) {
 	Type *new_type = original_type;
 
 	if (is_type_boolean(original_type)) {
@@ -1851,7 +1856,11 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type) {
 
 		if (build_context.word_size == 8) {
 			if (is_type_integer_128bit(original_type)) {
-				return alloc_type_simd_vector(2, t_u64);
+				if (cc == ProcCC_None) {
+					return original_type;
+				} else {
+					return alloc_type_simd_vector(2, t_u64);
+				}
 			}
 		}
 
@@ -1947,7 +1956,7 @@ Type *reduce_tuple_to_single_type(Type *original_type) {
 	return original_type;
 }
 
-Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) {
+Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type, ProcCallingConvention cc) {
 	Type *new_type = original_type;
 	if (new_type == nullptr) {
 		return nullptr;
@@ -1963,7 +1972,11 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) {
 	if (build_context.ODIN_OS == "windows") {
 		if (build_context.word_size == 8) {
 			if (is_type_integer_128bit(single_type)) {
-				return alloc_type_simd_vector(2, t_u64);
+				if (cc == ProcCC_None) {
+					return original_type;
+				} else {
+					return alloc_type_simd_vector(2, t_u64);
+				}
 			}
 		}
 
@@ -2071,13 +2084,13 @@ void set_procedure_abi_types(CheckerContext *c, Type *type) {
 		Entity *e = type->Proc.params->Tuple.variables[i];
 		if (e->kind == Entity_Variable) {
 			Type *original_type = e->type;
-			Type *new_type = type_to_abi_compat_param_type(c->allocator, original_type);
+			Type *new_type = type_to_abi_compat_param_type(c->allocator, original_type, type->Proc.calling_convention);
 			type->Proc.abi_compat_params[i] = new_type;
 		}
 	}
 
 	// NOTE(bill): The types are the same
-	type->Proc.abi_compat_result_type = type_to_abi_compat_result_type(c->allocator, type->Proc.results);
+	type->Proc.abi_compat_result_type = type_to_abi_compat_result_type(c->allocator, type->Proc.results, type->Proc.calling_convention);
 	type->Proc.return_by_pointer = abi_compat_return_by_pointer(c->allocator, type->Proc.calling_convention, type->Proc.abi_compat_result_type);
 }