Expand call
From reading gcc
概要[edit | edit source]
- expr.c にて定義
- 関数コールのtreeからRTL式を生成
引数[edit | edit source]
- exp 関数コールのtree (関数アドレスのtree、引数のtree)
- target
実装[edit | edit source]
2096 static rtx
2097 expand_call (exp, target)
2098 tree exp;
2099 rtx target;
2100 {
2101 tree actparms = TREE_OPERAND (exp, 1);
2102 register tree p;
2103 int args_size = 0;
2104 register int i;
2105 register tree *argvec;
2106 int num_actuals;
2107 rtx structure_value_addr = 0;
2108
2109 /* Don't let pending stack adjusts add up to too much.
2110 Also, do all pending adjustments now
2111 if there is any chance this might be a call to alloca. */
2112
2113 if (pending_stack_adjust >= 32
2114 || (pending_stack_adjust > 0
2115 &&
2116 /* Unless it's a call to a specific function that isn't alloca,
2117 we must assume it might be alloca. */
2118 !(p = TREE_OPERAND (exp, 0),
2119 TREE_CODE (p) == ADDR_EXPR
2120 && TREE_CODE (TREE_OPERAND (p, 0)) == FUNCTION_DECL
2121 && strcmp (IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (p, 0))),
2122 "alloca"))))
2123 do_pending_stack_adjust ();
2124
構造体のアドレス?
2125 if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
2126 {
2127 /* This call returns a big structure. */
2128 if (target)
2129 structure_value_addr = XEXP (target, 0);
2130 else
2131 /* Make room on the stack to hold the value. */
2132 structure_value_addr = get_structure_value_addr (expr_size (exp));
2133 }
2134
引数の数だけ領域を確保し、スタックに積む順序で配列に並べる。
2135 for (p = actparms, i = 0; p; p = TREE_CHAIN (p)) i++; 2136 num_actuals = i; 2137 argvec = (tree *) alloca (i * sizeof (tree)); 2138 2139 #ifdef STACK_GROWS_DOWNWARD 2140 /* In this case, must reverse order of args 2141 so that we compute and pust the last arg first. */ 2142 for (p = actparms, i = num_actuals - 1; p; p = TREE_CHAIN (p), i--) 2143 argvec[i] = p; 2144 #else 2145 for (p = actparms, i = 0; p; p = TREE_CHAIN (p), i++) 2146 argvec[i] = p; 2147 #endif 2148
なにかチェックし、引数をスタックに積む、PUSHのRTL式に変換
2149 for (i = 0; i < num_actuals; i++)
2150 {
2151 register tree p = argvec[i];
2152 register tree pval = TREE_VALUE (p);
2153
2154 /* Push the next argument. Note that it has already been converted
2155 if necessary to the type that the called function expects. */
2156
2157 if (TREE_CODE (pval) == ERROR_MARK)
2158 ;
2159 else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode)
2160 {
2161 register int size, used;
2162
2163 /* Argument is a scalar.
2164 Push it, and if its size is less than the
2165 amount of space allocated to it,
2166 also bump stack pointer by the additional space.
2167 Note that in C the default argument promotions
2168 will prevent such mismatches. */
2169
2170 used = size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval)));
2171 /* Compute how much space the push instruction will push.
2172 On many machines, pushing a byte will advance the stack
2173 pointer by a halfword. */
2174 size = PUSH_ROUNDING (size);
2175 /* Compute how much space the argument should get:
2176 round up to a multiple of the alignment for arguments. */
2177 used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
2178 / (PARM_BOUNDARY / BITS_PER_UNIT))
2179 * (PARM_BOUNDARY / BITS_PER_UNIT));
2180
2181 #ifdef STACK_GROWS_DOWNWARD
2182 if (size != used)
2183 anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode,
2184 used - size));
2185 #endif
2186
2187 emit_push_insn (expand_expr (pval, 0, VOIDmode, 0),
2188 TYPE_MODE (TREE_TYPE (pval)), 0, 0);
2189
2190 #ifndef STACK_GROWS_DOWNWARD
2191 if (size != used)
2192 anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode,
2193 used - size));
2194 #endif
2195
2196 /* Account for the space thus used. */
2197 args_size += used;
2198 current_args_size += used;
2199 }
2200 else
2201 {
2202 register rtx tem = expand_expr (pval, 0, VOIDmode, 0);
2203 register tree size = size_in_bytes (TREE_TYPE (pval));
2204 register tree used;
2205 register int excess;
2206
2207 /* Pushing a nonscalar. Round its size up to a multiple
2208 of the allocation unit for arguments. This part works
2209 on variable-size objects since SIZE and USED are rtx's. */
2210
2211 used = convert_units (convert_units (size, BITS_PER_UNIT, PARM_BOUNDARY),
2212 PARM_BOUNDARY, BITS_PER_UNIT);
2213
2214 if (!TREE_LITERAL (used))
2215 abort ();
2216
2217 excess = TREE_INT_CST_LOW (used) - PUSH_ROUNDING (TREE_INT_CST_LOW (size));
2218
2219 #ifdef STACK_GROWS_DOWNWARD
2220 if (excess != 0)
2221 anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, excess));
2222 #endif
2223
2224 emit_push_insn (tem, TYPE_MODE (TREE_TYPE (pval)),
2225 expand_expr (size, 0, VOIDmode, 0),
2226 (TYPE_ALIGN (TREE_TYPE (pval))
2227 / BITS_PER_UNIT));
2228
2229 #ifndef STACK_GROWS_DOWNWARD
2230 if (excess != 0)
2231 anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, excess));
2232 #endif
2233 args_size += TREE_INT_CST_LOW (used);
2234 current_args_size += TREE_INT_CST_LOW (used);
2235 }
2236 }
2237
関数を呼ぶ前に、INSNを吐き出して、queueに入れる。
2238 /* Perform postincrements before actually calling the function. */ 2239 emit_queue (); 2240
2241 /* Pass the function the address in which to return a structure value. */
2242 if (structure_value_addr)
2243 {
2244 register rtx reg = gen_rtx (REG, Pmode, STRUCT_VALUE_REGNUM);
2245 emit_move_insn (reg, structure_value_addr);
2246 emit_insn (gen_rtx (USE, VOIDmode, reg));
2247 }
2248
関数コール
2249 gen_call_1 (expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0), 2250 /* ??? For Pascal, this must pass a context to get the static chain from 2251 in certain cases. */ 2252 0, 2253 args_size / GET_MODE_SIZE (SImode), args_size); 2254
2255 /* ??? Nothing has been done here to record control flow
2256 when contained functions can do nonlocal gotos. */ 2257
戻り値が無い
2258 /* If value type not void, return an rtx for the value. */ 2259 2260 if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode) 2261 return 0;
2262
2263 if (structure_value_addr)
2264 {
2265 if (target)
2266 return target;
2267 return gen_rtx (MEM, BLKmode, structure_value_addr);
2268 }
2269
2270 if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)))
2271 {
2272 copy_function_value (target);
2273 return target;
2274 }
2275 return function_value (TYPE_MODE (TREE_TYPE (exp))); 2276 }
情報[edit | edit source]
2091 /* Generate all the code for a function call 2092 and return an rtx for its value. 2093 Store the value in TARGET (specified as an rtx) if convenient. 2094 If the value is stored in TARGET then TARGET is returned. */
