Răsfoiți Sursa

Merge pull request #3893 from HaxeFoundation/int64-new

Int64 abstract
Simon Krajewski 10 ani în urmă
părinte
comite
09a4f4dc54

+ 2 - 1
ast.ml

@@ -90,6 +90,7 @@ module Meta = struct
 		| IfFeature
 		| Impl
 		| PythonImport
+		| ImplicitCast
 		| Include
 		| InitPackage
 		| Internal
@@ -747,4 +748,4 @@ let get_value_meta meta =
 			| _ -> raise Not_found
 		end
 	with Not_found ->
-		PMap.empty
+		PMap.empty

+ 23 - 5
codegen.ml

@@ -690,7 +690,10 @@ module AbstractCast = struct
 			if (Meta.has Meta.MultiType a.a_meta) then
 				mk_cast eright tleft p
 			else match a.a_impl with
-				| Some c -> recurse cf (fun () -> make_static_call ctx c cf a tl [eright] tleft p)
+				| Some c -> recurse cf (fun () ->
+					let ret = make_static_call ctx c cf a tl [eright] tleft p in
+					{ ret with eexpr = TMeta( (Meta.ImplicitCast,[],ret.epos), ret) }
+				)
 				| None -> assert false
 		in
 		if type_iseq tleft eright.etype then
@@ -1546,6 +1549,13 @@ struct
 		List.iter2 (fun f a -> if not (type_iseq f a) then incr acc) tlfun tlarg;
 		!acc
 
+	(**
+		The rate function returns an ( int * int ) type.
+		The smaller the int, the best rated the caller argument is in comparison with the callee.
+
+		The first int refers to how many "conversions" would be necessary to convert from the callee to the caller type, and
+		the second refers to the type parameters.
+	**)
 	let rec rate_conv cacc tfun targ =
 		match simplify_t tfun, simplify_t targ with
 		| TInst({ cl_interface = true } as cf, tlf), TInst(ca, tla) ->
@@ -1637,10 +1647,11 @@ struct
 		| r :: ret ->
 			rm_duplicates (r :: acc) ret
 
-(* 	let s_options rated =
-		String.concat ",\n" (List.map (fun ((_,t),rate) ->
+	let s_options rated =
+		String.concat ",\n" (List.map (fun ((elist,t,_),rate) ->
+			"( " ^ (String.concat "," (List.map (fun(e,_) -> s_expr (s_type (print_context())) e) elist)) ^ " ) => " ^
 			"( " ^ (String.concat "," (List.map (fun (i,i2) -> string_of_int i ^ ":" ^ string_of_int i2) rate)) ^ " ) => " ^ (s_type (print_context()) t)
-		) rated) *)
+		) rated)
 
 	let count_optionals elist =
 		List.fold_left (fun acc (_,is_optional) -> if is_optional then acc + 1 else acc) 0 elist
@@ -1667,7 +1678,14 @@ struct
 				| [], [] -> acc
 				| (_,true) :: elist, _ :: args -> mk_rate acc elist args
 				| (e,false) :: elist, (n,o,t) :: args ->
-					mk_rate (rate_conv 0 t e.etype :: acc) elist args
+					(* if the argument is an implicit cast, we need to start with a penalty *)
+					(* The penalty should be higher than any other implicit cast - other than Dynamic *)
+					(* since Dynamic has a penalty of max_int, we'll impose max_int - 1 to it *)
+					(match e.eexpr with
+						| TMeta( (Meta.ImplicitCast,_,_), _) ->
+							mk_rate ((max_int - 1, 0) :: acc) elist args
+						| _ ->
+							mk_rate (rate_conv 0 t e.etype :: acc) elist args)
 				| _ -> assert false
 			in
 

+ 1 - 0
common.ml

@@ -412,6 +412,7 @@ module MetaInfo = struct
 		| IfFeature -> ":ifFeature",("Causes a field to be kept by DCE if the given feature is part of the compilation",[HasParam "Feature name";UsedOn TClassField])
 		| Impl -> ":impl",("Used internally to mark abstract implementation fields",[UsedOn TAbstractField; Internal])
 		| PythonImport -> ":pythonImport",("Generates python import statement for extern classes",[Platforms [Python]; UsedOn TClass])
+		| ImplicitCast -> ":implicitCast",("Generated automatically on the AST when an implicit abstract cast happens",[Internal; UsedOn TExpr])
 		| Include -> ":include",("",[Platform Cpp])
 		| InitPackage -> ":initPackage",("?",[])
 		| Meta.Internal -> ":internal",("Generates the annotated field/class with 'internal' access",[Platforms [Java;Cs]; UsedOnEither[TClass;TEnum;TClassField]])

+ 2 - 0
gencommon.ml

@@ -84,8 +84,10 @@ let rec like_int t =
 let rec like_i64 t =
 	match follow t with
 		| TInst({ cl_path = (["cs"], "Int64") },[])
+		| TAbstract({ a_path = (["cs"], "Int64") },[])
 		| TInst({ cl_path = (["cs"], "UInt64") },[])
 		| TInst({ cl_path = (["java"], "Int64") },[])
+		| TAbstract({ a_path = (["java"], "Int64") },[])
 		| TInst({ cl_path = (["haxe"], "Int64") },[])
 		| TAbstract({ a_path = (["haxe"], "Int64") },[]) -> true
 		| TAbstract(a, _) -> List.exists (fun t -> like_i64 t) a.a_from || List.exists (fun t -> like_i64 t) a.a_to

+ 2 - 0
gencs.ml

@@ -39,6 +39,8 @@ let rec is_cs_basic_type t =
 	match follow t with
 		| TInst( { cl_path = (["haxe"], "Int32") }, [] )
 		| TInst( { cl_path = (["haxe"], "Int64") }, [] )
+		| TAbstract ({ a_path = (["cs"], "Int64") },[])
+		| TAbstract ({ a_path = (["cs"], "UInt64") },[]) 
 		| TAbstract ({ a_path = ([], "Int") },[])
 		| TAbstract ({ a_path = ([], "Float") },[])
 		| TAbstract ({ a_path = ([], "Bool") },[]) ->

+ 3 - 1
genjava.ml

@@ -84,7 +84,7 @@ let is_java_basic_type t =
 		| TInst( { cl_path = (["haxe"], "Int32") }, [] )
 		| TInst( { cl_path = (["haxe"], "Int64") }, [] )
 		| TAbstract( { a_path = ([], "Single") }, [] )
-		| TAbstract( { a_path = (["java"], ("Int8" | "Int16" | "Char16")) }, [] )
+		| TAbstract( { a_path = (["java"], ("Int8" | "Int16" | "Char16" | "Int64")) }, [] )
 		| TAbstract( { a_path =	([], "Int") }, [] )
 		| TAbstract( { a_path =	([], "Float") }, [] )
 		| TAbstract( { a_path =	([], "Bool") }, [] ) ->
@@ -234,6 +234,8 @@ struct
 							mk_is true obj i16_md
 						| TAbstractDecl{ a_path = (["java"], "Char16") } ->
 							mk_is true obj c16_md
+						| TAbstractDecl{ a_path = (["java"], "Int64") } ->
+							mk_is true obj i64_md
 						| TClassDecl{ cl_path = (["haxe"], "Int64") } ->
 							mk_is true obj i64_md
 						| TAbstractDecl{ a_path = ([], "Dynamic") }

+ 0 - 0
std/cpp/_std/haxe/Int64.hx → std/cpp/_std/haxe/Int64.hx2


+ 11 - 1
std/cs/StdTypes.hx

@@ -26,7 +26,7 @@ package cs;
 @:notNull @:runtimeValue @:coreType abstract Char16 from Int {}
 @:notNull @:runtimeValue @:coreType abstract UInt8 to Int from Int {}
 @:notNull @:runtimeValue @:coreType abstract UInt16 to Int {}
-@:notNull @:runtimeValue @:coreType abstract Int64 from Int from Float from haxe.Int64
+@:notNull @:runtimeValue @:coreType abstract Int64 from Int from Float
 {
 	@:op(A+B) public static function addI(lhs:Int64, rhs:Int):Int64;
 	@:op(A+B) public static function add(lhs:Int64, rhs:Int64):Int64;
@@ -56,6 +56,11 @@ package cs;
 
 	@:op(~A) public static function bneg(t:Int64):Int64;
 	@:op(-A) public static function neg(t:Int64):Int64;
+
+	@:op(++A) public static function preIncrement(t:Int64):Int64;
+	@:op(A++) public static function postIncrement(t:Int64):Int64;
+	@:op(--A) public static function preDecrement(t:Int64):Int64;
+	@:op(A--) public static function postDecrement(t:Int64):Int64;
 }
 @:notNull @:runtimeValue @:coreType abstract UInt64 from Int from Int64 from Float from haxe.Int64
 {
@@ -87,4 +92,9 @@ package cs;
 
 	@:op(~A) public static function bneg(t:UInt64):UInt64;
 	@:op(-A) public static function neg(t:UInt64):UInt64;
+
+	@:op(++A) public static function preIncrement(t:UInt64):UInt64;
+	@:op(A++) public static function postIncrement(t:UInt64):UInt64;
+	@:op(--A) public static function preDecrement(t:UInt64):UInt64;
+	@:op(A--) public static function postDecrement(t:UInt64):UInt64;
 }

+ 154 - 89
std/cs/_std/haxe/Int64.hx

@@ -21,124 +21,189 @@
  */
 package haxe;
 using haxe.Int64;
-import cs.StdTypes.Int64 in NativeInt64;
-import cs.StdTypes.UInt64 in NativeUInt64;
+
+private typedef __Int64 = cs.StdTypes.Int64;
 
 @:coreApi
-@:nativeGen class Int64
+abstract Int64(__Int64) from __Int64 to __Int64
 {
-	@:extern private static inline function asNative(i:Int64):NativeInt64 return untyped i;
-	@:extern private static inline function ofNative(i:NativeInt64):Int64 return untyped i;
-	@:extern private static inline function ofUNative(i:NativeUInt64):Int64 return untyped i;
-	@:extern private static inline function mkNative(i:Int):NativeInt64 return cast i;
 
-	public static inline function make( high : Int, low : Int ) : Int64
-	{
-		return ((cast(high, NativeInt64) << 32 ) | (low & untyped __cs__('0xffffffffL'))).ofNative();
-	}
+	public static inline function make( high : Int32, low : Int32 ) : Int64
+		return new Int64( (cast(high, __Int64) << 32) | (cast(low, __Int64)& untyped __cs__('0xffffffffL')) );
 
-	public static inline function getLow( x : Int64 ) : Int
-	{
-		return cast (x.asNative() & (untyped __cs__("0xFFFFFFFFL")), Int);
-	}
+	private inline function new(x : __Int64)
+		this = x;
 
-	public static inline function getHigh( x : Int64 ) : Int {
-		return cast(cast(x,NativeUInt64) >> 32, Int);
-	}
+	private var val( get, set ) : __Int64;
+	inline function get_val() : __Int64 return this;
+	inline function set_val( x : __Int64 ) : __Int64 return this = x;
 
-	public static inline function ofInt( x : Int ) : Int64 {
-		return cast x;
-	}
+	public inline function copy():Int64
+		return new Int64( this );
 
-	public static inline function toInt( x : Int64 ) : Int
-	{
+	@:from public static inline function ofInt( x : Int ) : Int64
 		return cast x;
-	}
 
-	public static inline function add( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() + b.asNative()).ofNative();
+	public static inline function toInt( x : Int64 ) : Int {
+		if( x.val < 0x80000000 || x.val > 0x7FFFFFFF )
+			throw "Overflow";
+		return cast x.val;
 	}
 
-	public static inline function sub( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() - b.asNative()).ofNative();
-	}
+	public static inline function getHigh( x : Int64 ) : Int32
+		return cast( x.val >> 32 );
 
-	public static inline function mul( a : Int64, b : Int64 ) : Int64 {
-		return (a.asNative() * b.asNative()).ofNative();
-	}
+	public static inline function getLow( x : Int64 ) : Int32
+		return cast( x.val );
 
-	static function divMod( modulus : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 }
+	public static inline function isNeg( x : Int64 ) : Bool
+		return x.val < 0;
+
+	public static inline function isZero( x : Int64 ) : Bool
+		return x.val == 0;
+
+	public static inline function compare( a : Int64, b : Int64 ) : Int
 	{
-		var q:Int64 = (modulus.asNative() / divisor.asNative()).ofNative();
-		var m:Int64 = (modulus.asNative() % divisor.asNative()).ofNative();
-		return { quotient : q, modulus : m };
+		if( a.val < b.val ) return -1;
+		if( a.val > b.val ) return 1;
+		return 0;
 	}
 
-	public static inline function div( a : Int64, b : Int64 ) : Int64 {
-		return (a.asNative() / b.asNative()).ofNative();
+	public static inline function ucompare( a : Int64, b : Int64 ) : Int {
+		if( a.val < 0 )
+			return ( b.val < 0 ) ? compare( a, b ) : 1;
+		return ( b.val < 0 ) ? -1 : compare( a, b );
 	}
 
-	public static inline function mod( a : Int64, b : Int64 ) : Int64 {
-		return (a.asNative() % b.asNative()).ofNative();
-	}
+	public static inline function toStr( x : Int64 ) : String
+		return '${x.val}';
 
-	public static inline function shl( a : Int64, b : Int ) : Int64 {
-		return (a.asNative() << b).ofNative();
-	}
+	public static inline function divMod( dividend : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 }
+		return { quotient: dividend / divisor, modulus: dividend % divisor };
 
-	public static inline function shr( a : Int64, b : Int ) : Int64 {
-		return (a.asNative() >> b).ofNative();
-	}
+	private inline function toString() : String
+		return '$this';
 
-	public static inline function ushr( a : Int64, b : Int ) : Int64 {
-		return cast(cast(a, NativeUInt64) >> b, NativeInt64).ofNative();
-	}
+	@:op(-A) public static function neg( x : Int64 ) : Int64
+		return -x.val;
 
-	public static inline function and( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() & b.asNative()).ofNative();
-	}
+	@:op(++A) private inline function preIncrement() : Int64
+		return ++this;
 
-	public static inline function or( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() | b.asNative()).ofNative();
-	}
+	@:op(A++) private inline function postIncrement() : Int64
+		return this++;
 
