From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40331) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XWAh0-0005V0-Lk for qemu-devel@nongnu.org; Mon, 22 Sep 2014 16:58:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XWAgv-0005iU-6o for qemu-devel@nongnu.org; Mon, 22 Sep 2014 16:58:42 -0400 Received: from mail-qa0-x229.google.com ([2607:f8b0:400d:c00::229]:38682) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XWAgv-0005hJ-2L for qemu-devel@nongnu.org; Mon, 22 Sep 2014 16:58:37 -0400 Received: by mail-qa0-f41.google.com with SMTP id cm18so767764qab.14 for ; Mon, 22 Sep 2014 13:58:31 -0700 (PDT) Sender: Richard Henderson From: Richard Henderson Date: Mon, 22 Sep 2014 13:57:41 -0700 Message-Id: <1411419461-24390-12-git-send-email-rth@twiddle.net> In-Reply-To: <1411419461-24390-1-git-send-email-rth@twiddle.net> References: <1411419461-24390-1-git-send-email-rth@twiddle.net> Subject: [Qemu-devel] [PULL 11/11] tcg: Always enable TCGv type checking List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org Instead of using structures, which imply some amount of overhead on certain ABIs, use pointer types. This actually reduces the size of the binaries vs a NON-debug build on ppc64 and x86_64, due to a reduction in the number of sign-extension insns. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- tcg/tcg.h | 89 ++++++++++++++++++++++++--------------------------------------- 1 file changed, 34 insertions(+), 55 deletions(-) diff --git a/tcg/tcg.h b/tcg/tcg.h index fcc50bd..a2fe1a9 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -275,75 +275,54 @@ typedef enum TCGMemOp { typedef tcg_target_ulong TCGArg; -/* Define a type and accessor macros for variables. Using a struct is - nice because it gives some level of type safely. Ideally the compiler - be able to see through all this. However in practice this is not true, - especially on targets with braindamaged ABIs (e.g. i386). - We use plain int by default to avoid this runtime overhead. - Users of tcg_gen_* don't need to know about any of this, and should - treat TCGv as an opaque type. +/* Define a type and accessor macros for variables. Using pointer types + is nice because it gives some level of type safety. Converting to and + from intptr_t rather than int reduces the number of sign-extension + instructions that get implied on 64-bit hosts. Users of tcg_gen_* don't + need to know about any of this, and should treat TCGv as an opaque type. In addition we do typechecking for different types of variables. TCGv_i32 and TCGv_i64 are 32/64-bit variables respectively. TCGv and TCGv_ptr - are aliases for target_ulong and host pointer sized values respectively. - */ + are aliases for target_ulong and host pointer sized values respectively. */ -#ifdef CONFIG_DEBUG_TCG -#define DEBUG_TCGV 1 -#endif +typedef struct TCGv_i32_d *TCGv_i32; +typedef struct TCGv_i64_d *TCGv_i64; +typedef struct TCGv_ptr_d *TCGv_ptr; -#ifdef DEBUG_TCGV +static inline TCGv_i32 QEMU_ARTIFICIAL MAKE_TCGV_I32(intptr_t i) +{ + return (TCGv_i32)i; +} -typedef struct +static inline TCGv_i64 QEMU_ARTIFICIAL MAKE_TCGV_I64(intptr_t i) { - int i32; -} TCGv_i32; + return (TCGv_i64)i; +} -typedef struct +static inline TCGv_ptr QEMU_ARTIFICIAL MAKE_TCGV_PTR(intptr_t i) { - int i64; -} TCGv_i64; - -typedef struct { - int iptr; -} TCGv_ptr; - -#define MAKE_TCGV_I32(i) __extension__ \ - ({ TCGv_i32 make_tcgv_tmp = {i}; make_tcgv_tmp;}) -#define MAKE_TCGV_I64(i) __extension__ \ - ({ TCGv_i64 make_tcgv_tmp = {i}; make_tcgv_tmp;}) -#define MAKE_TCGV_PTR(i) __extension__ \ - ({ TCGv_ptr make_tcgv_tmp = {i}; make_tcgv_tmp; }) -#define GET_TCGV_I32(t) ((t).i32) -#define GET_TCGV_I64(t) ((t).i64) -#define GET_TCGV_PTR(t) ((t).iptr) -#if TCG_TARGET_REG_BITS == 32 -#define TCGV_LOW(t) MAKE_TCGV_I32(GET_TCGV_I64(t)) -#define TCGV_HIGH(t) MAKE_TCGV_I32(GET_TCGV_I64(t) + 1) -#endif + return (TCGv_ptr)i; +} + +static inline intptr_t QEMU_ARTIFICIAL GET_TCGV_I32(TCGv_i32 t) +{ + return (intptr_t)t; +} -#else /* !DEBUG_TCGV */ +static inline intptr_t QEMU_ARTIFICIAL GET_TCGV_I64(TCGv_i64 t) +{ + return (intptr_t)t; +} -typedef int TCGv_i32; -typedef int TCGv_i64; -#if TCG_TARGET_REG_BITS == 32 -#define TCGv_ptr TCGv_i32 -#else -#define TCGv_ptr TCGv_i64 -#endif -#define MAKE_TCGV_I32(x) (x) -#define MAKE_TCGV_I64(x) (x) -#define MAKE_TCGV_PTR(x) (x) -#define GET_TCGV_I32(t) (t) -#define GET_TCGV_I64(t) (t) -#define GET_TCGV_PTR(t) (t) +static inline intptr_t QEMU_ARTIFICIAL GET_TCGV_PTR(TCGv_ptr t) +{ + return (intptr_t)t; +} #if TCG_TARGET_REG_BITS == 32 -#define TCGV_LOW(t) (t) -#define TCGV_HIGH(t) ((t) + 1) +#define TCGV_LOW(t) MAKE_TCGV_I32(GET_TCGV_I64(t)) +#define TCGV_HIGH(t) MAKE_TCGV_I32(GET_TCGV_I64(t) + 1) #endif -#endif /* DEBUG_TCGV */ - #define TCGV_EQUAL_I32(a, b) (GET_TCGV_I32(a) == GET_TCGV_I32(b)) #define TCGV_EQUAL_I64(a, b) (GET_TCGV_I64(a) == GET_TCGV_I64(b)) #define TCGV_EQUAL_PTR(a, b) (GET_TCGV_PTR(a) == GET_TCGV_PTR(b)) -- 1.9.3