From cccc98ded06e7257fd4279079ddcc705478d4457 Mon Sep 17 00:00:00 2001 From: robc Date: Mon, 25 Sep 2006 17:35:47 +0000 Subject: Merge from ST 20060925 git-svn-id: https://gcc.gnu.org/svn/gcc/branches/st/cli@117200 138bc75d-0d04-0410-961f-82ee72b054a4 --- cil32-crosstool.sh | 245 ++++++++++++---------- gcc/config/cil32/gcc4net.cs | 14 -- gcc/config/cil32/gen-cil.c | 435 +++++++++++++++++++++++++-------------- gcc/config/cil32/tree-simp-cil.c | 342 +++++++++++++++++++++--------- gcc/config/cil32/tree-simp-cil.h | 4 +- 5 files changed, 659 insertions(+), 381 deletions(-) diff --git a/cil32-crosstool.sh b/cil32-crosstool.sh index 53cf09e75e2..40f587e062c 100755 --- a/cil32-crosstool.sh +++ b/cil32-crosstool.sh @@ -1,6 +1,7 @@ #!/bin/sh +INSTALL_BINUTILS=yes INSTALL_GCC=yes TARGET=cil32 @@ -12,81 +13,65 @@ PREFIX=${PREFIX-`pwd`/newbuild} SYSROOT=${PREFIX}/${TARGET} LANGUAGES=c -_help() -{ - echo "Options:" - echo " -nogcc : build only binutils (no compiler)" - echo " -cpp : build also C++ compiler" - echo " -help : this message" -} - -while [ $# -gt 0 ] ; do - -if [ "x$1" == x-help ] ; then - _help ; - exit 0 -elif [ "x$1" == x-cpp ] ; then - LANGUAGES=c,c++ -elif [ "x$1" == x-nogcc ] ; then - INSTALL_GCC=no -else - echo "Unrecognized option: " $1 - _help ; - exit 1 -fi - -shift 1 -done - echo "DIRECTORIES:" echo " BUILD_DIR: " ${BUILD_DIR} echo " SOURCE_DIR: " ${SOURCE_DIR} echo " SYSROOT: " ${SYSROOT} echo " PREFIX: " ${PREFIX} - -PATH="${PREFIX}/bin:${PATH}" -export PATH +_help() +{ + echo "Options:" + echo " -binutils : install of binutils (default)" + echo " -nobinutils : skip install of binutils" + echo " -gcc : gcc build and installation (default)" + echo " -nogcc : skip gcc build and installation" + echo " -cpp : build also C++ compiler" + echo " -help : this message" +} # Create directories - -mkdir -p ${PREFIX} -mkdir -p ${PREFIX}/bin -mkdir -p ${PREFIX}/include -mkdir -p ${PREFIX}/lib -# SYSROOT must be = ${PREFIX}/${TARGET} -mkdir -p ${SYSROOT} -mkdir -p ${SYSROOT}/bin -( cd ${SYSROOT} ; ln -fs ../include . ) -( cd ${SYSROOT} ; ln -fs ../lib . ) +_prepare_dirs() +{ + mkdir -p ${PREFIX} + mkdir -p ${PREFIX}/bin + mkdir -p ${PREFIX}/include + mkdir -p ${PREFIX}/lib + # SYSROOT must be = ${PREFIX}/${TARGET} + mkdir -p ${SYSROOT} + mkdir -p ${SYSROOT}/bin + ( cd ${SYSROOT} ; ln -fs ../include . ) + ( cd ${SYSROOT} ; ln -fs ../lib . ) +} # Install Binutils +_binutils() +{ + CIL_AS=${CIL_AS-`which ilasm`} + CIL_LD=${CIL_LD-`which ilalink`} -CIL_AS=${CIL_AS-`which ilasm`} -CIL_LD=${CIL_LD-`which ilalink`} - -echo "Tools:" -echo " CIL ASSEMBLER: " ${CIL_AS} -echo " CIL LINKER: " ${CIL_LD} + echo "Tools:" + echo " CIL ASSEMBLER: " ${CIL_AS} + echo " CIL LINKER: " ${CIL_LD} -echo -echo "Installing Bin Utils" + echo + echo "Installing Bin Utils" -cat > ${SYSROOT}/bin/tool_not_exist <<_EOF_ + cat > ${SYSROOT}/bin/tool_not_exist <<_EOF_ #!/bin/sh echo "Tool " \`basename \$0\` " not provided" exit 1 _EOF_ -chmod 755 ${SYSROOT}/bin/tool_not_exist + chmod 755 ${SYSROOT}/bin/tool_not_exist -cat > ${SYSROOT}/bin/as <<_EOF_ + cat > ${SYSROOT}/bin/as <<_EOF_ #!/bin/sh ${CIL_AS} "\$@" _EOF_ -chmod 755 ${SYSROOT}/bin/as + chmod 755 ${SYSROOT}/bin/as -cat > ${SYSROOT}/bin/ld <<_EOF_ + cat > ${SYSROOT}/bin/ld <<_EOF_ #!/bin/sh PARAM= @@ -107,81 +92,119 @@ done ${CIL_LD} \$PARAM _EOF_ -chmod 755 ${SYSROOT}/bin/ld - -cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/addr2line -cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/ar -cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/nm -cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/objcopy -cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/objdump -cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/ranlib -cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/readelf -cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/size -cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/strings -cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/strip - - -cp ${SYSROOT}/bin/addr2line ${PREFIX}/bin/${TARGET}-addr2line -cp ${SYSROOT}/bin/ar ${PREFIX}/bin/${TARGET}-ar -cp ${SYSROOT}/bin/as ${PREFIX}/bin/${TARGET}-as -cp ${SYSROOT}/bin/ld ${PREFIX}/bin/${TARGET}-ld -cp ${SYSROOT}/bin/nm ${PREFIX}/bin/${TARGET}-nm -cp ${SYSROOT}/bin/objcopy ${PREFIX}/bin/${TARGET}-objcopy -cp ${SYSROOT}/bin/objdump ${PREFIX}/bin/${TARGET}-objdump -cp ${SYSROOT}/bin/ranlib ${PREFIX}/bin/${TARGET}-ranlib -cp ${SYSROOT}/bin/readelf ${PREFIX}/bin/${TARGET}-readelf -cp ${SYSROOT}/bin/size ${PREFIX}/bin/${TARGET}-size -cp ${SYSROOT}/bin/strings ${PREFIX}/bin/${TARGET}-strings -cp ${SYSROOT}/bin/strip ${PREFIX}/bin/${TARGET}-strip - -echo -echo "Installing vm wrappers" - -cat > ${PREFIX}/bin/${TARGET}-ilrun <<_EOF_ + chmod 755 ${SYSROOT}/bin/ld + + cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/addr2line + cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/ar + cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/nm + cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/objcopy + cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/objdump + cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/ranlib + cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/readelf + cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/size + cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/strings + cp ${SYSROOT}/bin/tool_not_exist ${SYSROOT}/bin/strip + + + cp ${SYSROOT}/bin/addr2line ${PREFIX}/bin/${TARGET}-addr2line + cp ${SYSROOT}/bin/ar ${PREFIX}/bin/${TARGET}-ar + cp ${SYSROOT}/bin/as ${PREFIX}/bin/${TARGET}-as + cp ${SYSROOT}/bin/ld ${PREFIX}/bin/${TARGET}-ld + cp ${SYSROOT}/bin/nm ${PREFIX}/bin/${TARGET}-nm + cp ${SYSROOT}/bin/objcopy ${PREFIX}/bin/${TARGET}-objcopy + cp ${SYSROOT}/bin/objdump ${PREFIX}/bin/${TARGET}-objdump + cp ${SYSROOT}/bin/ranlib ${PREFIX}/bin/${TARGET}-ranlib + cp ${SYSROOT}/bin/readelf ${PREFIX}/bin/${TARGET}-readelf + cp ${SYSROOT}/bin/size ${PREFIX}/bin/${TARGET}-size + cp ${SYSROOT}/bin/strings ${PREFIX}/bin/${TARGET}-strings + cp ${SYSROOT}/bin/strip ${PREFIX}/bin/${TARGET}-strip + + echo + echo "Installing vm wrappers" + + cat > ${PREFIX}/bin/${TARGET}-ilrun <<_EOF_ #!/bin/sh -ilrun -L ${PREFIX}/lib "\$@" +basedir=\`dirname \$0\` +basedir=\`cd \$basedir/.. ; pwd\` + +ilrun -L \$basedir/lib "\$@" _EOF_ -chmod 755 ${PREFIX}/bin/${TARGET}-ilrun + chmod 755 ${PREFIX}/bin/${TARGET}-ilrun -cat > ${PREFIX}/bin/${TARGET}-mono <<_EOF_ + cat > ${PREFIX}/bin/${TARGET}-mono <<_EOF_ #!/bin/sh -export MONO_PATH=${PREFIX}/lib +basedir=\`dirname \$0\` +basedir=\`cd \$basedir/.. ; pwd\` -mono "\$@" +MONO_PATH=\$basedir/lib mono "\$@" _EOF_ -chmod 755 ${PREFIX}/bin/${TARGET}-mono + chmod 755 ${PREFIX}/bin/${TARGET}-mono +} -# ... To Be Completed with needed binutil tools - -# ... To Be Completed with libraries +# Configure, build and install gcc -if test "x${INSTALL_GCC}" == "xno" -then +_gcc() +{ + echo + echo "Configuring GCC" + + mkdir -p ${BUILD_DIR}/build-gcc + cd ${BUILD_DIR}/build-gcc + + ${SOURCE_DIR}/configure --target=${TARGET} \ + --enable-languages=${LANGUAGES} \ + --disable-bootstrap \ + --prefix=${PREFIX} \ + --with-local-prefix=${SYSROOT} + + echo + echo "Building GCC" + make all + + echo + echo "Installing GCC" + make install +} + +while [ $# -gt 0 ] ; do + +if [ "x$1" == x-help ] ; then + _help ; exit 0 +elif [ "x$1" == x-cpp ] ; then + LANGUAGES=c,c++ +elif [ "x$1" == x-nobinutils ] ; then + INSTALL_BINUTILS=no +elif [ "x$1" == x-nogcc ] ; then + INSTALL_GCC=no +elif [ "x$1" == x-binutils ] ; then + INSTALL_BINUTILS=yes +elif [ "x$1" == x-gcc ] ; then + INSTALL_GCC=yes +else + echo "Unrecognized option: " $1 + _help ; + exit 1 fi -# Configure gcc +shift 1 +done -echo -echo "Configuring GCC" +PATH="${PREFIX}/bin:${PATH}" +export PATH -mkdir -p ${BUILD_DIR}/build-gcc -cd ${BUILD_DIR}/build-gcc +_prepare_dirs -${SOURCE_DIR}/configure --target=${TARGET} \ - --enable-languages=${LANGUAGES} \ - --disable-bootstrap \ - --prefix=${PREFIX} \ - --with-local-prefix=${SYSROOT} +if test "x${INSTALL_BINUTILS}" == "xyes" +then + _binutils +fi -# Build and install gcc -echo -echo "Building GCC" -make all -echo -echo "Installing GCC" -make install +if test "x${INSTALL_GCC}" == "xyes" +then + _gcc +fi diff --git a/gcc/config/cil32/gcc4net.cs b/gcc/config/cil32/gcc4net.cs index fff17f545a9..3321a55b4ff 100644 --- a/gcc/config/cil32/gcc4net.cs +++ b/gcc/config/cil32/gcc4net.cs @@ -52,12 +52,10 @@ namespace gcc4net { } public unsafe static void Startup() { - Module mainModule; Assembly assembly; Type type; // Find the module that contains the "main" function. - mainModule = null; assembly = Assembly.GetEntryAssembly(); type = assembly.GetType(""); // Invoke the application's ".init" function, if present. @@ -90,17 +88,5 @@ namespace gcc4net { public static long __absti2(long a) { return (a>=0) ? a : -a; } public static float __abssf2(float a) { return (a>=0) ? a : -a; } public static double __absdf2(double a) { return (a>=0) ? a : -a; } - - unsafe public static void memset(void* dest , byte val, int len) { - byte* ptr = (byte*)dest; - while (len-- > 0) - *ptr++ = val; - } - unsafe public static void memcpy (void* dest, void* src, int len) { - byte* d = (byte*)dest; - byte* s = (byte*)src; - while (len-- > 0) - *d++ = *s++; - } } } diff --git a/gcc/config/cil32/gen-cil.c b/gcc/config/cil32/gen-cil.c index 0f74ce6ac88..afe4d918756 100644 --- a/gcc/config/cil32/gen-cil.c +++ b/gcc/config/cil32/gen-cil.c @@ -75,7 +75,7 @@ static void dump_label_name (FILE *, tree); static void dump_fun_type (FILE *, tree, tree, const char *, bool); static void dump_valuetype_name (FILE *, tree); static void compute_addr_expr (FILE *, tree); -static void print_type_suffix (FILE *, tree, tree, bool); +static void print_type_suffix (FILE *, tree, bool); static void gen_cil_modify_expr (FILE *, tree); static char * append_string (char *, const char *, unsigned int *, unsigned int *); @@ -93,6 +93,7 @@ static void stack_set (unsigned int) ATTRIBUTE_UNUSED; static void stack_reset (void); static void stack_push (unsigned int); static void stack_pop (unsigned int); +static void gen_integral_conv (FILE *, tree, tree); static void gen_start_function (FILE *); static unsigned int gen_cil (void); static void gen_cil_1 (FILE *); @@ -136,6 +137,8 @@ mark_var_defs_uses (tree node) case CALL_EXPR: { tree args = TREE_OPERAND (node, 1); + tree fun_expr; + tree dfun = NULL_TREE; mark_var_defs_uses (TREE_OPERAND (node, 0)); @@ -144,6 +147,33 @@ mark_var_defs_uses (tree node) mark_var_defs_uses (TREE_VALUE (args)); args = TREE_CHAIN (args); } + + fun_expr = TREE_OPERAND (node, 0); + if (TREE_CODE (fun_expr) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (fun_expr, 0)) == FUNCTION_DECL) + dfun = TREE_OPERAND (fun_expr, 0); + + /* Calls to some built-in functions require ad-hoc simplifications */ + if (dfun && DECL_BUILT_IN (dfun)) + { + switch (DECL_FUNCTION_CODE (dfun)) + { + case BUILT_IN_VA_COPY: + { + tree va_dest = TREE_VALUE (TREE_OPERAND (node, 1)); + + gcc_assert (TREE_CODE (va_dest) == ADDR_EXPR); + gcc_assert (TREE_CODE (TREE_OPERAND (va_dest, 0)) == VAR_DECL + && !DECL_FILE_SCOPE_P (TREE_OPERAND (va_dest, 0))); + + TREE_SIDE_EFFECTS (TREE_OPERAND (va_dest, 0)) = true; + } + break; + + default: + ; + } + } } break; @@ -200,6 +230,10 @@ mark_var_defs_uses (tree node) mark_var_defs_uses (lhs); mark_var_defs_uses (rhs); + + if (AGGREGATE_TYPE_P (TREE_TYPE (lhs)) && TREE_CODE (rhs) == VAR_DECL) + TREE_SIDE_EFFECTS (rhs) = true; + gcc_assert (TREE_CODE (rhs) != CONSTRUCTOR && TREE_CODE (rhs) != STRING_CST); } @@ -212,16 +246,33 @@ mark_var_defs_uses (tree node) case NOP_EXPR: case FLOAT_EXPR: case FIX_TRUNC_EXPR: - case INDIRECT_REF: - case BIT_FIELD_REF: - case ADDR_EXPR: - case COMPONENT_REF: case ABS_EXPR: case RETURN_EXPR: case WITH_SIZE_EXPR: mark_var_defs_uses (TREE_OPERAND (node, 0)); break; + case ADDR_EXPR: + case COMPONENT_REF: + { + tree op = TREE_OPERAND (node, 0); + + mark_var_defs_uses (op); + if (AGGREGATE_TYPE_P (TREE_TYPE (op)) && TREE_CODE (op) == VAR_DECL) + TREE_SIDE_EFFECTS (op) = true; + } + break; + + case INDIRECT_REF: + { + tree op = TREE_OPERAND (node, 0); + + mark_var_defs_uses (op); + if (AGGREGATE_TYPE_P (TREE_TYPE (node)) && TREE_CODE (op) == VAR_DECL) + TREE_SIDE_EFFECTS (op) = true; + } + break; + case INTEGER_CST: case REAL_CST: case STRING_CST: @@ -342,8 +393,7 @@ remove_stloc_ldloc (block_stmt_iterator bsi, tree *node_ptr, bool *mod) case INIT_EXPR: case MODIFY_EXPR: - if (! AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (node, 0)))) - remove_stloc_ldloc (bsi, &TREE_OPERAND (node, 1), mod); + remove_stloc_ldloc (bsi, &TREE_OPERAND (node, 1), mod); gcc_assert (TREE_CODE (TREE_OPERAND (node, 1)) != CONSTRUCTOR && TREE_CODE (TREE_OPERAND (node, 1)) != STRING_CST); break; @@ -355,28 +405,23 @@ remove_stloc_ldloc (block_stmt_iterator bsi, tree *node_ptr, bool *mod) case NOP_EXPR: case FLOAT_EXPR: case FIX_TRUNC_EXPR: - case BIT_FIELD_REF: + case ADDR_EXPR: + case COMPONENT_REF: + case INDIRECT_REF: case ABS_EXPR: case RETURN_EXPR: case WITH_SIZE_EXPR: remove_stloc_ldloc (bsi, &TREE_OPERAND (node, 0), mod); break; - case ADDR_EXPR: - case COMPONENT_REF: - if (! AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (node, 0)))) - remove_stloc_ldloc (bsi, &TREE_OPERAND (node, 0), mod); - break; - - case INDIRECT_REF: - if (! AGGREGATE_TYPE_P (TREE_TYPE (node))) - remove_stloc_ldloc (bsi, &TREE_OPERAND (node, 0), mod); - break; - case VAR_DECL: + /* In GIMPLE, TREE_SIDE_EFFECTS is true for a VAR_DECL only if the + variable is volatile. + However, mark_var_defs_uses (...) function sets TREE_SIDE_EFFECTS + for some non-volatile variables that shouldn't be removed. */ if (! TREE_ADDRESSABLE (node) && ! TREE_STATIC (node) - && ! TREE_THIS_VOLATILE (node) + && ! TREE_SIDE_EFFECTS (node) && ! DECL_FILE_SCOPE_P (node)) { tree prev_stmt; @@ -812,10 +857,11 @@ dump_type (FILE *file, tree node, bool ref) { /* node = TYPE_MAIN_VARIANT (node); */ - if (TYPE_MAIN_VARIANT (node) == va_list_type_node) { + if (TYPE_MAIN_VARIANT (node) == va_list_type_node) + { fputs ("valuetype [mscorlib]System.ArgIterator", file); return; - } + } switch (TREE_CODE (node)) { @@ -861,7 +907,7 @@ dump_type (FILE *file, tree node, bool ref) case REAL_TYPE: { - int type_size = GET_MODE_BITSIZE (TYPE_MODE (node)); + int type_size = TYPE_PRECISION (node); switch (type_size) { @@ -898,7 +944,7 @@ dump_type (FILE *file, tree node, bool ref) case VECTOR_TYPE: { - int type_size = GET_MODE_BITSIZE (TYPE_MODE (node)); + int type_size = TREE_INT_CST_LOW (TYPE_SIZE (node)); tree innertype = TREE_TYPE (node); enum machine_mode innermode = TYPE_MODE (innertype); @@ -1099,6 +1145,7 @@ dump_type_for_builtin (FILE *file, tree node, bool all_types) { case ENUMERAL_TYPE: case INTEGER_TYPE: + case BOOLEAN_TYPE: { int type_size = GET_MODE_BITSIZE (TYPE_MODE (node)); @@ -1120,7 +1167,7 @@ dump_type_for_builtin (FILE *file, tree node, bool all_types) case REAL_TYPE: { - int type_size = GET_MODE_BITSIZE (TYPE_MODE (node)); + int type_size = TYPE_PRECISION (node); switch (type_size) { @@ -1147,6 +1194,7 @@ dump_type_eval_mode (FILE *stream, tree node, bool all_types) { case ENUMERAL_TYPE: case INTEGER_TYPE: + case BOOLEAN_TYPE: { int type_size = GET_MODE_BITSIZE (TYPE_MODE (node)); @@ -1254,23 +1302,6 @@ compute_addr_expr (FILE *file, tree t) } break; - case BIT_FIELD_REF: - { - tree obj = TREE_OPERAND (t, 0); - unsigned int off = TREE_INT_CST_LOW (TREE_OPERAND (t, 2)); - - gcc_assert (off % 8 == 0); - compute_addr_expr (file, obj); - if (off / 8 > 0) - { - fprintf (file, "\n\tldc.i4\t%d", off / 8); - fputs ("\n\tadd", file); - stack_push (1); - stack_pop (1); - } - } - break; - default: fprintf (stderr, "%s: %s\n", __func__, tree_code_name[TREE_CODE (t)]); @@ -1282,22 +1313,15 @@ compute_addr_expr (FILE *file, tree t) } static void -print_type_suffix (FILE *file, tree type_node, tree conv_in_type, bool unsign) +print_type_suffix (FILE *file, tree type_node, bool unsign) { - int type_size = GET_MODE_BITSIZE (TYPE_MODE (type_node)); - switch (TREE_CODE (type_node)) { case ENUMERAL_TYPE: case INTEGER_TYPE: { - bool uns = false; - - if (TYPE_UNSIGNED (type_node) - || (conv_in_type != NULL_TREE - && TYPE_UNSIGNED (conv_in_type) - && type_size > GET_MODE_BITSIZE (TYPE_MODE (conv_in_type)))) - uns = unsign; + int type_size = TYPE_PRECISION (type_node); + bool uns = unsign && TYPE_UNSIGNED (type_node); switch (type_size) { @@ -1313,16 +1337,24 @@ print_type_suffix (FILE *file, tree type_node, tree conv_in_type, bool unsign) } break; + case BOOLEAN_TYPE: + fputs ((unsign && TYPE_UNSIGNED (type_node))?"u1":"i1", file); + break; + case REAL_TYPE: - switch (type_size) - { - case 32: fputs ("r4", file); break; - case 64: fputs ("r8", file); break; - default: - fprintf (stderr, "Unsupported floating point size %d\n", type_size); - gcc_assert (0); - break; - } + { + int type_size = TYPE_PRECISION (type_node); + + switch (type_size) + { + case 32: fputs ("r4", file); break; + case 64: fputs ("r8", file); break; + default: + fprintf (stderr, "Unsupported floating point size %d\n", type_size); + gcc_assert (0); + break; + } + } break; case POINTER_TYPE: @@ -1331,17 +1363,14 @@ print_type_suffix (FILE *file, tree type_node, tree conv_in_type, bool unsign) case VECTOR_TYPE: { - bool uns = false; + int type_size = TREE_INT_CST_LOW (TYPE_SIZE (type_node)); + bool uns = TYPE_UNSIGNED (type_node) && unsign; tree innertype = TREE_TYPE (type_node); enum machine_mode innermode = TYPE_MODE (innertype); /* Only expect integer vectors */ gcc_assert (GET_MODE_CLASS (innermode) == MODE_INT); - /* and then emit as corresponding same-size interger mode */ - if (TYPE_UNSIGNED (type_node) && unsign) - uns = true; - switch (type_size) { case 8: fputs ((uns)?"u1":"i1", file); break; @@ -1364,6 +1393,79 @@ print_type_suffix (FILE *file, tree type_node, tree conv_in_type, bool unsign) } } +/* Emit a conversion from integral or pointer type IN_TYPE + to integral type OUT_TYPE to file FILE. + If the precision of OUT_TYPE is bigger than that of IN_TYPE, + then IN_TYPE and OUT_TYPE have to have the same signedness. */ + +static void +gen_integral_conv (FILE *file, tree out_type, tree in_type) +{ + unsigned int out_bits, cont_size, in_bits; + + gcc_assert (INTEGRAL_TYPE_P (out_type)); + gcc_assert (INTEGRAL_TYPE_P (in_type) || TREE_CODE (in_type) == POINTER_TYPE); + gcc_assert (TYPE_PRECISION (out_type) <= 64); + gcc_assert (TYPE_PRECISION (out_type) <= TYPE_PRECISION (in_type) + || TYPE_UNSIGNED (out_type) == TYPE_UNSIGNED (in_type)); + + /* Get the precision of the output and input types and the size + of the output type container */ + in_bits = TYPE_PRECISION (in_type); + out_bits = TYPE_PRECISION (out_type); + cont_size = GET_MODE_BITSIZE (TYPE_MODE (out_type)); + gcc_assert (cont_size >= out_bits); + + /* Dump a conv with for the container size, if not superfluous */ + if ((cont_size == out_bits && (out_bits != in_bits || out_bits < 32)) + || ((out_bits > 32) ^ (in_bits > 32))) + { + fputs ("\n\tconv.", file); + print_type_suffix (file, get_integer_type (cont_size, + TYPE_UNSIGNED (out_type)), + true); + } + + /* If the container is bigger than the output type precision, + force the output to be of the desired precision. */ + if (cont_size > out_bits) + { + if (TYPE_UNSIGNED (out_type)) + { + unsigned HOST_WIDEST_INT mask; + double_int mask_di; + + /* Compute the mask to be applied to the existing value */ + gcc_assert (HOST_BITS_PER_WIDEST_INT >= 64); + mask = (1LL << out_bits) - 1LL; + mask_di.low = mask; + mask_di.high = (HOST_WIDE_INT)(mask >> HOST_BITS_PER_WIDE_INT); + + /* Apply the mask */ + if (out_bits <= 32) + fputs ("\n\tldc.i4\t", file); + else + fputs ("\n\tldc.i8\t", file); + dump_double_int (file, mask_di, false); + fputs ("\n\tand", file); + } + else + { + unsigned int cont_size = (out_bits > 32) ? 64 : 32; + unsigned int shift = cont_size - out_bits; + + /* Do a pair of shift to perform the sign extension */ + fprintf (file, "\n\tldc.i4\t%d", shift); + fputs ("\n\tshl\t", file); + fprintf (file, "\n\tldc.i4\t%d", shift); + fputs ("\n\tshr\t", file); + } + + stack_push (1); + stack_pop (1); + } +} + /* Dump the node NODE in CIL on the file FILE. */ static void gen_cil_node (FILE *file, tree node) @@ -1386,26 +1488,18 @@ gen_cil_node (FILE *file, tree node) { case INTEGER_CST: { - int type_size = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (node))); + int type_size = TYPE_PRECISION (TREE_TYPE (node)); - switch (type_size) - { - case 8: - case 16: - case 32: - fprintf (file, "\n\tldc.i4\t%ld", TREE_INT_CST_LOW (node)); - break; - - case 64: - fprintf (file, "\n\tldc.i8\t%ld", TREE_INT_CST_LOW (node)); - break; + gcc_assert (type_size <= 64); + if (type_size <= 32) + fputs ("\n\tldc.i4\t", file); + else + fputs ("\n\tldc.i8\t", file); + dump_double_int (file, TREE_INT_CST (node), false); - default: - internal_error ("\nldc: unsupported int size %d\n", type_size); - break; - } if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE) fputs ("\n\tconv.i", file); + stack_push (1); } break; @@ -1425,7 +1519,7 @@ gen_cil_node (FILE *file, tree node) mode = TYPE_MODE (type_tree); real_to_target (buf, &d, mode); real_to_decimal (string, &d, sizeof (string), 5, 1); - type_size = GET_MODE_BITSIZE (TYPE_MODE (type_tree)); + type_size = TYPE_PRECISION (type_tree); switch (type_size) { @@ -1449,14 +1543,17 @@ gen_cil_node (FILE *file, tree node) case VECTOR_CST: { tree elt; - unsigned int val = 0; + unsigned HOST_WIDEST_INT val = 0; + double_int val_di; tree vector_type = TREE_TYPE (node); - int vector_bitsize = GET_MODE_BITSIZE (TYPE_MODE (vector_type)); + int vector_bitsize = TREE_INT_CST_LOW (TYPE_SIZE (vector_type)); tree unit_type = TREE_TYPE (vector_type); - int unit_bitsize = GET_MODE_BITSIZE (TYPE_MODE (unit_type)); + int unit_bitsize = TYPE_PRECISION (unit_type); + + gcc_assert (HOST_BITS_PER_WIDEST_INT >= 64); - /* At this time, support only 32 bit vectors */ - if (vector_bitsize != 32) + /* At this time, support up to 64-bit vectors */ + if (vector_bitsize > 64) internal_error ("\nVECTOR_CST size %d\n", vector_bitsize); for (elt = TREE_VECTOR_CST_ELTS (node); elt; elt = TREE_CHAIN (elt)) @@ -1465,6 +1562,7 @@ gen_cil_node (FILE *file, tree node) switch (TREE_CODE (elt_val)) { case INTEGER_CST: + gcc_assert (TREE_INT_CST_HIGH (elt_val) == 0); val = (val << unit_bitsize) | TREE_INT_CST_LOW (elt_val); break; @@ -1474,7 +1572,15 @@ gen_cil_node (FILE *file, tree node) } } - fprintf (file, "\n\tldc.i4\t%#0x", val); + val_di.low = val; + val_di.high = (HOST_WIDE_INT)(val >> HOST_BITS_PER_WIDE_INT); + + if (vector_bitsize <= 32) + fputs ("\n\tldc.i4\t", file); + else + fputs ("\n\tldc.i8\t", file); + dump_double_int (file, val_di, false); + stack_push (1); break; } @@ -2012,7 +2118,6 @@ gen_cil_node (FILE *file, tree node) case MINUS_EXPR: case RDIV_EXPR: case LSHIFT_EXPR: - case BIT_XOR_EXPR: op0 = TREE_OPERAND (node, 0); op1 = TREE_OPERAND (node, 1); @@ -2026,25 +2131,21 @@ gen_cil_node (FILE *file, tree node) case MINUS_EXPR: fputs ("\n\tsub", file); break; case RDIV_EXPR: fputs ("\n\tdiv", file); break; case LSHIFT_EXPR: fputs ("\n\tshl", file); break; - case BIT_XOR_EXPR: fputs ("\n\txor", file); break; default: gcc_unreachable (); } - /* Values smaller than 32-bits are represented as 32-bit - on the evaluation stack, therefore an explicit conversion - is required. */ - if (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (node))) < 32) - { - fputs ("\n\tconv.", file); - print_type_suffix (file, TREE_TYPE (node), NULL_TREE, true); - } - stack_pop (1); + + /* Values with precision smaller than the one used + on the evaluation stack require an explicit conversion. */ + if (INTEGRAL_TYPE_P (TREE_TYPE (node))) + gen_integral_conv (file, TREE_TYPE (node), TREE_TYPE (node)); break; case BIT_IOR_EXPR: case BIT_AND_EXPR: + case BIT_XOR_EXPR: op0 = TREE_OPERAND (node, 0); op1 = TREE_OPERAND (node, 1); @@ -2055,12 +2156,14 @@ gen_cil_node (FILE *file, tree node) { case BIT_IOR_EXPR: fputs ("\n\tor", file); break; case BIT_AND_EXPR: fputs ("\n\tand", file); break; + case BIT_XOR_EXPR: fputs ("\n\txor", file); break; default: gcc_unreachable (); } - /* No need for conversions even in case of values smaller - than 32-bits, since for these operations the output is + /* No need for conversions even in case of values with precision + smaller than the one used on the evaluation stack, + since for these operations the output is always less or equal than both operands. */ stack_pop (1); @@ -2095,7 +2198,7 @@ gen_cil_node (FILE *file, tree node) gcc_unreachable (); } - if (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (node))) == 64) + if (TYPE_PRECISION (TREE_TYPE (node)) > 32) fputs ("\n\tconv.i8", file); stack_pop (1); @@ -2127,7 +2230,7 @@ gen_cil_node (FILE *file, tree node) fputs ("\n\tldc.i4.1" "\n\txor", file); - if (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (node))) == 64) + if (TYPE_PRECISION (TREE_TYPE (node)) > 32) fputs ("\n\tconv.i8", file); stack_pop (1); @@ -2156,8 +2259,9 @@ gen_cil_node (FILE *file, tree node) if (TYPE_UNSIGNED (TREE_TYPE (node))) fputs (".un", file); - /* No need for conversions even in case of values smaller - than 32-bits, since for these operations the output is + /* No need for conversions even in case of values with precision + smaller than the one used on the evaluation stack, + since for these operations the output is always less or equal than both operands. */ stack_pop (1); @@ -2190,8 +2294,9 @@ gen_cil_node (FILE *file, tree node) fputs (")", file); } - /* No need for conversions even in case of values smaller - than 32-bits, since for this operation the output is + /* No need for conversions even in case of values with precision + smaller than the one used on the evaluation stack, + since for these operations the output is always less or equal than both operands. */ stack_pop (1); @@ -2210,49 +2315,63 @@ gen_cil_node (FILE *file, tree node) gcc_unreachable (); } - /* Values smaller than 32-bits are represented as 32-bit - on the evaluation stack, therefore an explicit conversion - is required. + /* Values with precision smaller than the one used + on the evaluation stack require an explicit conversion. Unfortunately this is true for the negation as well just for the case in which the operand is the smallest negative value. Example: 8-bit negation of -128 gives 0 and not 128. */ - if (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (node))) < 32) - { - fputs ("\n\tconv.", file); - print_type_suffix (file, TREE_TYPE (node), NULL_TREE, true); - } - + if (INTEGRAL_TYPE_P (TREE_TYPE (node))) + gen_integral_conv (file, TREE_TYPE (node), TREE_TYPE (node)); break; case INDIRECT_REF: - case BIT_FIELD_REF: compute_addr_expr (file, node); - fputs ("\n\tldind.", file); - print_type_suffix (file, TREE_TYPE (node), NULL_TREE, true); + if (AGGREGATE_TYPE_P (TREE_TYPE (node))) + { + fputs ("\n\tldobj\t", file); + dump_type (file, TREE_TYPE (node), true); + } + else + { + fputs ("\n\tldind.", file); + print_type_suffix (file, TREE_TYPE (node), true); + } break; case CONVERT_EXPR: + case FLOAT_EXPR: /* ER: if flag_trapv is set, we could generate the .ovf version? */ /* TODO: */ - gen_cil_node (file, TREE_OPERAND (node, 0)); - fputs ("\n\tconv.", file); - print_type_suffix (file, TREE_TYPE (node), TREE_TYPE (TREE_OPERAND (node, 0)), true); - break; - + case FIX_TRUNC_EXPR: case NOP_EXPR: { - enum tree_code out_type_code = TREE_CODE (TREE_TYPE (node)); + tree op = TREE_OPERAND (node, 0); + tree in_type = TREE_TYPE (op); + tree out_type = TREE_TYPE (node); - gen_cil_node (file, TREE_OPERAND (node, 0)); + gen_cil_node (file, op); - if (out_type_code == INTEGER_TYPE - || out_type_code == ENUMERAL_TYPE - || out_type_code == REAL_TYPE - || out_type_code == POINTER_TYPE) + if (TREE_CODE (node) == NOP_EXPR && INTEGRAL_TYPE_P (out_type)) + { + gcc_assert (INTEGRAL_TYPE_P (in_type) + || TREE_CODE (in_type) == POINTER_TYPE); + + if (TYPE_PRECISION (out_type) > TYPE_PRECISION (in_type)) + { + tree tmp_type = TYPE_UNSIGNED (in_type) + ? unsigned_type_for (out_type) + : signed_type_for (out_type); + + gen_integral_conv (file, tmp_type, in_type); + gen_integral_conv (file, out_type, tmp_type); + } + else + gen_integral_conv (file, out_type, in_type); + } + else { fputs ("\n\tconv.", file); - print_type_suffix (file, TREE_TYPE (node), - TREE_TYPE (TREE_OPERAND (node, 0)), true); + print_type_suffix (file, out_type, true); } } break; @@ -2434,13 +2553,6 @@ gen_cil_node (FILE *file, tree node) } break; - case FLOAT_EXPR: - case FIX_TRUNC_EXPR: - gen_cil_node (file, TREE_OPERAND (node, 0)); - fputs ("\n\tconv.", file); - print_type_suffix (file, TREE_TYPE (node), NULL_TREE, true); - break; - case TRUTH_NOT_EXPR: gen_cil_node (file, TREE_OPERAND (node, 0)); fputs ("\n\tldc.i4.0" @@ -2456,6 +2568,8 @@ gen_cil_node (FILE *file, tree node) op1 = TREE_OPERAND (node, 1); gen_cil_node (file, op0); + gcc_assert (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE + || TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE); if (TREE_CODE (TREE_TYPE (op0)) == INTEGER_TYPE) { fputs ("\n\tldc.i4.0" @@ -2467,6 +2581,8 @@ gen_cil_node (FILE *file, tree node) } gen_cil_node (file, op1); + gcc_assert (TREE_CODE (TREE_TYPE (op1)) == INTEGER_TYPE + || TREE_CODE (TREE_TYPE (op1)) == BOOLEAN_TYPE); if (TREE_CODE (TREE_TYPE (op1)) == INTEGER_TYPE) { fputs ("\n\tldc.i4.0" @@ -2518,20 +2634,6 @@ gen_cil_modify_expr (FILE *file, tree node) tree lhs = TREE_OPERAND (node, 0); tree rhs = TREE_OPERAND (node, 1); - if (AGGREGATE_TYPE_P (TREE_TYPE (rhs)) - && (TREE_CODE (lhs) == INDIRECT_REF || TREE_CODE (rhs) == INDIRECT_REF)) - { - gcc_assert (AGGREGATE_TYPE_P (TREE_TYPE (lhs))); - compute_addr_expr (file, lhs); - compute_addr_expr (file, rhs); - fprintf (file, "\n\tldc.i4\t%lu", - TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (rhs)))); - fputs ("\n\tcall\tvoid [gcc4net]gcc4net.Crt::memcpy(void*, void*, int32)",file); - stack_push (1); - stack_pop (3); - return; - } - switch (TREE_CODE (lhs)) { case SSA_NAME: @@ -2541,8 +2643,19 @@ gen_cil_modify_expr (FILE *file, tree node) case INDIRECT_REF: compute_addr_expr (file, lhs); gen_cil_node (file, rhs); - fputs ("\n\tstind.", file); - print_type_suffix (file, TREE_TYPE (lhs), NULL_TREE, false); + + if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))) + { + gcc_assert (AGGREGATE_TYPE_P (TREE_TYPE (rhs))); + fputs ("\n\tstobj\t", file); + dump_type (file, TREE_TYPE (lhs), true); + } + else + { + fputs ("\n\tstind.", file); + print_type_suffix (file, TREE_TYPE (lhs), false); + } + stack_pop (2); break; @@ -2642,7 +2755,7 @@ append_coded_type (char *str, tree type, { case INTEGER_TYPE: { - int type_size = GET_MODE_BITSIZE (TYPE_MODE (type)); + int type_size = TYPE_PRECISION (type); char tmp_str[8] = "UI"; char *tmp_str_ptr = tmp_str; @@ -2655,9 +2768,13 @@ append_coded_type (char *str, tree type, } break; + case BOOLEAN_TYPE: + str = append_string (str, "B", len, max_len); + break; + case REAL_TYPE: { - int type_size = GET_MODE_BITSIZE (TYPE_MODE (type)); + int type_size = TYPE_PRECISION (type); char tmp_str[4] = "F"; snprintf (tmp_str + 1, 3, "%d", type_size); @@ -2887,7 +3004,7 @@ print_valuetype_decl (FILE *file, tree t) if (is_enum) { - int type_size = GET_MODE_BITSIZE (TYPE_MODE (t)); + int type_size = TYPE_PRECISION (t); char tmp_str[8] = "int"; char *base_type_str = tmp_str; tree tmp; diff --git a/gcc/config/cil32/tree-simp-cil.c b/gcc/config/cil32/tree-simp-cil.c index 8e43c2fbee9..d8f8aa26994 100644 --- a/gcc/config/cil32/tree-simp-cil.c +++ b/gcc/config/cil32/tree-simp-cil.c @@ -90,6 +90,12 @@ Roberto Costa */ assignment also requires a load from memory; from the memory access point of view, the operation cannot be made atomic. + *) Expansion of BIT_FIELD_REF nodes. + CIL has no direct support for bit-field access; hence, + equivalent code that extracts the bit pattern and applies the + appropriate bit mask is generated. + Memory access is performed by using INDIRECT_REF nodes. + *) Expansion of TARGET_MEM_REF nodes. Emission of such nodes is not difficult in gen_cil pass; however, a previous expansion may trigger further optimizations @@ -126,6 +132,15 @@ Roberto Costa */ The reason is that CIL shift operations require a shift operand of type int32. + *) Forcing arguments of CALL_EXPRs to be local variables, only for + specific built-in functions. + A few built-in functions require special simplifications + in order to make their emission easier; in particular: + *) the 1st argument of BUILT_IN_VA_COPY has to be a local variable + (the emitted CIL uses a 'stloc' to store its value). + To force arguments of calls to be local variables, new local + variables are generated. + *) Rename of inlined variables to unique names. Emitted variables by gen_cil pass keep the original name. In case of variables declared within inlined functions, @@ -144,52 +159,67 @@ Roberto Costa */ */ /* Local functions, macros and variables. */ -static tree get_unsigned_integer_type (int); static bool is_copy_required (tree); static bool mostly_zeros_p (tree); static bool all_zeros_p (tree); static void simp_switch (block_stmt_iterator *, tree *); static void simp_trivial_switch (block_stmt_iterator *, tree *); +static void simp_builtin_call (block_stmt_iterator, tree); static void simp_abs (block_stmt_iterator *, tree *); static void simp_min_max (block_stmt_iterator *, tree *); static void simp_rotate (block_stmt_iterator *, tree *); static void simp_shift (block_stmt_iterator *, tree); static void simp_target_mem_ref (block_stmt_iterator *, tree *); static void simp_array_ref (block_stmt_iterator *, tree *); +static void simp_bitfield (block_stmt_iterator *, tree *, tree, unsigned int, + unsigned int, unsigned int, HOST_WIDEST_INT, bool); static void simp_rhs_bitfield_component_ref (block_stmt_iterator *, tree *); static void simp_lhs_bitfield_component_ref (block_stmt_iterator *, tree *); +static void simp_bitfield_ref (block_stmt_iterator *, tree *); static void pre_simp_init (block_stmt_iterator *, tree); static void simp_cil_node (block_stmt_iterator *, tree *); -static void split_use (block_stmt_iterator, tree *); -static void rename_var (tree, const char*); +static void split_use (block_stmt_iterator, tree *, bool); +static void rename_var (tree, const char*, unsigned long); static void simp_vars (void); static unsigned int simp_cil (void); static bool simp_cil_gate (void); static tree res_var; -static tree uint32_type; -/* Return the unsigned integer type with size BITS bits */ +/* Return the integer type with size BITS bits. + The type is unsigned or signed depending on UNS. */ -static tree -get_unsigned_integer_type (int bits) +tree +get_integer_type (int bits, bool uns) { - if (GET_MODE_BITSIZE (TYPE_MODE (unsigned_type_node)) == bits) - return unsigned_type_node; - else if (GET_MODE_BITSIZE (TYPE_MODE (long_unsigned_type_node)) == bits) - return long_unsigned_type_node; - else if (GET_MODE_BITSIZE (TYPE_MODE (short_unsigned_type_node)) == bits) - return short_unsigned_type_node; - else if (GET_MODE_BITSIZE (TYPE_MODE (long_long_unsigned_type_node)) - == bits) - return long_long_unsigned_type_node; - else if (GET_MODE_BITSIZE (TYPE_MODE (unsigned_char_type_node)) == bits) - return unsigned_char_type_node; - else - { - gcc_assert (0); - return NULL_TREE; - } + if (uns) + { + switch (bits) + { + case 8: return unsigned_intQI_type_node; + case 16: return unsigned_intHI_type_node; + case 32: return unsigned_intSI_type_node; + case 64: return unsigned_intDI_type_node; + case 128: return unsigned_intTI_type_node; + default: + gcc_assert (0); + return NULL_TREE; + } + } + else + { + switch (bits) + { + case 8: return intQI_type_node; + case 16: return intHI_type_node; + case 32: return intSI_type_node; + case 64: return intDI_type_node; + case 128: return intTI_type_node; + default: + gcc_assert (0); + return NULL_TREE; + } + } } /* In the case of multiple uses of tree NODE, return whether @@ -247,6 +277,8 @@ simp_cil_node (block_stmt_iterator *bsi, tree *node_ptr) case CALL_EXPR: { tree args = TREE_OPERAND (node, 1); + tree fun_expr; + tree dfun = NULL_TREE; simp_cil_node (bsi, &TREE_OPERAND (node, 0)); @@ -255,6 +287,15 @@ simp_cil_node (block_stmt_iterator *bsi, tree *node_ptr) simp_cil_node (bsi, &TREE_VALUE (args)); args = TREE_CHAIN (args); } + + fun_expr = TREE_OPERAND (node, 0); + if (TREE_CODE (fun_expr) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (fun_expr, 0)) == FUNCTION_DECL) + dfun = TREE_OPERAND (fun_expr, 0); + + /* Calls to some built-in functions require ad-hoc simplifications */ + if (dfun && DECL_BUILT_IN (dfun)) + simp_builtin_call (*bsi, node); } break; @@ -306,7 +347,7 @@ simp_cil_node (block_stmt_iterator *bsi, tree *node_ptr) if (AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (node, 1))) && TREE_CODE (TREE_OPERAND (node, 0)) == INDIRECT_REF && TREE_CODE (TREE_OPERAND (node, 1)) == CALL_EXPR) - split_use (*bsi, &TREE_OPERAND (node, 1)); + split_use (*bsi, &TREE_OPERAND (node, 1), false); break; case NEGATE_EXPR: @@ -316,7 +357,6 @@ simp_cil_node (block_stmt_iterator *bsi, tree *node_ptr) case NOP_EXPR: case FLOAT_EXPR: case FIX_TRUNC_EXPR: - case BIT_FIELD_REF: simp_cil_node (bsi, &TREE_OPERAND (node, 0)); break; @@ -324,14 +364,14 @@ simp_cil_node (block_stmt_iterator *bsi, tree *node_ptr) simp_cil_node (bsi, &TREE_OPERAND (node, 0)); if (AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (node, 0))) && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR) - split_use (*bsi, &TREE_OPERAND (node, 0)); + split_use (*bsi, &TREE_OPERAND (node, 0), false); break; case INDIRECT_REF: simp_cil_node (bsi, &TREE_OPERAND (node, 0)); if (AGGREGATE_TYPE_P (TREE_TYPE (node)) && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR) - split_use (*bsi, &TREE_OPERAND (node, 0)); + split_use (*bsi, &TREE_OPERAND (node, 0), false); break; case COMPONENT_REF: @@ -339,7 +379,7 @@ simp_cil_node (block_stmt_iterator *bsi, tree *node_ptr) simp_cil_node (bsi, &TREE_OPERAND (node, 0)); if (AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (node, 0))) && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR) - split_use (*bsi, &TREE_OPERAND (node, 0)); + split_use (*bsi, &TREE_OPERAND (node, 0), false); if (DECL_BIT_FIELD (TREE_OPERAND (node, 1))) { tree stmt = bsi_stmt (*bsi); @@ -352,6 +392,16 @@ simp_cil_node (block_stmt_iterator *bsi, tree *node_ptr) } break; + case BIT_FIELD_REF: + simp_cil_node (bsi, &TREE_OPERAND (node, 0)); + if (AGGREGATE_TYPE_P (TREE_TYPE (TREE_OPERAND (node, 0))) + && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR) + split_use (*bsi, &TREE_OPERAND (node, 0), false); + gcc_assert (TREE_CODE (bsi_stmt (*bsi)) != MODIFY_EXPR + || TREE_OPERAND (bsi_stmt (*bsi), 0) != node); + simp_bitfield_ref (bsi, node_ptr); + break; + case TARGET_MEM_REF: simp_cil_node (bsi, &TMR_SYMBOL (node)); simp_cil_node (bsi, &TMR_BASE (node)); @@ -361,7 +411,7 @@ simp_cil_node (block_stmt_iterator *bsi, tree *node_ptr) gcc_assert (TREE_CODE (node) == INDIRECT_REF); if (AGGREGATE_TYPE_P (TREE_TYPE (node)) && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR) - split_use (*bsi, &TREE_OPERAND (node, 0)); + split_use (*bsi, &TREE_OPERAND (node, 0), false); break; case ARRAY_REF: @@ -372,7 +422,7 @@ simp_cil_node (block_stmt_iterator *bsi, tree *node_ptr) gcc_assert (TREE_CODE (node) == INDIRECT_REF); if (AGGREGATE_TYPE_P (TREE_TYPE (node)) && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR) - split_use (*bsi, &TREE_OPERAND (node, 0)); + split_use (*bsi, &TREE_OPERAND (node, 0), false); break; case RETURN_EXPR: @@ -862,6 +912,40 @@ simp_trivial_switch (block_stmt_iterator *bsi, tree *node_ptr) } } +/* Force specific arguments of the CALL_EXPR to a built-in function + pointed by NODE to be local variables. + Which arguments are forced depend on the built-in function. + BSI is the iterator of the statement that contains NODE + (in order to allow insertion of new statements). */ + +static void +simp_builtin_call (block_stmt_iterator bsi, tree node) +{ + tree fun_expr = TREE_OPERAND (node, 0); + + gcc_assert (TREE_CODE (node) == CALL_EXPR); + gcc_assert (TREE_CODE (fun_expr) == ADDR_EXPR); + gcc_assert (TREE_CODE (TREE_OPERAND (fun_expr, 0)) == FUNCTION_DECL); + gcc_assert (DECL_BUILT_IN (TREE_OPERAND (fun_expr, 0))); + + switch (DECL_FUNCTION_CODE (TREE_OPERAND (fun_expr, 0))) + { + case BUILT_IN_VA_COPY: + { + tree va_dest = TREE_VALUE (TREE_OPERAND (node, 1)); + + gcc_assert (TREE_CODE (va_dest) == ADDR_EXPR); + if (TREE_CODE (TREE_OPERAND (va_dest, 0)) != VAR_DECL + || DECL_FILE_SCOPE_P (TREE_OPERAND (va_dest, 0))) + split_use (bsi, &TREE_OPERAND (va_dest, 0), true); + } + break; + + default: + ; + } +} + /* Remove the ABS_EXPR pointed by NODE_PTR by inserting explicit control flow. BSI points to the iterator of the statement that contains *NODE_PTR @@ -1077,7 +1161,7 @@ simp_rotate (block_stmt_iterator *bsi, tree *node_ptr) op0 = fold_convert (op0_uns_type, op0); /* Convert the second operand to 32-bit */ - op1 = fold_convert (uint32_type, TREE_OPERAND (node, 1)); + op1 = fold_convert (unsigned_intSI_type_node, TREE_OPERAND (node, 1)); /* Make sure that the two operands have no side effects */ if (is_copy_required (op0)) @@ -1109,8 +1193,8 @@ simp_rotate (block_stmt_iterator *bsi, tree *node_ptr) /* Build second shift */ t2 = fold_build2 (left ? RSHIFT_EXPR : LSHIFT_EXPR, op0_uns_type, op0, - build2 (MINUS_EXPR, uint32_type, - fold_convert (uint32_type, + build2 (MINUS_EXPR, unsigned_intSI_type_node, + fold_convert (unsigned_intSI_type_node, TYPE_SIZE (TREE_TYPE (op0))), op1)); @@ -1143,7 +1227,7 @@ simp_shift (block_stmt_iterator *bsi, tree node) || TREE_CODE (node) == RSHIFT_EXPR); /* Generate the type conversion */ - t = fold_convert (uint32_type, TREE_OPERAND (node, 1)); + t = fold_convert (unsigned_intSI_type_node, TREE_OPERAND (node, 1)); /* Gimplify the equivalent expression and update the current node */ TREE_OPERAND (node, 1) = force_gimple_operand_bsi (bsi, t, FALSE, NULL); @@ -1312,46 +1396,40 @@ simp_array_ref (block_stmt_iterator *bsi, tree *node_ptr) *node_ptr = build1 (INDIRECT_REF, TREE_TYPE (node), t1); } -/* Expand the COMPONENT_REF (pointed by NODE_PTR) accessing - a BIT_FIELD_DECL and being on a right-hand side by transforming it +/* Expand a bit-field reference by transforming it into an INDIRECT_REF and applying the necessary bit mask operations. BSI points to the iterator of the statement that contains *NODE_PTR (in order to allow insertion of new statements). BSI is passed by reference because instructions are inserted. NODE is passed by reference because simplification requires - replacing the node. */ + replacing the node. + OBJ is the object containing the bit-field. + CONT_SIZE is the number of bits of the bit-field container. + BFLD_SIZE is the number of bits being referenced. + BFLD_OFF is the position of the first referenced bit. + OFF is an additional offset in bytes of the bit-field from the + beginning of the OBJ. + UNS tells whether the bit-field is unsigned or not. */ static void -simp_rhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) +simp_bitfield (block_stmt_iterator *bsi, tree *node_ptr, + tree obj, unsigned int cont_size, unsigned int bfld_size, + unsigned int bfld_off, HOST_WIDEST_INT off, bool uns) { tree node = *node_ptr; location_t locus = EXPR_LOCATION (bsi_stmt (*bsi)); - tree obj = TREE_OPERAND (node, 0); - tree fld = TREE_OPERAND (node, 1); - tree fld_type, fld_off ; - unsigned int cont_size, bfld_size, bfld_off; tree new_type, obj_ptr_type; tree tmp_var, tmp_stmt; tree t; - HOST_WIDEST_INT off; - - gcc_assert (TREE_CODE (node) == COMPONENT_REF); - gcc_assert (DECL_BIT_FIELD (fld)); - /* Extract bit field layout */ - fld_type = DECL_BIT_FIELD_TYPE (fld); - fld_off = DECL_FIELD_OFFSET (fld); - cont_size = TREE_INT_CST_LOW (TYPE_SIZE (fld_type)); - bfld_size = TYPE_PRECISION (TREE_TYPE (fld)); - bfld_off = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (fld)) & (cont_size - 1); - gcc_assert (cont_size >= TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (node)))); + gcc_assert (cont_size >= bfld_size + bfld_off); /* Build the type corresponding of a pointer to the object */ obj_ptr_type = build0 (POINTER_TYPE, TREE_TYPE (obj)); layout_type (obj_ptr_type); /* Build the new type for the equivalent access */ - new_type = get_unsigned_integer_type (cont_size); + new_type = get_integer_type (cont_size, uns); /* Build the (gimplified) equivalent expression */ @@ -1364,13 +1442,6 @@ simp_rhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) t = tmp_var; bsi_insert_before (bsi, tmp_stmt, BSI_SAME_STMT); - off = TREE_INT_CST_LOW (fld_off) - + ((TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (fld)) - & ~(cont_size - 1)) - / 8); - - gcc_assert (TREE_INT_CST_HIGH (fld_off) == 0); - if (off > 0) { tmp_var = create_tmp_var (obj_ptr_type, "cilsimp"); @@ -1399,7 +1470,7 @@ simp_rhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) tmp_var, build2 (LSHIFT_EXPR, new_type, t, - build_int_cstu (uint32_type, + build_int_cstu (unsigned_intSI_type_node, cont_size - bfld_size - bfld_off))); SET_EXPR_LOCATION (tmp_stmt, locus); @@ -1414,7 +1485,7 @@ simp_rhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) tmp_var, build2 (RSHIFT_EXPR, new_type, t, - build_int_cstu (uint32_type, + build_int_cstu (unsigned_intSI_type_node, cont_size - bfld_size))); SET_EXPR_LOCATION (tmp_stmt, locus); t = tmp_var; @@ -1427,6 +1498,46 @@ simp_rhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) *node_ptr = fold_convert (TREE_TYPE (node), t); } +/* Expand the COMPONENT_REF (pointed by NODE_PTR) accessing + a BIT_FIELD_DECL and being on a right-hand side by transforming it + into an INDIRECT_REF and applying the necessary bit mask operations. + BSI points to the iterator of the statement that contains *NODE_PTR + (in order to allow insertion of new statements). + BSI is passed by reference because instructions are inserted. + NODE is passed by reference because simplification requires + replacing the node. */ + +static void +simp_rhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) +{ + tree node = *node_ptr; + tree obj = TREE_OPERAND (node, 0); + tree fld = TREE_OPERAND (node, 1); + tree fld_type, fld_off; + unsigned int cont_size, bfld_size, bfld_off; + HOST_WIDEST_INT off; + + gcc_assert (TREE_CODE (node) == COMPONENT_REF); + gcc_assert (DECL_BIT_FIELD (fld)); + + /* Extract bit field layout */ + fld_type = DECL_BIT_FIELD_TYPE (fld); + fld_off = DECL_FIELD_OFFSET (fld); + cont_size = TREE_INT_CST_LOW (TYPE_SIZE (fld_type)); + bfld_size = TYPE_PRECISION (TREE_TYPE (fld)); + bfld_off = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (fld)) & (cont_size - 1); + gcc_assert (cont_size >= TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (node)))); + gcc_assert (TREE_INT_CST_HIGH (fld_off) == 0); + off = TREE_INT_CST_LOW (fld_off) + + ((TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (fld)) + & ~(cont_size - 1)) + / 8); + + /* Simplify the bit-field */ + simp_bitfield (bsi, node_ptr, obj, cont_size, bfld_size, bfld_off, off, + DECL_UNSIGNED (fld)); +} + /* Expand the COMPONENT_REF (pointed by NODE_PTR) accessing a BIT_FIELD_DECL and being on a left-hand side by transforming it into an INDIRECT_REF and applying the necessary bit mask operations. @@ -1466,7 +1577,7 @@ simp_lhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) gcc_assert (cont_size >= TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (node)))); /* Build the new type for the equivalent access */ - new_type = get_unsigned_integer_type (cont_size); + new_type = get_integer_type (cont_size, true); /* Build the type corresponding of a pointer to the object */ obj_ptr_type = build0 (POINTER_TYPE, TREE_TYPE (obj)); @@ -1490,7 +1601,7 @@ simp_lhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) tmp_var, build2 (LSHIFT_EXPR, new_type, rhs, - build_int_cstu (uint32_type, + build_int_cstu (unsigned_intSI_type_node, cont_size - bfld_size))); SET_EXPR_LOCATION (tmp_stmt, locus); rhs = tmp_var; @@ -1506,7 +1617,7 @@ simp_lhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) tmp_var, build2 (RSHIFT_EXPR, new_type, rhs, - build_int_cstu (uint32_type, + build_int_cstu (unsigned_intSI_type_node, cont_size - bfld_size - bfld_off))); SET_EXPR_LOCATION (tmp_stmt, locus); @@ -1556,9 +1667,9 @@ simp_lhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) /* Compute the mask to be applied to the existing value */ gcc_assert (HOST_BITS_PER_WIDEST_INT >= 64); - mask |= (1 << (cont_size - bfld_size - bfld_off)) - 1; + mask |= (1LL << (cont_size - bfld_size - bfld_off)) - 1LL; mask <<= bfld_off + bfld_size; - mask |= (1 << bfld_off) - 1; + mask |= (1LL << bfld_off) - 1; /* Apply the mask to the existing value */ tmp_var = create_tmp_var (new_type, "cilsimp"); @@ -1566,7 +1677,9 @@ simp_lhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) tmp_var, build2 (BIT_AND_EXPR, new_type, t, - build_int_cstu (new_type, mask))); + build_int_cst_wide (new_type, + mask, + mask >> HOST_BITS_PER_WIDE_INT))); SET_EXPR_LOCATION (tmp_stmt, locus); t = tmp_var; bsi_insert_before (bsi, tmp_stmt, BSI_SAME_STMT); @@ -1587,6 +1700,51 @@ simp_lhs_bitfield_component_ref (block_stmt_iterator *bsi, tree *node_ptr) TREE_OPERAND (stmt, 1) = rhs; } +/* Expand the BIT_FIELD_REF (pointed by NODE_PTR) by transforming it + into an INDIRECT_REF and applying the necessary bit mask operations. + BSI points to the iterator of the statement that contains *NODE_PTR + (in order to allow insertion of new statements). + BSI is passed by reference because instructions are inserted. + NODE is passed by reference because simplification requires + replacing the node. */ + +static void +simp_bitfield_ref (block_stmt_iterator *bsi, tree *node_ptr) +{ + tree node = *node_ptr; + tree obj = TREE_OPERAND (node, 0); + unsigned int ref_bfld_off, cont_size, bfld_size, bfld_off; + HOST_WIDE_INT off; + + gcc_assert (TREE_CODE (node) == BIT_FIELD_REF); + + /* Extract bit field layout */ + bfld_size = TREE_INT_CST_LOW (TREE_OPERAND (node, 1)); + ref_bfld_off = TREE_INT_CST_LOW (TREE_OPERAND (node, 2)); + gcc_assert (bfld_size <= 64); + + /* At least, cont_size is the next power of two of the bit-field size */ + cont_size = bfld_size - 1; + cont_size |= (cont_size >> 1); + cont_size |= (cont_size >> 2); + cont_size |= (cont_size >> 4); + ++cont_size; + gcc_assert (cont_size == 8 || cont_size == 16 + || cont_size == 32 || cont_size == 64); + + /* Widen the container until an aligned access is enough */ + while ((ref_bfld_off & ~(cont_size - 1)) + != ((ref_bfld_off + bfld_size - 1) & ~(cont_size - 1))) + cont_size <<= 1; + + bfld_off = ref_bfld_off & (cont_size - 1); + off = (ref_bfld_off - bfld_off) >> 3; + + /* Simplify the bit-field */ + simp_bitfield (bsi, node_ptr, obj, cont_size, bfld_size, bfld_off, off, + BIT_FIELD_REF_UNSIGNED (node)); +} + /* Expand the INIT_EXPR (or MODIFY_EXPR) in NODE having a CONSTRUCTOR or STRING_CST on the right side into a sequence of simpler (here, it means "not involving CONSTRUCTOR or @@ -1655,21 +1813,23 @@ pre_simp_init (block_stmt_iterator *bsi, tree node) *bsi = tmp_bsi; } -/* Make sure that the tree pointed by NODE_PTR is a VAR_DECL. +/* Make sure that the tree pointed by NODE_PTR is a VAR_DECL; + if LOCAL is true, then the VAR_DECL must be a local variable. In case, split the statement containing NODE_PTR into two by creating a new local variable. BSI points to the iterator of the statement that contains NODE_PTR (in order to allow insertion of new statements). */ static void -split_use (block_stmt_iterator bsi, tree *node_ptr) +split_use (block_stmt_iterator bsi, tree *node_ptr, bool local) { tree node = *node_ptr; location_t locus = EXPR_LOCATION (bsi_stmt (bsi)); tree type = TREE_TYPE (node); tree var, stmt; - if (TREE_CODE (node) == VAR_DECL) + if (TREE_CODE (node) == VAR_DECL + && (!local || !DECL_FILE_SCOPE_P (node))) return; /* Split the current statement by creating a new local variable */ @@ -1963,24 +2123,11 @@ expand_init_to_stmt_list (tree decl, tree init, tree *stmt_list, bool cleared) elements. */ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), i, index, value) { - enum machine_mode mode; - HOST_WIDE_INT bitsize; - int unsignedp; tree t; if (initializer_zerop (value)) continue; - unsignedp = TYPE_UNSIGNED (elttype); - mode = TYPE_MODE (elttype); - - if (mode == BLKmode) - bitsize = (host_integerp (TYPE_SIZE (elttype), 1) - ? tree_low_cst (TYPE_SIZE (elttype), 1) - : -1); - else - bitsize = GET_MODE_BITSIZE (mode); - gcc_assert (index == NULL_TREE || TREE_CODE (index) != RANGE_EXPR); @@ -2020,7 +2167,7 @@ expand_init_to_stmt_list (tree decl, tree init, tree *stmt_list, bool cleared) /* Rename a single variable using the specified suffix */ static void -rename_var (tree var, const char* suffix) +rename_var (tree var, const char* suffix, unsigned long index) { const char *orig_name = IDENTIFIER_POINTER (DECL_NAME (var)); char *newsym = alloca (strlen (orig_name) + strlen (suffix) + 10 + 1); @@ -2029,7 +2176,7 @@ rename_var (tree var, const char* suffix) "%s%s%lu", orig_name, suffix, - (unsigned long)var)); + index)); } /* Simplify variables: rename inlined variables @@ -2041,20 +2188,28 @@ simp_vars (void) { block_stmt_iterator bsi = bsi_start (ENTRY_BLOCK_PTR); tree *p = &cfun->unexpanded_var_list; + unsigned long num_loc = 0; - for (; *p; ) + for (; *p; p = &TREE_CHAIN (*p)) { tree var = TREE_VALUE (*p); tree init = DECL_INITIAL (var); if (TREE_STATIC (var) && DECL_CONTEXT (var) != 0) { - rename_var (var, "?fs"); + rename_var (var, "?fs", (unsigned long)var); DECL_CONTEXT (var) = 0; } - if (DECL_FROM_INLINE (var) && DECL_NAME (var) != NULL) - rename_var (var, "?in"); + if (DECL_NAME (var) != NULL && ! TREE_STATIC (var)) + { + if (DECL_FROM_INLINE (var)) + rename_var (var, "?in", num_loc); + else + rename_var (var, "?", num_loc); + + ++num_loc; + } if (!TREE_STATIC (var) && init && init != error_mark_node) { @@ -2063,8 +2218,6 @@ simp_vars (void) build2 (INIT_EXPR, TREE_TYPE (var), var, init), BSI_NEW_STMT); } - - p = &TREE_CHAIN (*p); } } @@ -2077,7 +2230,6 @@ simp_cil (void) block_stmt_iterator bsi; res_var = NULL_TREE; - uint32_type = get_unsigned_integer_type (32); simp_vars (); @@ -2103,7 +2255,7 @@ simp_cil (void) pre_simp_init (&bsi, stmt); else if (TREE_CODE (lhs) == COMPONENT_REF && DECL_BIT_FIELD (TREE_OPERAND (lhs, 1))) - split_use (bsi, &TREE_OPERAND (stmt, 1)); + split_use (bsi, &TREE_OPERAND (stmt, 1), false); } } } diff --git a/gcc/config/cil32/tree-simp-cil.h b/gcc/config/cil32/tree-simp-cil.h index 51f0970a707..6f4ea4fc502 100644 --- a/gcc/config/cil32/tree-simp-cil.h +++ b/gcc/config/cil32/tree-simp-cil.h @@ -33,7 +33,7 @@ Roberto Costa */ #include "tree.h" -void -expand_init_to_stmt_list (tree, tree, tree *, bool); +extern void expand_init_to_stmt_list (tree, tree, tree *, bool); +extern tree get_integer_type (int, bool); #endif /* TREE_SIMP_CIL_H */ -- cgit v1.2.3