-	public static inline function xor( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() ^ b.asNative()).ofNative();
-	}
+	@:op(--A) private inline function preDecrement() : Int64
+		return --this;
 
-	public static inline function neg( a : Int64 ) : Int64
-	{
-		return (-(a.asNative())).ofNative();
-	}
+	@:op(A--) private inline function postDecrement() : Int64
+		return this--;
+	
+	@:op(A + B) public static inline function add( a : Int64, b : Int64 ) : Int64
+		return a.val + b.val;
 
-	public static inline function isNeg( a : Int64 ) : Bool
-	{
-		return (a.asNative() < 0.mkNative());
-	}
+	@:op(A + B) @:commutative private static inline function addInt( a : Int64, b : Int ) : Int64
+		return a.val + b;
 
-	public static inline function isZero( a : Int64 ) : Bool
-	{
-		return (a.asNative() == 0.mkNative());
-	}
+	@:op(A - B) public static inline function sub( a : Int64, b : Int64 ) : Int64
+		return a.val - b.val;
 
-	public static inline function compare( a : Int64, b : Int64 ) : Int
-	{
-		return (a.asNative() < b.asNative()) ? -1 : (a.asNative() > b.asNative()) ? 1 : 0;
-	}
+	@:op(A - B) private static inline function subInt( a : Int64, b : Int ) : Int64
+		return a.val - b;
 
-	public static function ucompare( a : Int64, b : Int64 ) : Int
-	{
-		var a:NativeUInt64 = cast a,
-				b:NativeUInt64 = cast b;
-		return (a < b) ? -1 : (a > b) ? 1 : 0;
-	}
+	@:op(A - B) private static inline function intSub( a : Int, b : Int64 ) : Int64
+		return a - b.val;
 
-	public static inline function toStr( a : Int64 ) : String {
-		return a + "";
-	}
+	@:op(A * B) public static inline function mul( a : Int64, b : Int64 ) : Int64
+		return a.val * b.val;
+
+	@:op(A * B) @:commutative private static inline function mulInt( a : Int64, b : Int ) : Int64
+		return a.val * b;
+
+	@:op(A / B) public static inline function div( a : Int64, b : Int64 ) : Int64
+		return a.val / b.val;
+
+	@:op(A / B) private static inline function divInt( a : Int64, b : Int ) : Int64
+		return a.val / b;
+
+	@:op(A / B) private static inline function intDiv( a : Int, b : Int64 ) : Int64
+		return a / b.val;
+
+	@:op(A % B) public static inline function mod( a : Int64, b : Int64 ) : Int64
+		return a.val % b.val;
+
+	@:op(A % B) private static inline function modInt( a : Int64, b : Int ) : Int64
+		return a.val % b;
+
+	@:op(A % B) private static inline function intMod( a : Int, b : Int64 ) : Int64
+		return a % b.val;
+
+	@:op(A == B) public static inline function eq( a : Int64, b : Int64 ) : Bool
+		return a.val == b.val;
+
+	@:op(A == B) @:commutative private static inline function eqInt( a : Int64, b : Int ) : Bool
+		return a.val == b;
+
+	@:op(A != B) public static inline function neq( a : Int64, b : Int64 ) : Bool
+		return a.val != b.val;
+
+	@:op(A != B) @:commutative private static inline function neqInt( a : Int64, b : Int ) : Bool
+		return a.val != b;
+
+	@:op(A < B) private static inline function lt( a : Int64, b : Int64 ) : Bool
+		return a.val < b.val;
+
+	@:op(A < B) private static inline function ltInt( a : Int64, b : Int ) : Bool
+		return a.val < b;
+
+	@:op(A < B) private static inline function intLt( a : Int, b : Int64 ) : Bool
+		return a < b.val;
+
+	@:op(A <= B) private static inline function lte( a : Int64, b : Int64 ) : Bool
+		return a.val <= b.val;
+
+	@:op(A <= B) private static inline function lteInt( a : Int64, b : Int ) : Bool
+		return a.val <= b;
+
+	@:op(A <= B) private static inline function intLte( a : Int, b : Int64 ) : Bool
+		return a <= b.val;
+
+	@:op(A > B) private static inline function gt( a : Int64, b : Int64 ) : Bool
+		return a.val > b.val;
+
+	@:op(A > B) private static inline function gtInt( a : Int64, b : Int ) : Bool
+		return a.val > b;
+
+	@:op(A > B) private static inline function intGt( a : Int, b : Int64 ) : Bool
+		return a > b.val;
+
+	@:op(A >= B) private static inline function gte( a : Int64, b : Int64 ) : Bool
+		return a.val >= b.val;
+
+	@:op(A >= B) private static inline function gteInt( a : Int64, b : Int ) : Bool
+		return a.val >= b;
+
+	@:op(A >= B) private static inline function intGte( a : Int, b : Int64 ) : Bool
+		return a >= b.val;
+
+	@:op(~A) private static inline function complement( x : Int64 ) : Int64
+		return ~x.val;
+
+	@:op(A & B) public static inline function and( a : Int64, b : Int64 ) : Int64
+		return a.val & b.val;
+
+	@:op(A | B) public static inline function or( a : Int64, b : Int64 ) : Int64
+		return a.val | b.val;
+
+	@:op(A ^ B) public static inline function xor( a : Int64, b : Int64 ) : Int64
+		return a.val ^ b.val;
+
+	@:op(A << B) public static inline function shl( a : Int64, b : Int ) : Int64
+		return a.val << b;
+
+	@:op(A >> B) public static inline function shr( a : Int64, b : Int ) : Int64
+		return a.val >> b;
+
+	@:op(A >>> B) public static inline function ushr( a : Int64, b : Int ) : Int64
+		return cast ( (a.val : cs.StdTypes.UInt64) >> b );
 }

+ 352 - 185
std/haxe/Int64.hx

@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2005-2012 Haxe Foundation
+ * Copyright (C)2005-2013 Haxe Foundation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -21,77 +21,112 @@
  */
 package haxe;
 
-class Int64 {
+using haxe.Int64;
 
-	var high : Int;
-	var low : Int;
+ /**
+	A cross-platform signed 64-bit integer.
+	Int64 instances can be created from two 32-bit words using `Int64.make()`.
+ **/
+abstract Int64(__Int64) from __Int64 to __Int64
+{
+	private inline function new( x : __Int64 )
+		this = x;
 
-	inline function new(high, low) {
-		this.high = i32(high);
-		this.low = i32(low);
-	}
+	/**
+		Makes a copy of `this` Int64.
+	**/
+	public inline function copy():Int64
+		return make( high, low );
 
-	#if php
-	/*
-		private function to correctly handle 32-bit integer overflow on php
-		see: http://stackoverflow.com/questions/300840/force-php-integer-overflow
-	*/
-	private static function i32php(value:Int):Int {
-			value = (value & untyped __php__("0xFFFFFFFF"));
- 		    if ( (value & untyped __php__("0x80000000"))!=0 )
-		        value = -(((~value) & untyped __php__("0xFFFFFFFF")) + 1);
-		    return value;
-	}
-	#end
-
-	/*
-		private function to correctly handle 32-bit ushr on php
-		see: https://github.com/HaxeFoundation/haxe/commit/1a878aa90708040a41b0dd59f518d83b09ede209
-	*/
-	private static inline function ushr32(v:Int,n:Int):Int {
-		#if php
-		 	return (v >> n) & (untyped __php__("0x7fffffff") >> (n-1));
-		#else
-			return v>>>n;
-		#end
+	/**
+		Construct an Int64 from two 32-bit words `high` and `low`.
+	**/
+	public static inline function make( high:Int32, low:Int32 ) : Int64
+		return new Int64( new __Int64(high, low) );
+
+	/**
+		Returns an Int64 with the value of the Int `x`.
+		`x` is sign-extended to fill 64 bits.
+	**/
+	@:from public static inline function ofInt( x : Int ) : Int64
+		return make( x >> 31, x );
+
+	/**
+		Returns an Int with the value of the Int64 `x`.
+		Throws an exception  if `x` cannot be represented in 32 bits.
+	**/
+	public static inline function toInt( x : Int64 ) : Int {
+		if( x.high != x.low >> 31 )
+			throw "Overflow";
+
+		return x.low;
 	}
 
-	@:extern static inline function i32(i) {
-		#if (js || flash8)
-			return i | 0;
-		#elseif php
-			return i32php(i); // handle overflow of 32-bit integers correctly
-		#elseif python
-			return (i + python.Syntax.opPow(2, 31)) % python.Syntax.opPow(2, 32) - python.Syntax.opPow(2, 31);
-		#else
-			return i;
-		#end
+	/**
+		Returns the high 32-bit word of `x`.
+	**/
+	public static inline function getHigh( x : Int64 ) : Int32
+		return x.high;
+
+	/**
+		Returns the low 32-bit word of `x`.
+	**/
+	public static inline function getLow( x : Int64 ) : Int32
+		return x.low;
+
+	/**
+		Returns `true` if `x` is less than zero.
+	**/
+	public static inline function isNeg( x : Int64) : Bool
+		return x.high < 0;
+
+	/**
+		Returns `true` if `x` is exactly zero.
+	**/
+	public static inline function isZero( x : Int64 ) : Bool
+		return x == 0;
+
+	/**
+		Compares `a` and `b` in signed mode.
+		Returns a negative value if `a < b`, positive if `a > b`,
+		or 0 if `a == b`.
+	**/
+	public static inline function compare( a : Int64, b : Int64 ) : Int {
+		var v = a.high - b.high;
+		v = if( v != 0 ) v else Int32.ucompare(a.low, b.low);
+		return a.high < 0 ? (b.high < 0 ? v : -1) : (b.high >= 0 ? v : 1);
 	}
 
-	@:extern static inline function i32mul(a:Int,b:Int) {
-		#if (php || js || flash8)
-		/*
-			We can't simply use i32(a*b) since we might overflow (52 bits precision in doubles)
-		*/
-		return i32(i32((a * (b >>> 16)) << 16) + (a * (b&0xFFFF)));
-		#else
-		return a * b;
-		#end
+	/**
+		Compares `a` and `b` in unsigned mode.
+		Returns a negative value if `a < b`, positive if `a > b`,
+		or 0 if `a == b`.
+	**/
+	public static inline function ucompare( a : Int64, b : Int64 ) : Int {
+		var v = Int32.ucompare(a.high, b.high);
+		return if( v != 0 ) v else Int32.ucompare(a.low, b.low);
 	}
 
-	#if as3 public #end function toString() {
-		if ((high|low) == 0 )
+	/**
+		Returns a signed decimal `String` representation of `x`.
+	**/
+	public static inline function toStr(x:Int64) : String
+		return x.toString();
+
+	#if as3 public #else private #end function toString() : String
+	{
+		var i : Int64 = cast this;
+		if ( i == 0 )
 			return "0";
 		var str = "";
 		var neg = false;
-		var i = this;
-		if( isNeg(i) ) {
+		if( i.isNeg() ) {
 			neg = true;
-			i = Int64.neg(i);
+			i = -i;
 		}
-		var ten = ofInt(10);
-		while( !isZero(i) ) {
-			var r = divMod(i, ten);
+		var ten : Int64 = 10;
+		while( i != 0 ) {
+			var r = i.divMod( ten );
 			str = r.modulus.low + str;
 			i = r.quotient;
 		}
@@ -99,176 +134,308 @@ class Int64 {
 		return str;
 	}
 
-	public static inline function make( high : Int, low : Int ) : Int64 {
-		return new Int64(high, low);
+	/**
+		Performs signed integer divison of `dividend` by `divisor`.
+		Returns `{ quotient : Int64, modulus : Int64 }`.
+	**/
+	public static function divMod( dividend : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 }
+	{
+		// Handle special cases of 0 and 1
+		if( divisor.high == 0 )
+		{
+			switch( divisor.low ) {
+				case 0: throw "divide by zero";
+				case 1: return { quotient : dividend.copy(), modulus : 0 };
+			}
+		}
+
+		var divSign = dividend.isNeg() != divisor.isNeg();
+
+		var modulus = dividend.isNeg() ? -dividend : dividend.copy();
+		divisor = divisor.isNeg() ? -divisor : divisor;
+
+		var quotient : Int64 = 0;
+		var mask : Int64 = 1;
+
+		while( !divisor.isNeg() ) {
+			var cmp = ucompare( divisor, modulus );
+			divisor <<= 1;
+			mask <<= 1;
+			if( cmp >= 0 ) break;
+		}
+
+		while( mask != 0 ) {
+			if( ucompare(modulus, divisor) >= 0 ) {
+				quotient |= mask;
+				modulus -= divisor;
+			}
+			mask >>>= 1;
+			divisor >>>= 1;
+		}
+
+		if( divSign ) quotient = -quotient;
+		if( dividend.isNeg() ) modulus = -modulus;
+
+		return {
+			quotient : quotient,
+			modulus  : modulus
+		};
 	}
 
-	public static inline function ofInt( x : Int ) : Int64 {
-		return new Int64(x >> 31,x);
+	/**
+		Returns the negative of `x`.
+	**/
+	@:op(-A) public static inline function neg( x : Int64 ) : Int64 {
+		var high = ~x.high;
+		var low = -x.low;
+		if( low == 0 )
+			high++;
+		return make( high, low );
 	}
 
-	public static function toInt( x : Int64 ) : Int {
-		if( x.high != 0 ) {
-			if( x.high < 0 )
-				return -toInt(neg(x));
-			throw "Overflow";
-		}
-		return x.low;
+	@:op(++A) private inline function preIncrement() : Int64 {
+		this.low++;
+		if( this.low == 0 ) this.high++;
+		return cast this;
 	}
 
-	public static function getLow( x : Int64 ) : Int {
-		return x.low;
+	@:op(A++) private inline function postIncrement() : Int64 {
+		var ret = copy();
+		preIncrement();
+		return ret;
 	}
 
-	public static function getHigh( x : Int64 ) : Int {
-		return x.high;
+	@:op(--A) private inline function preDecrement() : Int64 {
+		if( this.low == 0 ) this.high--;
+		this.low--;
+		return cast this;
 	}
 
-	public static function add( a : Int64, b : Int64 ) : Int64 {
-		var high = i32(a.high + b.high);
-		var low = i32(a.low + b.low);
-		if( uicompare(low,a.low) < 0 )
-			high++;
-		return new Int64(high, low);
+	@:op(A--) private inline function postDecrement() : Int64 {
+		var ret = copy();
+		preDecrement();
+		return ret;
 	}
 
-	public static function sub( a : Int64, b : Int64 ) : Int64 {
-		var high = i32(a.high - b.high); // i32() call required to match add
-		var low = i32(a.low - b.low); // i32() call required to match add
-		if( uicompare(a.low,b.low) < 0 )
-			high--;
-		return new Int64(high, low);
+	/**
+		Returns the sum of `a` and `b`.
+	**/
+	@:op(A + B) public static inline function add( a : Int64, b : Int64 ) : Int64 {
+		var high = a.high + b.high;
+		var low = a.low + b.low;
+		if( Int32.ucompare( low, a.low ) < 0 ) high++;
+		return make( high, low );
 	}
 
-	public static function mul( a : Int64, b : Int64 ) : Int64 {
+	@:op(A + B) @:commutative private static inline function addInt( a : Int64, b : Int ) : Int64
+		return add( a, b );
+
+	/**
+		Returns `a` minus `b`.
+	**/
+	@:op(A - B) public static inline function sub( a : Int64, b : Int64 ) : Int64 {
+		var high = a.high - b.high;
+		var low = a.low - b.low;
+		if( Int32.ucompare( a.low, b.low ) < 0 ) high--;
+        return make( high, low );
+	}
+
+	@:op(A - B) private static inline function subInt( a : Int64, b : Int ) : Int64
+		return sub( a, b );
+
+	@:op(A - B) private static inline function intSub( a : Int, b : Int64 ) : Int64
+		return sub( a, b );
+
+	/**
+		Returns the product of `a` and `b`.
+	**/
+	@:op(A * B) public static inline function mul( a : Int64, b : Int64 ) : Int64 {
 		var mask = 0xFFFF;
-		var al = a.low & mask, ah = ushr32(a.low , 16);
-		var bl = b.low & mask, bh = ushr32(b.low , 16);
+		var al = a.low & mask, ah = a.low >>> 16;
+		var bl = b.low & mask, bh = b.low >>> 16;
 		var p00 = al * bl;
 		var p10 = ah * bl;
 		var p01 = al * bh;
 		var p11 = ah * bh;
 		var low = p00;
-		var high = i32(p11 + ushr32(p01 , 16) + ushr32(p10 , 16));
-		p01 = i32(p01 << 16); low = i32(low + p01); if( uicompare(low, p01) < 0 ) high = i32(high + 1);
-		p10 = i32(p10 << 16); low = i32(low + p10); if( uicompare(low, p10) < 0 ) high = i32(high + 1);
-		high = i32(high + i32mul(a.low,b.high));
-		high = i32(high + i32mul(a.high,b.low));
-		return new Int64(high, low);
+		var high = p11 + (p01 >>> 16) + (p10 >>> 16);
+		p01 <<= 16;
+		low += p01;
+		if( Int32.ucompare(low, p01) < 0 ) high++;
+		p10 <<= 16;
+		low += p10;
+		if( Int32.ucompare(low, p10) < 0 ) high++;
+		high += a.low * b.high + a.high * b.low;
+		return make( high, low );
 	}
 
-	static function divMod( modulus : Int64, divisor : Int64 ) {
-		var quotient = new Int64(0, 0);
-		var mask = new Int64(0, 1);
-		divisor = new Int64(divisor.high, divisor.low);
-		while( divisor.high >= 0 ) {
-			var cmp = ucompare(divisor, modulus);
-			divisor.high = i32( i32(divisor.high << 1) | ushr32(divisor.low , 31) );
-			divisor.low = i32(divisor.low << 1);
-			mask.high = i32( i32(mask.high << 1) | ushr32(mask.low , 31) );
-			mask.low = i32(mask.low << 1);
-			if( cmp >= 0 ) break;
-		}
-		while( i32(mask.low | mask.high) != 0 ) {
-			if( ucompare(modulus, divisor) >= 0 ) {
-				quotient.high= i32(quotient.high | mask.high);
-				quotient.low= i32(quotient.low | mask.low);
-				modulus = sub(modulus,divisor);
-			}
-			mask.low = i32( ushr32(mask.low , 1) | i32(mask.high << 31) );
-			mask.high = ushr32(mask.high , 1);
+	@:op(A * B) @:commutative private static inline function mulInt( a : Int64, b : Int ) : Int64
+		return mul( a, b );
 
-			divisor.low = i32( ushr32(divisor.low , 1) | i32(divisor.high << 31) );
-			divisor.high = ushr32(divisor.high , 1);
-		}
-		return { quotient : quotient, modulus : modulus };
-	}
+	/**
+		Returns the quotient of `a` divided by `b`.
+	**/
+	@:op(A / B) public static inline function div( a : Int64, b : Int64 ) : Int64
+		return divMod(a, b).quotient;
 
-	public static function div( a : Int64, b : Int64 ) : Int64 {
-		if(b.high==0) // handle special cases of 0 and 1
-			switch(b.low) {
-			case 0:	throw "divide by zero";
-			case 1: return new Int64(a.high,a.low);
-			}
-		var sign = ((a.high<0) || (b.high<0)) && (!( (a.high<0) && (b.high<0))); // make sure we get the correct sign
-		if( a.high < 0 ) a = neg(a);
-		if( b.high < 0 ) b = neg(b);
-		var q = divMod(a, b).quotient;
-		return sign ? neg(q) : q;
-	}
+	@:op(A / B) private static inline function divInt( a : Int64, b : Int ) : Int64
+		return div( a, b );
 
-	public static function mod( a : Int64, b : Int64 ) : Int64 {
-		if(b.high==0) // handle special cases of 0 and 1
-			switch(b.low) {
-			case 0:	throw "modulus by zero";
-			case 1: return ofInt(0);
-			}
-		var sign = a.high<0; // the sign of a modulus is the sign of the value being mod'ed
-		if( a.high < 0 ) a = neg(a);
-		if( b.high < 0 ) b = neg(b);
-		var m = divMod(a, b).modulus;
-		return sign ? neg(m) : m;
-	}
+	@:op(A / B) private static inline function intDiv( a : Int, b : Int64 ) : Int64
+		return div( a, b ).toInt();
 
-	public static inline function shl( a : Int64, b : Int ) : Int64 {
-		return if( b & 63 == 0 ) a else if( b & 63 < 32 ) new Int64( (a.high << b) | ushr32(a.low, i32(32-(b&63))), a.low << b ) else new Int64( a.low << i32(b - 32), 0 );
-	}
+	/**
+		Returns the modulus of `a` divided by `b`.
+	**/
+	@:op(A % B) public static inline function mod( a : Int64, b : Int64 ) : Int64
+		return divMod(a, b).modulus;
 
-	public static inline function shr( a : Int64, b : Int ) : Int64 {
-		return if( b & 63 == 0 ) a else if( b & 63 < 32 ) new Int64( a.high >> b, ushr32(a.low,b) | (a.high << i32(32 - (b&63))) ) else new Int64( a.high >> 31, a.high >> i32(b - 32) );
-	}
+	@:op(A % B) private static inline function modInt( a : Int64, b : Int ) : Int64
+		return mod( a, b ).toInt();
 
-	public static inline function ushr( a : Int64, b : Int ) : Int64 {
-		return if( b & 63 == 0 ) a else if( b & 63 < 32 ) new Int64( ushr32(a.high, b), ushr32(a.low, b) | (a.high << i32(32 - (b&63))) ) else new Int64( 0, ushr32(a.high, i32(b - 32)) );
-	}
+	@:op(A % B) private static inline function intMod( a : Int, b : Int64 ) : Int64
+		return mod( a, b ).toInt();
 
-	public static inline function and( a : Int64, b : Int64 ) : Int64 {
-		return new Int64( a.high & b.high, a.low & b.low );
-	}
+	/**
+		Returns `true` if `a` is equal to `b`.
+	**/
+	@:op(A == B) public static inline function eq( a : Int64, b : Int64 ) : Bool
+		return a.high == b.high && a.low == b.low;
 
-	public static inline function or( a : Int64, b : Int64 ) : Int64 {
-		return new Int64( a.high | b.high, a.low | b.low );
-	}
+	@:op(A == B) @:commutative private static inline function eqInt( a : Int64, b : Int ) : Bool
+		return eq( a, b );
 
-	public static inline function xor( a : Int64, b : Int64 ) : Int64 {
-		return new Int64( a.high ^ b.high, a.low ^ b.low );
-	}
+	/**
+		Returns `true` if `a` is not equal to `b`.
+	**/
+	@:op(A != B) public static inline function neq( a : Int64, b : Int64 ) : Bool
+		return a.high != b.high || a.low != b.low;
 
-	public static inline function neg( a : Int64 ) : Int64 {
-		var high = i32(~a.high);
-		var low = i32(-a.low);
-		if( low == 0 )
-			high++;
-		return new Int64(high,low);
-	}
+	@:op(A != B) @:commutative private static inline function neqInt( a : Int64, b : Int ) : Bool
+		return neq(a, b);
 
-	public static inline function isNeg( a : Int64 ) : Bool {
-		return a.high < 0;
-	}
+	@:op(A < B) private static inline function lt( a : Int64, b : Int64 ) : Bool
+		return compare(a, b) < 0;
 
-	public static inline function isZero( a : Int64 ) : Bool {
-		return (a.high | a.low) == 0;
-	}
+	@:op(A < B) private static inline function ltInt( a : Int64, b : Int ) : Bool
+		return lt(a, b);
+
+	@:op(A < B) private static inline function intLt( a : Int, b : Int64 ) : Bool
+		return lt(a, b);
 
-	static function uicompare( a : Int, b : Int ) {
-		return a < 0 ? (b < 0 ? i32(~b - ~a) : 1) : (b < 0 ? -1 : i32(a - b));
+	@:op(A <= B) private static inline function lte( a : Int64, b : Int64 ) : Bool
+		return compare(a, b) <= 0;
+
+	@:op(A <= B) private static inline function lteInt( a : Int64, b : Int ) : Bool
+		return lte(a, b);
+
+	@:op(A <= B) private static inline function intLte( a : Int, b : Int64 ) : Bool
+		return lte(a, b);
+
+	@:op(A > B) private static inline function gt( a : Int64, b : Int64 ) : Bool
+		return compare(a, b) > 0;
+
+	@:op(A > B) private static inline function gtInt( a : Int64, b : Int ) : Bool
+		return gt(a, b);
+
+	@:op(A > B) private static inline function intGt( a : Int, b : Int64 ) : Bool
+		return gt( a, b );
+
+	@:op(A >= B) private static inline function gte( a : Int64, b : Int64 ) : Bool
+		return compare(a, b) >= 0;
+
+	@:op(A >= B) private static inline function gteInt( a : Int64, b : Int ) : Bool
+		return gte(a, b);
+
+	@:op(A >= B) private static inline function intGte( a : Int, b : Int64 ) : Bool
+		return gte(a, b);
+
+	/**
+		Returns the bitwise NOT of `a`.
+	**/
+	@:op(~A) private static inline function complement( a : Int64 ) : Int64
+		return make( ~a.high, ~a.low );
+
+	/**
+		Returns the bitwise AND of `a` and `b`.
+	**/
+	@:op(A & B) public static inline function and( a : Int64, b : Int64 ) : Int64
+		return make( a.high & b.high, a.low & b.low );
+
+	/**
+		Returns the bitwise OR of `a` and `b`.
+	**/
+	@:op(A | B) public static inline function or( a : Int64, b : Int64 ) : Int64
+		return make( a.high | b.high, a.low | b.low );
+
+	/**
+		Returns the bitwise XOR of `a` and `b`.
+	**/
+	@:op(A ^ B) public static inline function xor( a : Int64, b : Int64 ) : Int64
+		return make( a.high ^ b.high, a.low ^ b.low );
+
+	/**
+		Returns `a` left-shifted by `b` bits.
+	**/
+	@:op(A << B) public static inline function shl( a : Int64, b : Int ) : Int64 {
+		b &= 63;
+		return if( b == 0 ) a.copy()
+			else if( b < 32 ) make( (a.high << b) | (a.low >>> (32-b)), a.low << b)
+			else make( a.low << (b-32), 0 );
 	}
 
-	public static inline function compare( a : Int64, b : Int64 ) : Int {
-		var v = i32(a.high - b.high);
-		return if( v != 0 ) v else uicompare(a.low,b.low);
+	/**
+		Returns `a` right-shifted by `b` bits in signed mode.
+		`a` is sign-extended.
+	**/
+	@:op(A >> B) public static inline function shr( a : Int64, b : Int) : Int64 {
+		b &= 63;
+		return if( b == 0 ) a.copy()
+			else if( b < 32 ) make( a.high >> b, (a.high << (32-b)) | (a.low >>> b) )
+			else make( a.high >> 31, a.high >> (b - 32) );
 	}
 
 	/**
-		Compare two Int64 in unsigned mode.
+		Returns `a` right-shifted by `b` bits in unsigned mode.
+		`a` is padded with zeroes.
 	**/
-	public static inline function ucompare( a : Int64, b : Int64 ) : Int {
-		var v = uicompare(a.high,b.high);
-		return if( v != 0 ) v else uicompare(a.low, b.low);
+	@:op(A >>> B) public static inline function ushr( a : Int64, b : Int ) : Int64 {
+		b &= 63;
+		return if( b == 0 ) a.copy()
+			else if( b < 32 ) make( a.high >>> b, (a.high << (32-b)) | (a.low >>> b) )
+			else make( 0, a.high >>> (b - 32) );
 	}
 
-	public static inline function toStr( a : Int64 ) : String {
-		return a.toString();
+	private var high(get,set) : Int32;
+	private inline function get_high() return this.high;
+	private inline function set_high(x) return this.high = x;
+
+	private var low(get,set) : Int32;
+	private inline function get_low() return this.low;
+	private inline function set_low(x) return this.low = x;
+}
+
+/**
+  * This typedef will fool @:coreApi into thinking that we are using
+  * the same underlying type, even though it might be different on
+  * specific platforms.
+  */
+private typedef __Int64 = ___Int64;
+
+private class ___Int64 {
+	public var high : Int32;
+	public var low : Int32;
+
+	public inline function new( high, low ) {
+		this.high = high;
+		this.low = low;
 	}
 
+	/**
+		We also define toString here to ensure we always get a pretty string
+		when tracing or calling Std.string. This tends not to happen when
+		toString is only in the abstract.
+	**/
+	public function toString() : String
+		return Int64.toStr( cast this );
 }

+ 2 - 2
std/haxe/io/FPHelper.hx

@@ -257,8 +257,8 @@ class FPHelper {
 			helper.position = 0;
 			var i64 = i64tmp;
 			@:privateAccess {
-				i64.low = helper.readUnsignedInt();
-				i64.high = helper.readUnsignedInt();
+				i64.low = cast helper.readUnsignedInt();
+				i64.high = cast helper.readUnsignedInt();
 			}
 			return i64;
 		#elseif php

+ 6 - 1
std/java/StdTypes.hx

@@ -24,7 +24,7 @@ package java;
 @:notNull @:runtimeValue @:coreType abstract Int8 from Int {}
 @:notNull @:runtimeValue @:coreType abstract Int16 from Int {}
 @:notNull @:runtimeValue @:coreType abstract Char16 from Int {}
-@:notNull @:runtimeValue @:coreType abstract Int64 from Int from Float from haxe.Int64
+@:notNull @:runtimeValue @:coreType abstract Int64 from Int from Float
 {
 	@:op(A+B) public static function addI(lhs:Int64, rhs:Int):Int64;
 	@:op(A+B) public static function add(lhs:Int64, rhs:Int64):Int64;
@@ -56,4 +56,9 @@ package java;
 
 	@:op(~A) public static function bneg(t:Int64):Int64;
 	@:op(-A) public static function neg(t:Int64):Int64;
+
+	@:op(++A) public static function preIncrement(t:Int64):Int64;
+	@:op(A++) public static function postIncrement(t:Int64):Int64;
+	@:op(--A) public static function preDecrement(t:Int64):Int64;
+	@:op(A--) public static function postDecrement(t:Int64):Int64;
 }

+ 154 - 87
std/java/_std/haxe/Int64.hx

@@ -21,122 +21,189 @@
  */
 package haxe;
 using haxe.Int64;
-import java.StdTypes.Int64 in NativeInt64;
+
+private typedef __Int64 = java.StdTypes.Int64;
 
 @:coreApi
-@:nativeGen class Int64
+abstract Int64(__Int64) from __Int64 to __Int64
 {
-	@:extern private static inline function asNative(i:Int64):NativeInt64 return untyped i;
-	@:extern private static inline function ofNative(i:NativeInt64):Int64 return untyped i;
-	@:extern private static inline function mkNative(i:Int):NativeInt64 return cast i;
 
-	public static inline function make( high : Int, low : Int ) : Int64
-	{
-		return ((cast(high, NativeInt64) << 32 ) | (low & untyped __java__('0xffffffffL'))).ofNative();
-	}
+	public static inline function make( high : Int32, low : Int32 ) : Int64
+		return new Int64( (cast(high, __Int64) << 32) | (cast(low, __Int64)& untyped __java__('0xffffffffL')) );
 
-	public static inline function getLow( x : Int64 ) : Int
-	{
-		return cast (x.asNative() & (untyped __java__("0xFFFFFFFFL")), Int);
-	}
+	private inline function new(x : __Int64)
+		this = x;
 
-	public static inline function getHigh( x : Int64 ) : Int {
-		return cast(cast(x,NativeInt64) >>> 32, Int);
-	}
+	private var val( get, set ) : __Int64;
+	inline function get_val() : __Int64 return this;
+	inline function set_val( x : __Int64 ) : __Int64 return this = x;
 
-	public static inline function ofInt( x : Int ) : Int64 {
-		return cast x;
-	}
+	public inline function copy():Int64
+		return new Int64( this );
 
-	public static inline function toInt( x : Int64 ) : Int
-	{
+	@:from public static inline function ofInt( x : Int ) : Int64
 		return cast x;
-	}
 
-	public static inline function add( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() + b.asNative()).ofNative();
+	public static inline function toInt( x : Int64 ) : Int {
+		if( x.val < 0x80000000 || x.val > 0x7FFFFFFF )
+			throw "Overflow";
+		return cast x.val;
 	}
 
-	public static inline function sub( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() - b.asNative()).ofNative();
-	}
+	public static inline function getHigh( x : Int64 ) : Int32
+		return cast( x.val >> 32 );
 
-	public static inline function mul( a : Int64, b : Int64 ) : Int64 {
-		return (a.asNative() * b.asNative()).ofNative();
-	}
+	public static inline function getLow( x : Int64 ) : Int32
+		return cast( x.val );
 
-	static function divMod( modulus : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 }
+	public static inline function isNeg( x : Int64 ) : Bool
+		return x.val < 0;
+
+	public static inline function isZero( x : Int64 ) : Bool
+		return x.val == 0;
+
+	public static inline function compare( a : Int64, b : Int64 ) : Int
 	{
-		var q:Int64 = (modulus.asNative() / divisor.asNative()).ofNative();
-		var m:Int64 = (modulus.asNative() % divisor.asNative()).ofNative();
-		return { quotient : q, modulus : m };
+		if( a.val < b.val ) return -1;
+		if( a.val > b.val ) return 1;
+		return 0;
 	}
 
-	public static inline function div( a : Int64, b : Int64 ) : Int64 {
-		return (a.asNative() / b.asNative()).ofNative();
+	public static inline function ucompare( a : Int64, b : Int64 ) : Int {
+		if( a.val < 0 )
+			return ( b.val < 0 ) ? compare( a, b ) : 1;
+		return ( b.val < 0 ) ? -1 : compare( a, b );
 	}
 
-	public static inline function mod( a : Int64, b : Int64 ) : Int64 {
-		return (a.asNative() % b.asNative()).ofNative();
-	}
+	public static inline function toStr( x : Int64 ) : String
+		return '${x.val}';
 
-	public static inline function shl( a : Int64, b : Int ) : Int64 {
-		return (a.asNative() << b).ofNative();
-	}
+	public static inline function divMod( dividend : Int64, divisor : Int64 ) : { quotient : Int64, modulus : Int64 }
+		return { quotient: dividend / divisor, modulus: dividend % divisor };
 
-	public static inline function shr( a : Int64, b : Int ) : Int64 {
-		return (a.asNative() >> b).ofNative();
-	}
+	private inline function toString() : String
+		return '$this';
 
-	public static inline function ushr( a : Int64, b : Int ) : Int64 {
-		return ( a.asNative() >>> b).ofNative();
-	}
+	@:op(-A) public static function neg( x : Int64 ) : Int64
+		return -x.val;
 
-	public static inline function and( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() & b.asNative()).ofNative();
-	}
+	@:op(++A) private inline function preIncrement() : Int64
+		return ++this;
 
-	public static inline function or( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() | b.asNative()).ofNative();
-	}
+	@:op(A++) private inline function postIncrement() : Int64
+		return this++;
 
-	public static inline function xor( a : Int64, b : Int64 ) : Int64
-	{
-		return (a.asNative() ^ b.asNative()).ofNative();
-	}
+	@:op(--A) private inline function preDecrement() : Int64
+		return --this;
 
-	public static inline function neg( a : Int64 ) : Int64
-	{
-		return (-(a.asNative())).ofNative();
-	}
+	@:op(A--) private inline function postDecrement() : Int64
+		return this--;
+	
+	@:op(A + B) public static inline function add( a : Int64, b : Int64 ) : Int64
+		return a.val + b.val;
 
-	public static inline function isNeg( a : Int64 ) : Bool
-	{
-		return (a.asNative() < 0.mkNative());
-	}
+	@:op(A + B) @:commutative private static inline function addInt( a : Int64, b : Int ) : Int64
+		return a.val + b;
 
-	public static inline function isZero( a : Int64 ) : Bool
-	{
-		return (a.asNative() == 0.mkNative());
-	}
+	@:op(A - B) public static inline function sub( a : Int64, b : Int64 ) : Int64
+		return a.val - b.val;
 
-	public static inline function compare( a : Int64, b : Int64 ) : Int
-	{
-		return (a.asNative() < b.asNative()) ? -1 : (a.asNative() > b.asNative()) ? 1 : 0;
-	}
+	@:op(A - B) private static inline function subInt( a : Int64, b : Int ) : Int64
+		return a.val - b;
 
-	public static function ucompare( a : Int64, b : Int64 ) : Int
-	{
-		if (a.asNative() < 0.mkNative())
-			return (b.asNative() < 0.mkNative()) ? compare( (~(a.asNative())).ofNative(), (~(b.asNative())).ofNative()) : 1;
-		return (b.asNative() < 0.mkNative()) ? -1 : compare(a, b);
-	}
+	@:op(A - B) private static inline function intSub( a : Int, b : Int64 ) : Int64
+		return a - b.val;
 
-	public static inline function toStr( a : Int64 ) : String {
-		return a + "";
-	}
+	@:op(A * B) public static inline function mul( a : Int64, b : Int64 ) : Int64
+		return a.val * b.val;
+
+	@:op(A * B) @:commutative private static inline function mulInt( a : Int64, b : Int ) : Int64
+		return a.val * b;
+
+	@:op(A / B) public static inline function div( a : Int64, b : Int64 ) : Int64
+		return a.val / b.val;
+
+	@:op(A / B) private static inline function divInt( a : Int64, b : Int ) : Int64
+		return a.val / b;
+
+	@:op(A / B) private static inline function intDiv( a : Int, b : Int64 ) : Int64
+		return a / b.val;
+
+	@:op(A % B) public static inline function mod( a : Int64, b : Int64 ) : Int64
+		return a.val % b.val;
+
+	@:op(A % B) private static inline function modInt( a : Int64, b : Int ) : Int64
+		return a.val % b;
+
+	@:op(A % B) private static inline function intMod( a : Int, b : Int64 ) : Int64
+		return a % b.val;
+
+	@:op(A == B) public static inline function eq( a : Int64, b : Int64 ) : Bool
+		return a.val == b.val;
+
+	@:op(A == B) @:commutative private static inline function eqInt( a : Int64, b : Int ) : Bool
+		return a.val == b;
+
+	@:op(A != B) public static inline function neq( a : Int64, b : Int64 ) : Bool
+		return a.val != b.val;
+
+	@:op(A != B) @:commutative private static inline function neqInt( a : Int64, b : Int ) : Bool
+		return a.val != b;
+
+	@:op(A < B) private static inline function lt( a : Int64, b : Int64 ) : Bool
+		return a.val < b.val;
+
+	@:op(A < B) private static inline function ltInt( a : Int64, b : Int ) : Bool
+		return a.val < b;
+
+	@:op(A < B) private static inline function intLt( a : Int, b : Int64 ) : Bool
+		return a < b.val;
+
+	@:op(A <= B) private static inline function lte( a : Int64, b : Int64 ) : Bool
+		return a.val <= b.val;
+
+	@:op(A <= B) private static inline function lteInt( a : Int64, b : Int ) : Bool
+		return a.val <= b;
+
+	@:op(A <= B) private static inline function intLte( a : Int, b : Int64 ) : Bool
+		return a <= b.val;
+
+	@:op(A > B) private static inline function gt( a : Int64, b : Int64 ) : Bool
+		return a.val > b.val;
+
+	@:op(A > B) private static inline function gtInt( a : Int64, b : Int ) : Bool
+		return a.val > b;
+
+	@:op(A > B) private static inline function intGt( a : Int, b : Int64 ) : Bool
+		return a > b.val;
+
+	@:op(A >= B) private static inline function gte( a : Int64, b : Int64 ) : Bool
+		return a.val >= b.val;
+
+	@:op(A >= B) private static inline function gteInt( a : Int64, b : Int ) : Bool
+		return a.val >= b;
+
+	@:op(A >= B) private static inline function intGte( a : Int, b : Int64 ) : Bool
+		return a >= b.val;
+
+	@:op(~A) private static inline function complement( x : Int64 ) : Int64
+		return ~x.val;
+
+	@:op(A & B) public static inline function and( a : Int64, b : Int64 ) : Int64
+		return a.val & b.val;
+
+	@:op(A | B) public static inline function or( a : Int64, b : Int64 ) : Int64
+		return a.val | b.val;
+
+	@:op(A ^ B) public static inline function xor( a : Int64, b : Int64 ) : Int64
+		return a.val ^ b.val;
+
+	@:op(A << B) public static inline function shl( a : Int64, b : Int ) : Int64
+		return a.val << b;
+
+	@:op(A >> B) public static inline function shr( a : Int64, b : Int ) : Int64
+		return a.val >> b;
+
+	@:op(A >>> B) public static inline function ushr( a : Int64, b : Int ) : Int64
+		return a.val >>> b;
 }

+ 350 - 0
tests/unit/src/unit/TestInt64.hx

@@ -1,4 +1,353 @@
 package unit;
+
+using haxe.Int64;
+
+class TestInt64 extends Test {
+
+	public function testMake() {
+		var a : Int64, i : Int;
+
+		// Test creation and fields
+		a = Int64.make(10,0xFFFFFFFF);
+		eq( a.getHigh(), 10 );
+		eq( a.getLow(), 0xFFFFFFFF );
+
+		// Int casts
+		a = 1;
+		eq( a.toInt(), 1 );
+
+		a = -1;
+		eq( a.getHigh(), 0xFFFFFFFF );
+		eq( a.getLow(), 0xFFFFFFFF );
+		eq( a.toInt(), -1 );
+
+		a = Int64.make(0,0x80000000);
+		eq( a.getHigh(), 0 );
+		eq( a.getLow(), 0x80000000 );
+		exc( tryOverflow.bind(a) );	// Throws Overflow
+
+		a = Int64.make(0xFFFFFFFF,0x80000000);
+		eq( a.getHigh(), 0xFFFFFFFF );
+		eq( a.getLow(), 0x80000000 );
+		eq( a.toInt(), -2147483648 );
+
+		a = Int64.make(0xFFFFFFFF,0x7FFFFFFF);
+		eq( a.getHigh(), 0xFFFFFFFF );
+		eq( a.getLow(), 0x7FFFFFFF );
+		exc( tryOverflow.bind(a) );	// Throws Overflow
+	}
+
+	// Some tests of how it generates Int64 when used as Null<Int64> or as type parameters
+	function testGen()
+	{
+		var arr:Array<Int64> = [];
+		arr.push(1);
+		arr.push(Int64.make(0xFFFFFFFF,0x80000000));
+		eq(arr[0].getHigh(), 0);
+		eq(arr[0].getLow(), 1);
+		eq(arr[1].getHigh(), 0xFFFFFFFF);
+		eq(arr[1].getLow(), 0x80000000);
+
+		var n:Null<Int64> = null;
+		eq(n, null);
+		var dyn:Dynamic = n;
+		eq(dyn, null);
+		n = Int64.make(0xf0f0f0f0, 0xefefefef);
+		eq(n.getHigh(), 0xf0f0f0f0);
+		eq(n.getLow(), 0xefefefef);
+	}
+
+	function tryOverflow( a : Int64 )
+	{
+		a.toInt();
+	}
+
+	public function testCopy() {
+		var a : Int64, b : Int64;
+		a = 1;
+		b = a.copy();
+		++b;
+		f( a == b );
+	}
+
+	public function testToString() {
+		var a : Int64;
+
+		// Issue #903
+		a = 0;
+		eq( Std.string( a ), "0" );
+
+		a = 156;
+		eq( '$a', "156" );
+
+		a = -1;
+		eq( '$a', "-1" );
+
+		a = Int64.make(0xFFFFFFFE,0);
+		eq( a.toStr(), "-8589934592" );
+
+		a = Int64.make(1,1);
+		eq( a.toStr(), "4294967297" );
+	}
+
+	public function testComparison() {
+		var a : Int64, b : Int64;
+		a = 1; b = 1;
+		t( a == b ); f( a != b );
+		t( a <= b ); f( a < b );
+		t( a >= b ); f( a > b );
+		eq( a.compare(b), 0 );
+		eq( a.ucompare(b), 0 );
+
+		a = -10;
+		b = -15;
+		f( a == b ); t( a != b );
+		f( a <= b ); f( a < b );
+		t( a >= b ); t( a > b );
+		t( a.compare(b) > 0 );
+		t( a.ucompare(b) > 0 );
+
+		a = Int64.make(0,0);
+		b = Int64.make(1,0);
+		f( a == b ); t( a != b );
+		t( a <= b ); t( a < b );
+		f( a >= b ); f( a > b );
+		t( a.compare(b) < 0 );
+		t( a.ucompare(b) < 0 );
+
+		a = Int64.make(0x0FFFFFFF,0xFFFFFFFF);
+		b = Int64.make(0x80000000,0x80000000);
+		f( a == b ); t( a != b );
+		f( a <= b ); f( a < b );
+		t( a >= b ); t( a > b );
+		t( a.compare(b) > 0 );
+		t( a.ucompare(b) < 0 );
+
+		// Issue #2317
+		a = Int64.make(0xA, 0x828D97A8);
+		b = 0;
+		t( a.compare(b) > 0 );
+		t( a.ucompare(b) > 0 );
+
+		// Issue #2090
+		a = 0;
+		b = Int64.make(320, -2138504556);
+		t( a.compare(b) < 0 );
+		t( a.ucompare(b) < 0 );
+
+
+	}
+
+	public function testIncrement() {
+		var a = Int64.make(0,0xFFFFFFFF);
+		var b = a.copy();
+		var c = Int64.make(1,0);
+		int64eq( a++, b );
+		int64eq( a--, c );
+		int64eq( ++a, c );
+		int64eq( --a, b );
+	}
+
+	public function testAddition() {
+		var a : Int64, b : Int64;
+
+		a = Int64.make(0,0x9E370301);
+		b = Int64.make(0,0xB0590000);
+		int64eq( a+b, Int64.make(0x1,0x4E900301) );
+
+		// negation
+		b = -a;
+		int64eq( a+b, 0 );
+
+		// Int64+Int
+		int64eq( a+12345678, Int64.make(0,0x9EF3644F) );
+
+		// Int+Int64
+		int64eq( 0xF0002222+a, Int64.make(0,0x8E372523) );
+	}
+
+	public function testSubtraction() {
+		var a : Int64, b : Int64;
+
+		a = Int64.make(1,0);
+		b = Int64.make(0,1);
+		int64eq( a-b, Int64.make(0,0xFFFFFFFF) );
+
+		b = a;
+		int64eq( a-b, 0 );
+
+		b = Int64.make(0xFFFFFFFE,1);
+		int64eq( a-b, Int64.make(2,0xFFFFFFFF) );
+
+		// Int64-Int
+		int64eq( a-12345678, Int64.make(0,0xFF439EB2) );
+
+		// Int-Int64
+		int64eq( 12345678-a, Int64.make(0xFFFFFFFF,0x00BC614E) );
+	}
+
+	public function testMultiplication() {
+		var a : Int64, b : Int64;
+
+		a = Int64.make(0, 0x239B0E13);
+		b = Int64.make(0, 0x39193D1B);
+		int64eq( a*b, Int64.make(0x07F108C6,0x4E900301) );
+
+		a = Int64.make(0, 0xD3F9C9F4);
+		b = Int64.make(0, 0xC865C765);
+		int64eq( a*b, Int64.make(0xA5EF6C6E,0x1ACD5944) );
+
+		var a = Int64.make(0xFFF21CDA, 0x972E8BA3);
+		var b = Int64.make(0x0098C29B, 0x81000001);
+		int64eq( a*b, Int64.make(0xDDE8A2E8, 0xBA2E8BA3) );
+
+		var a = Int64.make(0x81230000, 0x81230000);
+		var b = Int64.make(0x90909090, 0x90909090);
+		int64eq( a*b, Int64.make(0xF04C9C9C,0x53B00000) );
+
+		var a = Int64.make(0x00001000, 0x0020020E);
+		var b = Int64.make(0xBEDBEDED, 0xDEBDEBDE);
+		int64eq( a*b, Int64.make(0xC45C967D,0x25FAA224) );
+
+		// Issue #1532
+		a = Int64.make(0xFFF21CDA, 0x972E8BA3);
+    	b = Int64.make(0x0098C29B, 0x81000001);
+    	int64eq( a*b, Int64.make(0xDDE8A2E8, 0xBA2E8BA3) );
+
+		// Int64*Int
+		a = Int64.make(0x01000000, 0x11131111);
+		int64eq( a*7, Int64.make(0x07000000,0x77857777) );
+
+		// Int*Int64
+		a = Int64.make(0x91111111, 0x11111111);
+		int64eq( 2*a, Int64.make(0x22222222,0x22222222) );
+	}
+
+	public function testDivision() {
+		var a : Int64, b : Int64;
+
+		a = Int64.make(0x00002342, 0xDDEF3421);
+		b = Int64.make(0x00000001, 0x00002000);
+		int64eq( a/b, 9026 );
+		int64eq( a%b, Int64.make(0,0xD986F421) );
+		var result = a.divMod(b);
+		int64eq( a/b, result.quotient );
+		int64eq( a%b, result.modulus );
+
+		a = Int64.make(0xF0120AAA, 0xAAAAAAA0);
+		b = Int64.make(0x00020001, 0x0FF02000);
+		int64eq( a/b, -2038 );
+		int64eq( a%b, Int64.make(0xFFFE131F,0x8C496AA0) );
+		result = a.divMod(b);
+		int64eq( a/b, result.quotient );
+		int64eq( a%b, result.modulus );
+
+		a = Int64.make(0, 2);
+		b = Int64.make(0xFFFFFFFF, 0xFAFAFAFA);
+		int64eq( a/b, 0 );
+		int64eq( a%b, 2 );
+		result = a.divMod(b);
+		int64eq( a/b, result.quotient );
+		int64eq( a%b, result.modulus );
+
+		a = Int64.make(0x7ABADDAD, 0xDEADBEEF);
+		b = Int64.make(0xFFFFFFF1, 0x1FFFFFFF);
+		int64eq( a/b, Int64.make(0xFFFFFFFF,0xF7BFCEAE) );
+		int64eq( a%b, Int64.make(0x0000000A,0x166D8D9D) );
+		result = a.divMod(b);
+		int64eq( a/b, result.quotient );
+		int64eq( a%b, result.modulus );
+
+		a = Int64.make(0x81234567, 0xFDECBA98);
+		b = Int64.make(0xFFFFFEFF, 0xEEEEEEEE);
+		int64eq( a/b, 0x007ED446 );
+		int64eq( a%b, Int64.make(0xFFFFFFF5,0x31964D84) );
+		result = a.divMod(b);
+		int64eq( a/b, result.quotient );
+		int64eq( a%b, result.modulus );
+
+		// Int64/Int
+		int64eq( a/2, Int64.make(0xC091A2B3,0xFEF65D4C) );
+		int64eq( a%100, -68 );
+
+		// Int/Int64
+		int64eq( 10001/a, 0 );
+		int64eq( 515151%a, 515151 );
+	}
+
+	public function testBinaryOps() {
+		var a : Int64, b : Int64;
+
+		a = haxe.Int64.make(0x0FFFFFFF, 0x00000001);
+		b = haxe.Int64.make(0, 0x8FFFFFFF);
+		int64eq( a&b, 1 );
+		int64eq( a|b, Int64.make(0x0FFFFFFF, 0x8FFFFFFF) );
+		int64eq( a^b, Int64.make(0x0FFFFFFF, 0x8FFFFFFE) );
+		int64eq( ~a, Int64.make(0xF0000000, 0xFFFFFFFE) );
+	}
+
+	public function testShifts() {
+		var a : Int64;
+
+		a = 1 << 20;
+		int64eq( a, 0x100000 );
+
+		a <<= 20;
+		int64eq( a, Int64.make(0x100,0x00000000) );
+
+		a = -1;
+		a >>= 4;
+		int64eq( a, -1 );
+		a >>>= 4;
+		int64eq( a, Int64.make(0x0FFFFFFF,0xFFFFFFFF) );
+
+		// Ensure proper overflow behavior for shift operand
+		a = Int64.make(1,1);
+		int64eq( a << 0, a );
+		int64eq( a >> 0, a );
+		int64eq( a >>> 0, a );
+		int64eq( a << 64, a );
+		int64eq( a >> 64, a );
+		int64eq( a >>> 64, a );
+	}
+
+	/** Tests that we have all of the classic Int64 interface. */
+	public function testBackwardsCompat() {
+		var a : Int64 = 32.ofInt();
+		var b : Int64 = (-4).ofInt();
+
+		f( a.eq(b) );
+		t( a.neq(b) );
+		int64eq( a.add(b), 28 );
+		int64eq( a.sub(b), 36 );
+		int64eq( a.div(b), -8 );
+		int64eq( a.mod(b), 0 );
+		int64eq( b.shl(1), -8 );
+		int64eq( b.shr(1), -2 );
+		int64eq( b.ushr(1), Int64.make(0x7FFFFFFF,0xFFFFFFFE) );
+		int64eq( a.and(b), 32 );
+		int64eq( a.or(b), -4 );
+		int64eq( a.xor(b), -36 );
+		int64eq( a.neg(), -32 );
+		f( a.isNeg() );  t( b.isNeg() );
+		f( a.isZero() ); f( b.isZero() );
+		t( a.compare(b) > 0 );
+		t( a.ucompare(b) < 0 );
+		int64eq( a.toInt(), 32 );
+		int64eq( b.toInt(), -4 );
+	}
+
+	function int64eq( v : Int64, v2 : Int64, ?pos ) {
+		Test.count++;
+		if( v != v2 ) {
+			Test.report(Std.string(v)+" should be "+Std.string(v2),pos);
+			Test.success = false;
+		}
+	}
+}
+
+/*
+package unit;
 using haxe.Int64;
 import haxe.Int64.*;
 
@@ -113,3 +462,4 @@ class TestInt64 extends Test {
 		eq(Std.string(make(-2147483648, 1)), Std.string(neg(make(2147483647, -1)))); // -9223372036854775807 == neg(9223372036854775807)
 	}
 }
+*/

+ 1 - 1
tests/unit/src/unit/TestJava.hx

@@ -119,7 +119,7 @@ class TestJava extends Test
 		var c = new TestMyClass();
 		c.normalOverload(true);
 		t(c.boolCalled);
-		c.normalOverload(10);
+		c.normalOverload(6161);
 		t(c.intCalled);
 		c.normalOverload(haxe.Int64.ofInt(0));
 		t(c.int64Called);

+ 2 - 2
tests/unit/src/unit/issues/Issue3383.hx

@@ -6,7 +6,7 @@ class Issue3383 extends Test {
 		var i:Int = cast null,
 				f:Float = cast null,
 				s:Single = cast null,
-				i64:haxe.Int64 = null,
+				i64:haxe.Int64 = cast null,
 				span:cs.system.TimeSpan = null,
 				ui:UInt = cast null,
 				n:cs.system.Nullable_1<Int> = null;
@@ -14,7 +14,7 @@ class Issue3383 extends Test {
 			eq(i, cast null);
 			eq(f, cast null);
 			eq(s, cast null);
-			eq(i64, null);
+			eq(i64, cast null);
 			eq(span, null);
 			eq(ui, cast null);
 			eq(n, null);