00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #ifdef _KEEP_RCS_ID
00065 static char *rcs_id = "$Source: /proj/osprey/CVS/open64/osprey1.0/be/whirl2c/wn2c.cxx,v $ $Revision: 1.1.1.1 $";
00066 #endif
00067
00068
00069 #include <alloca.h>
00070 #include "whirl2c_common.h"
00071 #include "mempool.h"
00072 #include "const.h"
00073 #include "pf_cg.h"
00074 #include "region_util.h"
00075 #include "w2cf_parentize.h"
00076 #include "PUinfo.h"
00077 #include "wn2c.h"
00078 #include "wn2c_pragma.h"
00079 #include "st2c.h"
00080 #include "ty2c.h"
00081 #include "tcon2c.h"
00082 #include "wn2c_pragma.h"
00083 #include "ir_reader.h"
00084 #include "inttypes.h"
00085 #include "stdarg.h"
00086
00087 #if defined(__GNUC__) && (__GNUC__ >= 3)
00088 # define USING_HASH_SET 1
00089 # include <ext/hash_set>
00090 using namespace __gnu_cxx;
00091 #elif defined(__sgi) && !defined(__GNUC__)
00092 # define USING_HASH_SET 1
00093 # include <hash_set>
00094 #else
00095 # include <set>
00096 #endif
00097
00098 #if defined(_AIX) || defined(sun)
00099 #include <strings.h>
00100 #endif
00101
00102 #include <vector>
00103
00104 #define WN_pragma_nest(wn) WN_pragma_arg1(wn)
00105
00106
00107
00108
00109
00110
00111
00112
00113 #define WN2C_assignment_compatible_types(lhs_ty, rhs_ty) \
00114 Stab_Assignment_Compatible_Types(lhs_ty, rhs_ty, \
00115 FALSE, \
00116 FALSE, \
00117 FALSE)
00118
00119 #define WN2C_compatible_lvalues(lhs_ty, rhs_ty) \
00120 Stab_Assignment_Compatible_Types(lhs_ty, rhs_ty, \
00121 FALSE, \
00122 TRUE, \
00123 FALSE)
00124
00125 #define WN2C_arithmetic_compatible_types(t1, t2) \
00126 Stab_Identical_Types(t1, t2, \
00127 FALSE, \
00128 TRUE, \
00129 FALSE)
00130
00131 #define WN2C_compatible_qualified_types(t1, t2) \
00132 Stab_Identical_Types(t1, t2, \
00133 TRUE, \
00134 TRUE, \
00135 FALSE)
00136
00137 #define WN2C_array_lvalue_as_ptr(ptr_to_array, ptr) \
00138 (TY_Is_Pointer(ptr) && \
00139 TY_Is_Pointer(ptr_to_array) && \
00140 TY_Is_Array(TY_pointed(ptr_to_array)) && \
00141 WN2C_arithmetic_compatible_types(TY_AR_etype(TY_pointed(ptr_to_array)), \
00142 TY_pointed(ptr)))
00143
00144
00145 static BOOL
00146 WN2C_is_pointer_diff(OPCODE op, const WN *kid0, const WN *kid1)
00147 {
00148 TY_IDX ty0, ty1;
00149 BOOL is_pointer_diff = FALSE;
00150
00151 if (OPCODE_operator(op) == OPR_ASHR &&
00152 WN_operator(kid0) == OPR_SUB &&
00153 WN_operator(kid1) == OPR_INTCONST)
00154 {
00155 ty0 = WN_Tree_Type(WN_kid0(kid0));
00156 ty1 = WN_Tree_Type(WN_kid1(kid0));
00157
00158 if (TY_Is_Pointer(ty0) && TY_Is_Pointer(ty1) &&
00159 TY_size(TY_pointed(ty0)) == TY_size(TY_pointed(ty1)) &&
00160 TY_size(TY_pointed(ty0)) >> WN_const_val(kid1) == 1)
00161 is_pointer_diff = TRUE;
00162 }
00163 return is_pointer_diff;
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173 static const char WN2C_Purple_Region_Name[] = "prp___region";
00174 static const char WN2C_Return_Value_Name[] = "_RetVal";
00175 static BOOL WN2C_Used_Return_Value = FALSE;
00176
00177
00178
00179
00180
00181
00182
00183
00184 static const RETURNSITE *WN2C_Next_ReturnSite = NULL;
00185 static const CALLSITE *WN2C_Prev_CallSite = NULL;
00186
00187 static char last_ret_tmp[64];
00188
00189 static BOOL
00190 WN2C_Skip_Stmt(const WN *stmt)
00191 {
00192 return ((W2C_No_Pragmas && \
00193 (WN_operator(stmt) == OPR_PRAGMA ||
00194 WN_operator(stmt) == OPR_XPRAGMA) &&
00195 WN_pragma(stmt) != WN_PRAGMA_PREAMBLE_END) || \
00196
00197 WN2C_Skip_Pragma_Stmt(stmt) ||
00198
00199 (!W2C_Emit_Prefetch &&
00200 (WN_operator(stmt) == OPR_PREFETCH ||
00201 WN_operator(stmt) == OPR_PREFETCHX)) ||
00202
00203 (WN2C_Next_ReturnSite != NULL &&
00204 (stmt == RETURNSITE_store1(WN2C_Next_ReturnSite) ||
00205 stmt == RETURNSITE_store2(WN2C_Next_ReturnSite))) ||
00206
00207 (WN2C_Prev_CallSite != NULL &&
00208 (stmt == CALLSITE_store1(WN2C_Prev_CallSite) ||
00209 stmt == CALLSITE_store2(WN2C_Prev_CallSite))) ||
00210
00211 (WN_operator(stmt) == OPR_COMMENT &&
00212 strcmp(Index_To_Str(WN_GetComment(stmt)), "ENDLOOP") == 0)
00213 );
00214 }
00215
00216
00217
00218
00219
00220
00221
00222 static STATUS WN2C_lda_label(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00223 static STATUS WN2C_ignore(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00224 static STATUS WN2C_unsupported(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00225 static STATUS WN2C_binaryop(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00226 static STATUS WN2C_unaryop(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00227 static STATUS WN2C_func_entry(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00228 static STATUS WN2C_block(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00229 static STATUS WN2C_region(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00230 static STATUS WN2C_switch(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00231 static STATUS WN2C_compgoto(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00232 static STATUS WN2C_do_loop(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00233 static STATUS WN2C_do_while(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00234 static STATUS WN2C_while_do(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00235 static STATUS WN2C_if(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00236 static STATUS WN2C_goto(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00237 static STATUS WN2C_condbr(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00238 static STATUS WN2C_return(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00239 static STATUS WN2C_return_val(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00240 static STATUS WN2C_label(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00241 static STATUS WN2C_exc_scope_end(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00242 static STATUS WN2C_exc_scope_begin(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00243 static STATUS WN2C_istore(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00244 static STATUS WN2C_istorex(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00245 static STATUS WN2C_mstore(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00246 static STATUS WN2C_stid(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00247 static STATUS WN2C_call(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00248 static STATUS WN2C_eval(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00249 static STATUS WN2C_prefetch(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00250 static STATUS WN2C_comment(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00251 static STATUS WN2C_iload(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00252 static STATUS WN2C_iloadx(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00253 static STATUS WN2C_mload(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00254 static STATUS WN2C_array(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00255 static STATUS WN2C_intrinsic_op(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00256 static STATUS WN2C_tas(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00257 static STATUS WN2C_select(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00258 static STATUS WN2C_cvt(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00259 static STATUS WN2C_cvtl(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00260 static STATUS WN2C_realpart(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00261 static STATUS WN2C_imagpart(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00262 static STATUS WN2C_paren(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00263 static STATUS WN2C_complex(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00264 static STATUS WN2C_bnor(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00265 static STATUS WN2C_madd(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00266 static STATUS WN2C_msub(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00267 static STATUS WN2C_nmadd(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00268 static STATUS WN2C_nmsub(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00269 static STATUS WN2C_ldid(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00270 static STATUS WN2C_lda(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00271 static STATUS WN2C_const(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00272 static STATUS WN2C_intconst(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00273 static STATUS WN2C_parm(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00274 static STATUS WN2C_comma(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00275 static STATUS WN2C_rcomma(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00276 static STATUS WN2C_alloca(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00277 static STATUS WN2C_dealloca(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00278 static STATUS WN2C_asm_stmt(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00279 static STATUS WN2C_extract_bits(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00280 static STATUS WN2C_agoto(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context);
00281
00282 typedef STATUS (*WN2C_HANDLER_FUNC)(TOKEN_BUFFER, const WN*, CONTEXT);
00283
00284 typedef const WN * CWN;
00285 CWN *last_loc;
00286
00287
00288
00289
00290
00291
00292
00293 #define NUMBER_OF_OPERATORS (OPERATOR_LAST + 1)
00294 static WN2C_HANDLER_FUNC WN2C_Opr_Handler[NUMBER_OF_OPERATORS];
00295
00296 typedef struct Opr2handler
00297 {
00298 OPERATOR opr;
00299 WN2C_HANDLER_FUNC handler;
00300 } OPR2HANDLER;
00301
00302 #define NUMBER_OF_OPR2HANDLER_MAPS \
00303 (sizeof(WN2C_Opr_Handler_Map) / sizeof(OPR2HANDLER))
00304
00305 static const OPR2HANDLER WN2C_Opr_Handler_Map[] =
00306 {
00307 {OPR_FUNC_ENTRY, &WN2C_func_entry},
00308 {OPR_BLOCK, &WN2C_block},
00309 {OPR_REGION, &WN2C_region},
00310 {OPR_REGION_EXIT, &WN2C_goto},
00311 {OPR_COMPGOTO, &WN2C_compgoto},
00312 {OPR_SWITCH, &WN2C_switch},
00313 {OPR_DO_LOOP, &WN2C_do_loop},
00314 {OPR_DO_WHILE, &WN2C_do_while},
00315 {OPR_WHILE_DO, &WN2C_while_do},
00316 {OPR_IF, &WN2C_if},
00317 {OPR_GOTO, &WN2C_goto},
00318 {OPR_CASEGOTO, &WN2C_goto},
00319 {OPR_FALSEBR, &WN2C_condbr},
00320 {OPR_TRUEBR, &WN2C_condbr},
00321 {OPR_RETURN, &WN2C_return},
00322 {OPR_RETURN_VAL, &WN2C_return_val},
00323 {OPR_LABEL, &WN2C_label},
00324 {OPR_EXC_SCOPE_BEGIN, &WN2C_exc_scope_begin},
00325 {OPR_EXC_SCOPE_END, &WN2C_exc_scope_end},
00326 {OPR_ISTORE, &WN2C_istore},
00327 {OPR_ISTOREX, &WN2C_istorex},
00328 {OPR_MSTORE, &WN2C_mstore},
00329 {OPR_STID, &WN2C_stid},
00330 {OPR_CALL, &WN2C_call},
00331 {OPR_INTRINSIC_CALL, &WN2C_call},
00332 {OPR_ICALL, &WN2C_call},
00333 {OPR_PICCALL, &WN2C_call},
00334 {OPR_EVAL, &WN2C_eval},
00335 {OPR_PRAGMA, &WN2C_pragma},
00336 {OPR_XPRAGMA, &WN2C_pragma},
00337 {OPR_PREFETCH, &WN2C_prefetch},
00338 {OPR_PREFETCHX, &WN2C_prefetch},
00339 {OPR_COMMENT, &WN2C_comment},
00340 {OPR_ILOAD, &WN2C_iload},
00341 {OPR_ILOADX, &WN2C_iloadx},
00342 {OPR_MLOAD, &WN2C_mload},
00343 {OPR_ARRAY, &WN2C_array},
00344 {OPR_INTRINSIC_OP, &WN2C_intrinsic_op},
00345 {OPR_TAS, &WN2C_tas},
00346 {OPR_SELECT, &WN2C_select},
00347 {OPR_CSELECT, &WN2C_select},
00348 {OPR_CVT, &WN2C_cvt},
00349 {OPR_CVTL, &WN2C_cvtl},
00350 {OPR_NEG, &WN2C_unaryop},
00351 {OPR_ABS, &WN2C_unaryop},
00352 {OPR_SQRT, &WN2C_unaryop},
00353 {OPR_REALPART, &WN2C_realpart},
00354 {OPR_IMAGPART, &WN2C_imagpart},
00355 {OPR_PAREN, &WN2C_paren},
00356 {OPR_RND, &WN2C_unaryop},
00357 {OPR_TRUNC, &WN2C_unaryop},
00358 {OPR_CEIL, &WN2C_unaryop},
00359 {OPR_FLOOR, &WN2C_unaryop},
00360 {OPR_BNOT, &WN2C_unaryop},
00361 {OPR_LNOT, &WN2C_unaryop},
00362 {OPR_ADD, &WN2C_binaryop},
00363 {OPR_SUB, &WN2C_binaryop},
00364 {OPR_MPY, &WN2C_binaryop},
00365 {OPR_DIV, &WN2C_binaryop},
00366 {OPR_MOD, &WN2C_binaryop},
00367 {OPR_REM, &WN2C_binaryop},
00368 {OPR_MAX, &WN2C_binaryop},
00369 {OPR_MIN, &WN2C_binaryop},
00370 {OPR_BAND, &WN2C_binaryop},
00371 {OPR_BIOR, &WN2C_binaryop},
00372 {OPR_BNOR, &WN2C_bnor},
00373 {OPR_BXOR, &WN2C_binaryop},
00374 {OPR_LAND, &WN2C_binaryop},
00375 {OPR_LIOR, &WN2C_binaryop},
00376 {OPR_CAND, &WN2C_binaryop},
00377 {OPR_CIOR, &WN2C_binaryop},
00378 {OPR_SHL, &WN2C_binaryop},
00379 {OPR_ASHR, &WN2C_binaryop},
00380 {OPR_LSHR, &WN2C_binaryop},
00381 {OPR_COMPLEX, &WN2C_complex},
00382 {OPR_RECIP, &WN2C_unaryop},
00383 {OPR_RSQRT, &WN2C_unaryop},
00384 {OPR_MADD, &WN2C_madd},
00385 {OPR_MSUB, &WN2C_msub},
00386 {OPR_NMADD, &WN2C_nmadd},
00387 {OPR_NMSUB, &WN2C_nmsub},
00388 {OPR_EQ, &WN2C_binaryop},
00389 {OPR_NE, &WN2C_binaryop},
00390 {OPR_GT, &WN2C_binaryop},
00391 {OPR_GE, &WN2C_binaryop},
00392 {OPR_LT, &WN2C_binaryop},
00393 {OPR_LE, &WN2C_binaryop},
00394 {OPR_LDID, &WN2C_ldid},
00395 {OPR_LDA, &WN2C_lda},
00396 {OPR_CONST, &WN2C_const},
00397 {OPR_INTCONST, &WN2C_intconst},
00398 {OPR_PARM, &WN2C_parm},
00399 {OPR_TRAP, &WN2C_ignore},
00400 {OPR_ASSERT, &WN2C_ignore},
00401 {OPR_FORWARD_BARRIER, &WN2C_ignore},
00402 {OPR_BACKWARD_BARRIER, &WN2C_ignore},
00403 {OPR_COMMA, &WN2C_comma},
00404 {OPR_RCOMMA, &WN2C_rcomma},
00405 {OPR_ALLOCA, &WN2C_alloca},
00406 {OPR_DEALLOCA, &WN2C_dealloca},
00407 #ifdef KEY
00408 {OPR_LDMA, &WN2C_lda},
00409 {OPR_ASM_STMT, &WN2C_asm_stmt},
00410 {OPR_RROTATE, &WN2C_binaryop},
00411 {OPR_LDA_LABEL, &WN2C_lda},
00412 {OPR_GOTO_OUTER_BLOCK, &WN2C_goto},
00413 {OPR_EXTRACT_BITS, &WN2C_unaryop},
00414 {OPR_COMPOSE_BITS, &WN2C_binaryop},
00415 #endif
00416 {OPR_AGOTO, &WN2C_agoto},
00417 };
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 #define WN2C_IS_INFIX_OP(opc) \
00430 ((WN2C_Opc2cname[opc]!=NULL)? (WN2C_Opc2cname[opc][0]!='_') : FALSE)
00431
00432 #ifdef TARG_NVISA
00433
00434 #define WN2C_IS_FUNCALL_OP(opc) \
00435 (WN2C_Opc2cname[opc]!=NULL)
00436 #else
00437 #define WN2C_IS_FUNCALL_OP(opc) \
00438 ((WN2C_Opc2cname[opc]!=NULL)? (WN2C_Opc2cname[opc][0]=='_') : FALSE)
00439 #endif
00440
00441
00442
00443
00444
00445
00446
00447
00448 #define NUMBER_OF_OPCODES (OPCODE_LAST+1)
00449 static const char *WN2C_Opc2cname[NUMBER_OF_OPCODES];
00450
00451
00452 typedef struct Opc2Cname_Map
00453 {
00454 OPCODE opc;
00455 const char *cname;
00456 } OPC2CNAME_MAP;
00457
00458 #define NUMBER_OF_OPC2CNAME_MAPS \
00459 sizeof(WN2C_Opc2cname_Map) / sizeof(OPC2CNAME_MAP)
00460 static const OPC2CNAME_MAP WN2C_Opc2cname_Map[] =
00461 {
00462 {OPC_U8NEG, "-"},
00463 #ifdef TARG_IA64
00464 {OPC_F10NEG, "-"},
00465 #endif
00466 {OPC_FQNEG, "-"},
00467 {OPC_I8NEG, "-"},
00468 {OPC_U4NEG, "-"},
00469 {OPC_CQNEG, "_CQNEG"},
00470 {OPC_F8NEG, "-"},
00471 {OPC_C8NEG, "_C8NEG"},
00472 {OPC_I4NEG, "-"},
00473 {OPC_F4NEG, "-"},
00474 {OPC_C4NEG, "_C4NEG"},
00475 {OPC_I4ABS, "_I4ABS"},
00476 {OPC_F4ABS, "_F4ABS"},
00477 #ifdef TARG_IA64
00478 {OPC_F10ABS, "_F10ABS"},
00479 #endif
00480 {OPC_FQABS, "_FQABS"},
00481 {OPC_I8ABS, "_I8ABS"},
00482 {OPC_F8ABS, "_F8ABS"},
00483 {OPC_F4SQRT, "_F4SQRT"},
00484 {OPC_C4SQRT, "_C4SQRT"},
00485 #ifdef TARG_IA64
00486 {OPC_F10SQRT, "_F10SQRT"},
00487 #endif
00488 {OPC_FQSQRT, "_FQSQRT"},
00489 {OPC_CQSQRT, "_CQSQRT"},
00490 {OPC_F8SQRT, "_F8SQRT"},
00491 {OPC_C8SQRT, "_C8SQRT"},
00492 {OPC_I4F4RND, "_I4F4RND"},
00493 #ifdef TARG_IA64
00494 {OPC_I4F10RND, "_I4F10RND"},
00495 #endif
00496 {OPC_I4FQRND, "_I4FQRND"},
00497 {OPC_I4F8RND, "_I4F8RND"},
00498 {OPC_U4F4RND, "_U4F4RND"},
00499 #ifdef TARG_IA64
00500 {OPC_U4F10RND, "_U4F10RND"},
00501 #endif
00502 {OPC_U4FQRND, "_U4FQRND"},
00503 {OPC_U4F8RND, "_U4F8RND"},
00504 {OPC_I8F4RND, "_I8F4RND"},
00505 {OPC_I8F10RND, "_I8F10RND"},
00506 {OPC_I8FQRND, "_I8FQRND"},
00507 {OPC_I8F8RND, "_I8F8RND"},
00508 {OPC_U8F4RND, "_U8F4RND"},
00509 #ifdef TARG_IA64
00510 {OPC_U8F10RND, "_U8F10RND"},
00511 #endif
00512 {OPC_U8FQRND, "_U8FQRND"},
00513 {OPC_U8F8RND, "_U8F8RND"},
00514 {OPC_I4F4TRUNC, "_I4F4TRUNC"},
00515 #ifdef TARG_IA64
00516 {OPC_I4F10TRUNC, "_I4F10TRUNC"},
00517 #endif
00518 {OPC_I4FQTRUNC, "_I4FQTRUNC"},
00519 {OPC_I4F8TRUNC, "_I4F8TRUNC"},
00520 {OPC_U4F4TRUNC, "_U4F8TRUNC"},
00521 #ifdef TARG_IA64
00522 {OPC_U4F10TRUNC, "_U4F10TRUNC"},
00523 {OPC_U4FQTRUNC, "_U4FQTRUNC"},
00524 #else
00525 {OPC_U4FQTRUNC, "_U4F8TRUNC"},
00526 #endif
00527 {OPC_U4F8TRUNC, "_U4F8TRUNC"},
00528 {OPC_I8F4TRUNC, "_I8F4TRUNC"},
00529 #ifdef TARG_IA64
00530 {OPC_I8F10TRUNC, "_I8F10TRUNC"},
00531 #endif
00532 {OPC_I8FQTRUNC, "_I8FQTRUNC"},
00533 {OPC_I8F8TRUNC, "_I8F8TRUNC"},
00534 {OPC_U8F4TRUNC, "_U8F8TRUNC"},
00535 #ifdef TARG_NVISA
00536 {OPC_F4F4TRUNC, "truncf"},
00537 {OPC_F8F8TRUNC, "trunc"},
00538 #endif
00539 #ifdef TARG_IA64
00540 {OPC_U8F10TRUNC, "_U8F10TRUNC"},
00541 {OPC_U8FQTRUNC, "_U8FQTRUNC"},
00542 #else
00543 {OPC_U8FQTRUNC, "_U8F8TRUNC"},
00544 #endif
00545 {OPC_U8F8TRUNC, "_U8F8TRUNC"},
00546 {OPC_I4F4CEIL, "_I4F4CEIL"},
00547 #ifdef TARG_IA64
00548 {OPC_I4F10CEIL, "_I4F10CEIL"},
00549 #endif
00550 {OPC_I4FQCEIL, "_I4FQCEIL"},
00551 {OPC_I4F8CEIL, "_I4F8CEIL"},
00552 {OPC_U4F4CEIL, "_U4F8CEIL"},
00553 #ifdef TARG_IA64
00554 {OPC_U4F10CEIL, "_U4F10CEIL"},
00555 {OPC_U4FQCEIL, "_U4FQCEIL"},
00556 #else
00557 {OPC_U4FQCEIL, "_U4F8CEIL"},
00558 #endif
00559 {OPC_U4F8CEIL, "_U4F8CEIL"},
00560 {OPC_I8F4CEIL, "_I8F4CEIL"},
00561 #ifdef TARG_IA64
00562 {OPC_I8F10CEIL, "_I8F10CEIL"},
00563 #endif
00564 {OPC_I8FQCEIL, "_I8FQCEIL"},
00565 {OPC_I8F8CEIL, "_I8F8CEIL"},
00566 {OPC_U8F4CEIL, "_U8F4CEIL"},
00567 #ifdef TARG_IA64
00568 {OPC_U8F10CEIL, "_U8F10CEIL"},
00569 #endif
00570 {OPC_U8FQCEIL, "_U8FQCEIL"},
00571 {OPC_U8F8CEIL, "_U8F8CEIL"},
00572 {OPC_I4F4FLOOR, "_I4F4FLOOR"},
00573 #ifdef TARG_NVISA
00574 {OPC_F4F4CEIL, "ceilf"},
00575 {OPC_F8F8CEIL, "ceil"},
00576 #endif
00577 #ifdef TARG_IA64
00578 {OPC_I4F10FLOOR, "_I4F10FLOOR"},
00579 #endif
00580 {OPC_I4FQFLOOR, "_I4FQFLOOR"},
00581 {OPC_I4F8FLOOR, "_I4F8FLOOR"},
00582 {OPC_U4F4FLOOR, "_U4F4FLOOR"},
00583 #ifdef TARG_IA64
00584 {OPC_U4F10FLOOR, "_U4F10FLOOR"},
00585 #endif
00586 {OPC_U4FQFLOOR, "_U4FQFLOOR"},
00587 {OPC_U4F8FLOOR, "_U4F8FLOOR"},
00588 {OPC_I8F4FLOOR, "_I8F4FLOOR"},
00589 #ifdef TARG_IA64
00590 {OPC_I8F10FLOOR, "_I8F10FLOOR"},
00591 #endif
00592 {OPC_I8FQFLOOR, "_I8FQFLOOR"},
00593 {OPC_I8F8FLOOR, "_I8F8FLOOR"},
00594 {OPC_U8F4FLOOR, "_U8F4FLOOR"},
00595 #ifdef TARG_NVISA
00596 {OPC_F4F4FLOOR, "floorf"},
00597 {OPC_F8F8FLOOR, "floor"},
00598 #endif
00599 #ifdef TARG_IA64
00600 {OPC_U8F10FLOOR, "_U8F10FLOOR"},
00601 #endif
00602 {OPC_U8FQFLOOR, "_U8FQFLOOR"},
00603 {OPC_U8F8FLOOR, "_U8F8FLOOR"},
00604 #ifdef KEY
00605 {OPC_F4F4FLOOR, "_F4F4FLOOR"},
00606 #endif
00607 {OPC_I4BNOT, "~"},
00608 {OPC_U8BNOT, "~"},
00609 {OPC_I8BNOT, "~"},
00610 {OPC_U4BNOT, "~"},
00611
00612
00613 {OPC_BLNOT, "!"},
00614 {OPC_I4LNOT, "!"},
00615
00616 {OPC_U8ADD, "+"},
00617 #ifdef TARG_IA64
00618 {OPC_F10ADD, "+"},
00619 #endif
00620 {OPC_FQADD, "+"},
00621 {OPC_I8ADD, "+"},
00622 {OPC_U4ADD, "+"},
00623 {OPC_CQADD, "_CQADD"},
00624 {OPC_F8ADD, "+"},
00625 {OPC_C8ADD, "_C8ADD"},
00626 {OPC_I4ADD, "+"},
00627 {OPC_F4ADD, "+"},
00628 {OPC_C4ADD, "_C4ADD"},
00629 {OPC_U8SUB, "-"},
00630 #ifdef TARG_IA64
00631 {OPC_F10SUB, "-"},
00632 #endif
00633 {OPC_FQSUB, "-"},
00634 {OPC_I8SUB, "-"},
00635 {OPC_U4SUB, "-"},
00636 {OPC_CQSUB, "_CQSUB"},
00637 {OPC_F8SUB, "-"},
00638 {OPC_C8SUB, "_C8SUB"},
00639 {OPC_I4SUB, "-"},
00640 {OPC_F4SUB, "-"},
00641 {OPC_C4SUB, "_C4SUB"},
00642 {OPC_U8MPY, "*"},
00643 #ifdef TARG_IA64
00644 {OPC_F10MPY, "*"},
00645 #endif
00646 {OPC_FQMPY, "*"},
00647 {OPC_I8MPY, "*"},
00648 {OPC_U4MPY, "*"},
00649 {OPC_CQMPY, "_CQMPY"},
00650 {OPC_F8MPY, "*"},
00651 {OPC_C8MPY, "_C8MPY"},
00652 {OPC_I4MPY, "*"},
00653 {OPC_F4MPY, "*"},
00654 {OPC_C4MPY, "_C4MPY"},
00655 {OPC_U8DIV, "/"},
00656 #ifdef TARG_IA64
00657 {OPC_F10DIV, "/"},
00658 #endif
00659 {OPC_FQDIV, "/"},
00660 {OPC_I8DIV, "/"},
00661 {OPC_U4DIV, "/"},
00662 {OPC_CQDIV, "_CQDIV"},
00663 {OPC_F8DIV, "/"},
00664 {OPC_C8DIV, "_C8DIV"},
00665 {OPC_I4DIV, "/"},
00666 {OPC_F4DIV, "/"},
00667 {OPC_C4DIV, "_C4DIV"},
00668 {OPC_I4MOD, "_I4MOD"},
00669 {OPC_U8MOD, "%"},
00670 {OPC_I8MOD, "_I8MOD"},
00671 {OPC_U4MOD, "%"},
00672 {OPC_I4REM, "%"},
00673 {OPC_U8REM, "%"},
00674 {OPC_I8REM, "%"},
00675 {OPC_U4REM, "%"},
00676 {OPC_I4MAX, "_I4MAX"},
00677 {OPC_U8MAX, "_U8MAX"},
00678 {OPC_F4MAX, "_F4MAX"},
00679 #ifdef TARG_IA64
00680 {OPC_F10MAX, "_F10MAX"},
00681 #endif
00682 {OPC_FQMAX, "_FQMAX"},
00683 {OPC_I8MAX, "_I8MAX"},
00684 {OPC_U4MAX, "_U4MAX"},
00685 {OPC_F8MAX, "_F8MAX"},
00686 {OPC_I4MIN, "_I4MIN"},
00687 {OPC_U8MIN, "_U8MIN"},
00688 {OPC_F4MIN, "_F4MIN"},
00689 #ifdef TARG_IA64
00690 {OPC_F10MIN, "_F10MIN"},
00691 #endif
00692 {OPC_FQMIN, "_FQMIN"},
00693 {OPC_I8MIN, "_I8MIN"},
00694 {OPC_U4MIN, "_U4MIN"},
00695 {OPC_F8MIN, "_F8MIN"},
00696 {OPC_I4BAND, "&"},
00697 {OPC_U8BAND, "&"},
00698 {OPC_I8BAND, "&"},
00699 {OPC_U4BAND, "&"},
00700 {OPC_I4BIOR, "|"},
00701 {OPC_U8BIOR, "|"},
00702 {OPC_I8BIOR, "|"},
00703 {OPC_U4BIOR, "|"},
00704 {OPC_I4BXOR, "^"},
00705 {OPC_U8BXOR, "^"},
00706 {OPC_I8BXOR , "^"},
00707 {OPC_U4BXOR, "^"},
00708
00709
00710 {OPC_BLAND, "&&"},
00711 {OPC_I4LAND, "&&"},
00712 {OPC_BLIOR, "||"},
00713 {OPC_I4LIOR, "||"},
00714 {OPC_BCAND, "&&"},
00715 {OPC_I4CAND, "&&"},
00716 {OPC_BCIOR, "||"},
00717 {OPC_I4CIOR, "||"},
00718
00719 {OPC_I4SHL, "_I4SHL"},
00720 {OPC_U8SHL, "_U8SHL"},
00721 {OPC_I8SHL, "_I8SHL"},
00722 {OPC_U4SHL, "_U4SHL"},
00723 {OPC_I4ASHR, "_I4ASHR"},
00724 {OPC_U8ASHR, "_U8ASHR"},
00725 {OPC_I8ASHR, "_I8ASHR"},
00726 {OPC_U4ASHR, "_U4ASHR"},
00727 {OPC_I4LSHR, "_I4LSHR"},
00728 {OPC_U8LSHR, "_U8LSHR"},
00729 {OPC_I8LSHR, "_I8LSHR"},
00730 {OPC_U4LSHR, "_U4LSHR"},
00731 {OPC_F4RECIP, "_F4RECIP"},
00732 {OPC_C4RECIP, "_C4RECIP"},
00733 #ifdef TARG_IA64
00734 {OPC_F10RECIP, "_F10RECIP"},
00735 #endif
00736 {OPC_FQRECIP, "_FQRECIP"},
00737 {OPC_CQRECIP, "_CQRECIP"},
00738 {OPC_F8RECIP, "_F8RECIP"},
00739 {OPC_C8RECIP, "_C8RECIP"},
00740 {OPC_F4RSQRT, "_F4RSQRT"},
00741 {OPC_C4RSQRT, "_C4RSQRT"},
00742 #ifdef TARG_IA64
00743 {OPC_F10RSQRT, "_F10RSQRT"},
00744 #endif
00745 {OPC_FQRSQRT, "_FQRSQRT"},
00746 {OPC_CQRSQRT, "_CQRSQRT"},
00747 {OPC_F8RSQRT, "_F8RSQRT"},
00748 {OPC_C8RSQRT, "_C8RSQRT"},
00749
00750
00751 {OPC_BU8EQ, "=="},
00752 #ifdef TARG_IA64
00753 {OPC_BF10EQ, "=="},
00754 #endif
00755 {OPC_BFQEQ, "=="},
00756 {OPC_BI8EQ, "=="},
00757 {OPC_BU4EQ, "=="},
00758 {OPC_BCQEQ, "=="},
00759 {OPC_BF8EQ, "=="},
00760 {OPC_BC8EQ, "=="},
00761 {OPC_BI4EQ, "=="},
00762 {OPC_BF4EQ, "=="},
00763 {OPC_BC4EQ, "=="},
00764 #ifdef TARG_IA64
00765 {OPC_I8I4EQ, "=="},
00766 {OPC_I8I4NE, "!="},
00767 #endif
00768 {OPC_BU8NE, "!="},
00769 #ifdef TARG_IA64
00770 {OPC_BF10NE, "!="},
00771 #endif
00772 {OPC_BFQNE, "!="},
00773 {OPC_BI8NE, "!="},
00774 {OPC_BU4NE, "!="},
00775 {OPC_BCQNE, "!="},
00776 {OPC_BF8NE, "!="},
00777 {OPC_BC8NE, "!="},
00778 {OPC_BI4NE, "!="},
00779 {OPC_BF4NE, "!="},
00780 {OPC_BC4NE, "!="},
00781 {OPC_BI4GT, ">"},
00782 {OPC_BU8GT, ">"},
00783 {OPC_BF4GT, ">"},
00784 #ifdef TARG_IA64
00785 {OPC_BF10GT, ">"},
00786 #endif
00787 {OPC_BFQGT, ">"},
00788 {OPC_BI8GT, ">"},
00789 {OPC_BU4GT, ">"},
00790 {OPC_BF8GT, ">"},
00791 {OPC_BI4GE, ">="},
00792 {OPC_BU8GE, ">="},
00793 {OPC_BF4GE, ">="},
00794 #ifdef TARG_IA64
00795 {OPC_BF10GE, ">="},
00796 #endif
00797 {OPC_BFQGE, ">="},
00798 {OPC_BI8GE, ">="},
00799 {OPC_BU4GE, ">="},
00800 {OPC_BF8GE, ">="},
00801 {OPC_BI4LT, "<"},
00802 {OPC_BU8LT, "<"},
00803 {OPC_BF4LT, "<"},
00804 #ifdef TARG_IA64
00805 {OPC_BF10LT, "<"},
00806 #endif
00807 {OPC_BFQLT, "<"},
00808 {OPC_BI8LT, "<"},
00809 {OPC_BU4LT, "<"},
00810 {OPC_BF8LT, "<"},
00811 {OPC_BI4LE, "<="},
00812 {OPC_BU8LE, "<="},
00813 {OPC_BF4LE, "<="},
00814 #ifdef TARG_IA64
00815 {OPC_BF10LE, "<="},
00816 #endif
00817 {OPC_BFQLE, "<="},
00818 {OPC_BI8LE, "<="},
00819 {OPC_BU4LE, "<="},
00820 {OPC_BF8LE, "<="},
00821 #ifdef TARG_IA64
00822 {OPC_I4U8EQ, "=="},
00823 {OPC_I4F10EQ, "=="},
00824 {OPC_I4FQEQ, "=="},
00825 {OPC_I4I8EQ, "=="},
00826 {OPC_I4U4EQ, "=="},
00827 {OPC_I4CQEQ, "=="},
00828 {OPC_I4F8EQ, "=="},
00829 {OPC_I4C8EQ, "=="},
00830 #endif
00831 {OPC_I4I4EQ, "=="},
00832 #ifdef TARG_X8664
00833 {OPC_I4U4EQ, "=="},
00834 {OPC_I4I8EQ, "=="},
00835 {OPC_I4U8EQ, "=="},
00836 #endif
00837 {OPC_I4F4EQ, "=="},
00838 #ifdef TARG_X8664
00839 {OPC_I4F8EQ, "=="},
00840 {OPC_I4FQEQ, "=="},
00841 #endif
00842 {OPC_I4C4EQ, "=="},
00843 #ifndef TARG_X8664
00844 {OPC_I4U8NE, "!="},
00845 {OPC_I4F10NE, "!="},
00846 {OPC_I4FQNE, "!="},
00847 {OPC_I4I8NE, "!="},
00848 {OPC_I4U4NE, "!="},
00849 {OPC_I4CQNE, "!="},
00850 {OPC_I4F8NE, "!="},
00851 {OPC_I4C8NE, "!="},
00852 #else
00853 {OPC_I4C8EQ, "=="},
00854 {OPC_I4CQEQ, "=="},
00855 {OPC_I8I4EQ, "=="},
00856 {OPC_I8U4EQ, "=="},
00857 {OPC_I8I8EQ, "=="},
00858 {OPC_I8U8EQ, "=="},
00859 {OPC_I8F4EQ, "=="},
00860 {OPC_I8F8EQ, "=="},
00861 {OPC_I8FQEQ, "=="},
00862 {OPC_I8C4EQ, "=="},
00863 {OPC_I8C8EQ, "=="},
00864 {OPC_I8CQEQ, "=="},
00865 {OPC_U4I4EQ, "=="},
00866 {OPC_U4U4EQ, "=="},
00867 {OPC_U4I8EQ, "=="},
00868 {OPC_U4U8EQ, "=="},
00869 {OPC_U4F4EQ, "=="},
00870 {OPC_U4F8EQ, "=="},
00871 {OPC_U4FQEQ, "=="},
00872 {OPC_U4C4EQ, "=="},
00873 {OPC_U4C8EQ, "=="},
00874 {OPC_U4CQEQ, "=="},
00875 {OPC_U8I4EQ, "=="},
00876 {OPC_U8U4EQ, "=="},
00877 {OPC_U8I8EQ, "=="},
00878 {OPC_U8U8EQ, "=="},
00879 {OPC_U8F4EQ, "=="},
00880 {OPC_U8F8EQ, "=="},
00881 {OPC_U8FQEQ, "=="},
00882 {OPC_U8C4EQ, "=="},
00883 {OPC_U8C8EQ, "=="},
00884 {OPC_U8CQEQ, "=="},
00885 #endif
00886 {OPC_I4I4NE, "!="},
00887 #ifdef TARG_X8664
00888 {OPC_I4U4NE, "!="},
00889 {OPC_I4I8NE, "!="},
00890 {OPC_I4U8NE, "!="},
00891 #endif
00892 {OPC_I4F4NE, "!="},
00893 #ifdef TARG_X8664
00894 {OPC_I4F8NE, "!="},
00895 {OPC_I4FQNE, "!="},
00896 #endif
00897 {OPC_I4C4NE, "!="},
00898 #ifndef TARG_X8664
00899 {OPC_I4I4GT, ">"},
00900 {OPC_I4U8GT, ">"},
00901 {OPC_I4F4GT, ">"},
00902 {OPC_I4F10GT, ">"},
00903 {OPC_I4FQGT, ">"},
00904 {OPC_I4I8GT, ">"},
00905 {OPC_I4U4GT, ">"},
00906 {OPC_I4F8GT, ">"},
00907 #else
00908 {OPC_I4C8NE, "!="},
00909 {OPC_I4CQNE, "!="},
00910 {OPC_I8I4NE, "!="},
00911 {OPC_I8U4NE, "!="},
00912 {OPC_I8I8NE, "!="},
00913 {OPC_I8U8NE, "!="},
00914 {OPC_I8F4NE, "!="},
00915 {OPC_I8F8NE, "!="},
00916 {OPC_I8FQNE, "!="},
00917 {OPC_I8C4NE, "!="},
00918 {OPC_I8C8NE, "!="},
00919 {OPC_I8CQNE, "!="},
00920 {OPC_U4I4NE, "!="},
00921 {OPC_U4U4NE, "!="},
00922 {OPC_U4I8NE, "!="},
00923 {OPC_U4U8NE, "!="},
00924 {OPC_U4F4NE, "!="},
00925 {OPC_U4F8NE, "!="},
00926 {OPC_U4FQNE, "!="},
00927 {OPC_U4C4NE, "!="},
00928 {OPC_U4C8NE, "!="},
00929 {OPC_U4CQNE, "!="},
00930 {OPC_U8I4NE, "!="},
00931 {OPC_U8U4NE, "!="},
00932 {OPC_U8I8NE, "!="},
00933 {OPC_U8U8NE, "!="},
00934 {OPC_U8F4NE, "!="},
00935 {OPC_U8F8NE, "!="},
00936 {OPC_U8FQNE, "!="},
00937 {OPC_U8C4NE, "!="},
00938 {OPC_U8C8NE, "!="},
00939 {OPC_U8CQNE, "!="},
00940 #endif
00941 {OPC_I4I4GE, ">="},
00942 #ifdef TARG_X8664
00943 {OPC_I4U4GE, ">="},
00944 {OPC_I4I8GE, ">="},
00945 #endif
00946 {OPC_I4U8GE, ">="},
00947 {OPC_I4F4GE, ">="},
00948 #ifdef TARG_IA64
00949 {OPC_I4F10GE, ">="},
00950 {OPC_I4FQGE, ">="},
00951 {OPC_I4I8GE, ">="},
00952 {OPC_I4U4GE, ">="},
00953 #endif
00954 {OPC_I4F8GE, ">="},
00955 #ifndef TARG_X8664
00956 {OPC_I4I4LT, "<"},
00957 {OPC_I4U8LT, "<"},
00958 {OPC_I4F4LT, "<"},
00959 {OPC_I4F10LT, "<"},
00960 {OPC_I4FQLT, "<"},
00961 {OPC_I4I8LT, "<"},
00962 {OPC_I4U4LT, "<"},
00963 {OPC_I4F8LT, "<"},
00964 #else
00965 {OPC_I4FQGE, ">="},
00966 {OPC_I8I4GE, ">="},
00967 {OPC_I8U4GE, ">="},
00968 {OPC_I8I8GE, ">="},
00969 {OPC_I8U8GE, ">="},
00970 {OPC_I8F4GE, ">="},
00971 {OPC_I8F8GE, ">="},
00972 {OPC_I8FQGE, ">="},
00973 {OPC_U4I4GE, ">="},
00974 {OPC_U4U4GE, ">="},
00975 {OPC_U4I8GE, ">="},
00976 {OPC_U4U8GE, ">="},
00977 {OPC_U4F4GE, ">="},
00978 {OPC_U4F8GE, ">="},
00979 {OPC_U4FQGE, ">="},
00980 {OPC_U8I4GE, ">="},
00981 {OPC_U8U4GE, ">="},
00982 {OPC_U8I8GE, ">="},
00983 {OPC_U8U8GE, ">="},
00984 {OPC_U8F4GE, ">="},
00985 {OPC_U8F8GE, ">="},
00986 {OPC_U8FQGE, ">="},
00987 #endif
00988 {OPC_I4I4LE, "<="},
00989 #ifdef TARG_X8664
00990 {OPC_I4U4LE, "<="},
00991 {OPC_I4I8LE, "<="},
00992 #endif
00993 {OPC_I4U8LE, "<="},
00994 {OPC_I4F4LE, "<="},
00995 #ifndef TARG_X8664
00996 {OPC_I4F10LE, "<="},
00997 #else
00998 {OPC_I4F8LE, "<="},
00999 #endif
01000 {OPC_I4FQLE, "<="},
01001 #ifndef TARG_X8664
01002 {OPC_I4I8LE, "<="},
01003 {OPC_I4U4LE, "<="},
01004 #ifdef KEY
01005 {OPC_U8U8EQ, "=="},
01006 #endif
01007 #else
01008 {OPC_I8I4LE, "<="},
01009 {OPC_I8U4LE, "<="},
01010 {OPC_I8I8LE, "<="},
01011 {OPC_I8U8LE, "<="},
01012 {OPC_I8F4LE, "<="},
01013 {OPC_I8F8LE, "<="},
01014 {OPC_I8FQLE, "<="},
01015 {OPC_U4I4LE, "<="},
01016 {OPC_U4U4LE, "<="},
01017 {OPC_U4I8LE, "<="},
01018 {OPC_U4U8LE, "<="},
01019 {OPC_U4F4LE, "<="},
01020 {OPC_U4F8LE, "<="},
01021 {OPC_U4FQLE, "<="},
01022 {OPC_U8I4LE, "<="},
01023 {OPC_U8U4LE, "<="},
01024 {OPC_U8I8LE, "<="},
01025 {OPC_U8U8LE, "<="},
01026 {OPC_U8F4LE, "<="},
01027 {OPC_U8F8LE, "<="},
01028 {OPC_U8FQLE, "<="},
01029 {OPC_I4I4GT, ">"},
01030 {OPC_I4U4GT, ">"},
01031 {OPC_I4I8GT, ">"},
01032 {OPC_I4U8GT, ">"},
01033 {OPC_I4F4GT, ">"},
01034 {OPC_I4F8GT, ">"},
01035 {OPC_I4FQGT, ">"},
01036 {OPC_I8I4GT, ">"},
01037 {OPC_I8U4GT, ">"},
01038 {OPC_I8I8GT, ">"},
01039 {OPC_I8U8GT, ">"},
01040 {OPC_I8F4GT, ">"},
01041 {OPC_I8F8GT, ">"},
01042 {OPC_I8FQGT, ">"},
01043 {OPC_U4I4GT, ">"},
01044 {OPC_U4U4GT, ">"},
01045 {OPC_U4I8GT, ">"},
01046 {OPC_U4U8GT, ">"},
01047 {OPC_U4F4GT, ">"},
01048 {OPC_U4F8GT, ">"},
01049 {OPC_U4FQGT, ">"},
01050 {OPC_U8I4GT, ">"},
01051 {OPC_U8U4GT, ">"},
01052 {OPC_U8I8GT, ">"},
01053 {OPC_U8U8GT, ">"},
01054 {OPC_U8F4GT, ">"},
01055 {OPC_U8F8GT, ">"},
01056 {OPC_U8FQGT, ">"},
01057 {OPC_I4I4LT, "<"},
01058 {OPC_I4U4LT, "<"},
01059 {OPC_I4I8LT, "<"},
01060 {OPC_I4U8LT, "<"},
01061 {OPC_I4F4LT, "<"},
01062 {OPC_I4F8LT, "<"},
01063 {OPC_I4FQLT, "<"},
01064 {OPC_I8I4LT, "<"},
01065 {OPC_I8U4LT, "<"},
01066 {OPC_I8I8LT, "<"},
01067 {OPC_I8U8LT, "<"},
01068 {OPC_I8F4LT, "<"},
01069 {OPC_I8F8LT, "<"},
01070 {OPC_I8FQLT, "<"},
01071 {OPC_U4I4LT, "<"},
01072 {OPC_U4U4LT, "<"},
01073 {OPC_U4I8LT, "<"},
01074 {OPC_U4U8LT, "<"},
01075 {OPC_U4F4LT, "<"},
01076 {OPC_U4F8LT, "<"},
01077 {OPC_U4FQLT, "<"},
01078 {OPC_U8I4LT, "<"},
01079 {OPC_U8U4LT, "<"},
01080 {OPC_U8I8LT, "<"},
01081 {OPC_U8U8LT, "<"},
01082 {OPC_U8F4LT, "<"},
01083 {OPC_U8F8LT, "<"},
01084 {OPC_U8FQLT, "<"},
01085 #ifdef KEY
01086 {OPC_I4EXTRACT_BITS, "_I4EXTRACT_BITS"},
01087 {OPC_I8EXTRACT_BITS, "_I8EXTRACT_BITS"},
01088 {OPC_U4EXTRACT_BITS, "_U4EXTRACT_BITS"},
01089 {OPC_U8EXTRACT_BITS, "_U8EXTRACT_BITS"},
01090 {OPC_I4COMPOSE_BITS, "_I4COMPOSE_BITS"},
01091 {OPC_I8COMPOSE_BITS, "_I8COMPOSE_BITS"},
01092 {OPC_U4COMPOSE_BITS, "_U4COMPOSE_BITS"},
01093 {OPC_U8COMPOSE_BITS, "_U8COMPOSE_BITS"},
01094 #endif
01095
01096 #endif
01097 #ifdef TARG_X8664
01098 {OPC_V16F4RECIP, "_V16F4RECIP"},
01099 {OPC_F8F8FLOOR, "_F8F8FLOOR"},
01100 {OPC_U8U8LT, "<"},
01101 {OPC_I8I8EQ, "=="},
01102 {OPC_U4U4EQ, "=="},
01103 {OPC_U4I4EQ, "=="},
01104 {OPC_U4U8EQ, "=="},
01105 {OPC_U8I4EQ, "=="},
01106 {OPC_U8I8EQ, "=="},
01107 {OPC_U4U4LE, "<="},
01108 {OPC_U8U8LE, "<="},
01109 {OPC_I4F8LE, "<="},
01110 {OPC_I4F8NE, "!="},
01111 {OPC_U4F8NE, "!="},
01112 {OPC_U4U4NE, "!="},
01113 {OPC_U4U8NE, "!="},
01114 {OPC_U8U8NE, "!="},
01115 {OPC_U8I4NE, "!="},
01116 {OPC_U4U4GE, ">="},
01117 {OPC_V16I1ADD, "+"},
01118 {OPC_V16I2ADD, "+"},
01119 {OPC_V16I4ADD, "+"},
01120 {OPC_V16I8ADD, "+"},
01121 {OPC_V16F4ADD, "+"},
01122 {OPC_V16F8ADD, "+"},
01123 {OPC_V16C4ADD, "+"},
01124 {OPC_V16C8ADD, "+"},
01125 {OPC_M8I1ADD, "+"},
01126 {OPC_M8I2ADD, "+"},
01127 {OPC_M8I4ADD, "+"},
01128 {OPC_M8F4ADD, "+"},
01129 {OPC_V8I1ADD, "+"},
01130 {OPC_V8I2ADD, "+"},
01131 {OPC_V8I4ADD, "+"},
01132 {OPC_V8F4ADD, "+"},
01133 {OPC_V16I1SUB, "-"},
01134 {OPC_V16I2SUB, "-"},
01135 {OPC_V16I4SUB, "-"},
01136 {OPC_V16I8SUB, "-"},
01137 {OPC_V16F4SUB, "-"},
01138 {OPC_V16F8SUB, "-"},
01139 {OPC_V16C4SUB, "-"},
01140 {OPC_V16C8SUB, "-"},
01141 {OPC_M8I1SUB, "-"},
01142 {OPC_M8I2SUB, "-"},
01143 {OPC_M8I4SUB, "-"},
01144 {OPC_M8F4SUB, "-"},
01145 {OPC_V8I1SUB, "-"},
01146 {OPC_V8I2SUB, "-"},
01147 {OPC_V8I4SUB, "-"},
01148 {OPC_V8F4SUB, "-"},
01149 {OPC_V16I1BAND,"&"},
01150 {OPC_V16I2BAND,"&"},
01151 {OPC_V16I4BAND,"&"},
01152 {OPC_V16I8BAND,"&"},
01153 {OPC_V16F4BAND,"&"},
01154 {OPC_V16F8BAND,"&"},
01155 {OPC_V16I1BIOR,"|"},
01156 {OPC_V16I2BIOR,"|"},
01157 {OPC_V16I4BIOR,"|"},
01158 {OPC_V16I8BIOR,"|"},
01159 {OPC_V16F4BIOR,"|"},
01160 {OPC_V16F8BIOR,"|"},
01161 {OPC_V16I1BXOR,"^"},
01162 {OPC_V16I2BXOR,"^"},
01163 {OPC_V16I4BXOR,"^"},
01164 {OPC_V16I8BXOR,"^"},
01165 {OPC_V16F4BXOR,"^"},
01166 {OPC_V16F8BXOR,"^"},
01167 {OPC_V16F4MAX,"_V16F4MAX"},
01168 {OPC_V16F8MAX,"_V16F8MAX"},
01169 {OPC_V16F4MIN,"_V16F4MIN"},
01170 {OPC_V16F8MIN,"_V16F8MIN"},
01171 {OPC_V16F4DIV,"/"},
01172 {OPC_V16F8DIV,"/"},
01173 {OPC_V16F4MPY,"*"},
01174 {OPC_V16F8MPY,"*"},
01175 {OPC_V16C4DIV,"/"},
01176 {OPC_V16C8DIV,"/"},
01177 {OPC_V16C4MPY,"*"},
01178 {OPC_V16C8MPY,"*"},
01179 {OPC_V16F4SQRT, "SQRT"},
01180 {OPC_V16F8SQRT, "SQRT"},
01181 {OPC_V16I1NEG, "-"},
01182 {OPC_V16I2NEG, "-"},
01183 {OPC_V16I4NEG, "-"},
01184 {OPC_V16I8NEG, "-"},
01185 {OPC_V16F4NEG, "-"},
01186 {OPC_V16F8NEG, "-"},
01187 #else
01188 {OPC_I4F8LE, "<="}
01189 #endif
01190
01191 };
01192
01193 static bool
01194 WN2C_is_void_ptr (TY_IDX idx) {
01195 return TY_kind(idx) == KIND_POINTER && TY_kind(TY_pointed(idx)) == KIND_VOID;
01196 }
01197
01198
01199
01200
01201 static UINT
01202 WN2C_get_union_offset(TY_IDX ty, UINT field_id) {
01203
01204 UINT cur_field_id = 0;
01205 FLD_HANDLE fld = FLD_get_to_field(ty, field_id, cur_field_id);
01206 return FLD_ofst(fld);
01207 }
01208
01209 static SRCPOS last_source_line;
01210
01211
01212
01213
01214
01215 static void
01216 translator_warning(const char * str, ...) {
01217
01218 va_list vp;
01219 va_start(vp, str);
01220
01221 USRCPOS cpos;
01222 USRCPOS_srcpos(cpos) = last_source_line;
01223 const char *fname, *dirname;
01224 IR_Srcpos_Filename(USRCPOS_srcpos(cpos), &fname, &dirname);
01225
01226 fprintf(stderr, "internal translator warning (from %s:%d): ",
01227 fname, USRCPOS_linenum(cpos));
01228 vfprintf(stderr, str, vp);
01229 fprintf(stderr, "\n");
01230 va_end(vp);
01231 }
01232
01233
01234
01235
01236 static void
01237 WN2C_Stmt_Newline(TOKEN_BUFFER tokens,
01238 SRCPOS srcpos)
01239 {
01240 static int init = 0;
01241 if(!init) {
01242 IR_Dwarf_Gen_File_Table (FALSE);
01243 init = 1;
01244 }
01245 if (W2C_Emit_Linedirs)
01246 Append_Srcpos_Directive(tokens, srcpos);
01247 Append_Indented_Newline(tokens, 1);
01248 last_source_line = srcpos;
01249
01250 if (W2C_File[W2C_LOC_FILE] != NULL)
01251 Append_Srcpos_Map(tokens, srcpos);
01252 }
01253
01254
01255
01256
01257
01258 static STATUS
01259 WN2C_lvalue_wn(TOKEN_BUFFER tokens,
01260 const WN *wn,
01261 TY_IDX addr_ty,
01262 TY_IDX object_ty,
01263 STAB_OFFSET addr_offset,
01264 CONTEXT context);
01265
01266
01267 static void
01268 WN2C_incr_indentation_for_stmt_body(const WN *body)
01269 {
01270
01271
01272
01273
01274 if (WN_operator(body) != OPR_BLOCK)
01275 Increment_Indentation();
01276 }
01277
01278
01279 static void
01280 WN2C_decr_indentation_for_stmt_body(const WN *body)
01281 {
01282
01283
01284
01285
01286 if (WN_operator(body) != OPR_BLOCK)
01287 Decrement_Indentation();
01288 }
01289
01290
01291 static TOKEN_BUFFER
01292 WN2C_generate_cast(TY_IDX cast_to,
01293 BOOL pointer_to_type)
01294 {
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 TOKEN_BUFFER ty_buffer = New_Token_Buffer();
01305
01306 if (pointer_to_type)
01307 Append_Token_Special(ty_buffer, '*');
01308 if (TY_Is_Array_Or_Function(cast_to))
01309 WHIRL2C_parenthesize(ty_buffer);
01310 TY2C_translate_unqualified(ty_buffer, cast_to);
01311 WHIRL2C_parenthesize(ty_buffer);
01312 return ty_buffer;
01313 }
01314
01315
01316 static void
01317 WN2C_prepend_cast(TOKEN_BUFFER tokens,
01318 TY_IDX cast_to,
01319 BOOL pointer_to_type)
01320 {
01321 TOKEN_BUFFER ty_buffer = WN2C_generate_cast(cast_to, pointer_to_type);
01322 Prepend_And_Reclaim_Token_List(tokens, &ty_buffer);
01323 }
01324
01325
01326 static void
01327 WN2C_append_cast(TOKEN_BUFFER tokens,
01328 TY_IDX cast_to,
01329 BOOL pointer_to_type)
01330 {
01331 TOKEN_BUFFER ty_buffer = WN2C_generate_cast(cast_to, pointer_to_type);
01332 Append_And_Reclaim_Token_List(tokens, &ty_buffer);
01333 }
01334
01335
01336 static void
01337 WN2C_Assign_Complex_Const(TOKEN_BUFFER tokens,
01338 const char *lhs_name,
01339 TCON realpart,
01340 TCON imagpart)
01341 {
01342
01343 Append_Token_Special(tokens, '(');
01344 Append_Token_String(tokens, lhs_name);
01345 Append_Token_Special(tokens, '.');
01346 Append_Token_String(tokens, TY2C_Complex_Realpart_Name);
01347 Append_Token_Special(tokens, '=');
01348 TCON2C_translate(tokens, realpart);
01349 Append_Token_Special(tokens, ')');
01350 Append_Token_Special(tokens, ',');
01351
01352
01353 Append_Token_Special(tokens, '(');
01354 Append_Token_String(tokens, lhs_name);
01355 Append_Token_Special(tokens, '.');
01356 Append_Token_String(tokens, TY2C_Complex_Imagpart_Name);
01357 Append_Token_Special(tokens, '=');
01358 TCON2C_translate(tokens, imagpart);
01359 Append_Token_Special(tokens, ')');
01360 Append_Token_Special(tokens, ',');
01361 }
01362
01363
01364 static TOKEN_BUFFER
01365 WN2C_Translate_Arithmetic_Operand(const WN*wn,
01366 TY_IDX result_ty,
01367 CONTEXT context)
01368 {
01369 TOKEN_BUFFER opnd_tokens = New_Token_Buffer();
01370 TY_IDX opnd_ty;
01371
01372
01373
01374
01375 if(WN_operator(wn) == OPR_LDA)
01376 opnd_ty = WN_ty(wn);
01377 else
01378 opnd_ty = WN_Tree_Type(wn);
01379
01380 if (!WN2C_arithmetic_compatible_types(result_ty, opnd_ty))
01381 {
01382 CONTEXT_set_top_level_expr(context);
01383 (void)WN2C_translate(opnd_tokens, wn, context);
01384 if (CONTEXT_ptr_arith(context) &&
01385 TY_kind(result_ty) == KIND_SCALAR &&
01386 TY_kind(opnd_ty) == KIND_SCALAR) {
01387
01388 } else {
01389 WHIRL2C_parenthesize(opnd_tokens);
01390 WN2C_prepend_cast(opnd_tokens, result_ty, FALSE);
01391 }
01392 }
01393 else
01394 (void)WN2C_translate(opnd_tokens, wn, context);
01395
01396 return opnd_tokens;
01397 }
01398
01399
01400 static STATUS
01401 WN2C_address_add(TOKEN_BUFFER tokens,
01402 OPCODE opcode,
01403 TY_IDX expr_ty,
01404 WN *wn0,
01405 WN *wn1,
01406 CONTEXT context)
01407 {
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420 TOKEN_BUFFER opnd_tokens;
01421 UINT64 old_intconst = 0;
01422 WN *intconst = NULL;
01423 BOOL top_level_expr = CONTEXT_top_level_expr(context);
01424 TY_IDX wn0_ty = WN_Tree_Type(wn0);
01425 TY_IDX wn1_ty = WN_Tree_Type(wn1);
01426 TY_IDX given_lvalue_ty = (CONTEXT_lvalue_type(context)?
01427 CONTEXT_given_lvalue_ty(context) : 0);
01428
01429 Is_True(OPCODE_operator(opcode) == OPR_ADD,
01430 ("Unexpected kind of pointer expression in WN2C_address_add()"));
01431
01432 CONTEXT_reset_needs_lvalue(context);
01433
01434 intconst = WN_Get_PtrAdd_Intconst(wn0, wn1, TY_pointed(expr_ty));
01435 if (intconst != NULL)
01436 {
01437
01438
01439
01440
01441
01442
01443 if (TY_size(TY_pointed(expr_ty)) > 1)
01444 {
01445 Is_True(WN_operator(intconst) == OPR_INTCONST,
01446 ("Expected INTCONST in WN2C_address_add()"));
01447
01448 old_intconst = WN_const_val(intconst);
01449 WN_const_val(intconst) =
01450 WN_const_val(intconst) / TY_size(TY_pointed(expr_ty));
01451 }
01452
01453
01454 }
01455 else if (given_lvalue_ty == (TY_IDX) 0)
01456 {
01457
01458
01459
01460
01461
01462 top_level_expr = FALSE;
01463
01464 WN2C_append_cast(tokens, expr_ty, FALSE);
01465
01466 if (TY_Is_Pointer(wn0_ty))
01467 wn0_ty = Stab_Pointer_To(Stab_Mtype_To_Ty(MTYPE_U1));
01468 else
01469 wn1_ty = Stab_Pointer_To(Stab_Mtype_To_Ty(MTYPE_U1));
01470 }
01471 else
01472 {
01473
01474
01475
01476
01477 if (WN_operator(wn0) == OPR_INTCONST &&
01478 TY_size(TY_pointed(expr_ty)) > WN_const_val(wn0) &&
01479 TY_Is_Structured(TY_pointed(expr_ty)))
01480 {
01481
01482 return WN2C_lvalue_wn(tokens,
01483 wn1,
01484 expr_ty,
01485 given_lvalue_ty,
01486 WN_const_val(wn0),
01487 context);
01488 }
01489 else if (WN_operator(wn1) == OPR_INTCONST &&
01490 TY_size(TY_pointed(expr_ty)) > WN_const_val(wn1) &&
01491 TY_Is_Structured(TY_pointed(expr_ty)))
01492 {
01493
01494 return WN2C_lvalue_wn(tokens,
01495 wn0,
01496 expr_ty,
01497 given_lvalue_ty,
01498 WN_const_val(wn1),
01499 context);
01500 }
01501 else
01502 {
01503
01504
01505
01506 intconst = WN_Get_PtrAdd_Intconst(wn0, wn1, given_lvalue_ty);
01507 if (intconst != NULL)
01508 {
01509
01510
01511
01512
01513 if (TY_size(given_lvalue_ty) > 1)
01514 {
01515 Is_True(WN_operator(intconst) == OPR_INTCONST,
01516 ("Expected INTCONST in WN2C_address_add()"));
01517
01518 old_intconst = WN_const_val(intconst);
01519 WN_const_val(intconst) =
01520 WN_const_val(intconst) / TY_size(given_lvalue_ty);
01521 }
01522
01523 if (TY_Is_Pointer(wn0_ty))
01524 wn0_ty = Stab_Pointer_To(given_lvalue_ty);
01525 else
01526 wn1_ty = Stab_Pointer_To(given_lvalue_ty);
01527 }
01528 else
01529 {
01530
01531 top_level_expr = FALSE;
01532 WN2C_append_cast(tokens, given_lvalue_ty, TRUE);
01533
01534 if (TY_Is_Pointer(wn0_ty))
01535 wn0_ty = Stab_Pointer_To(Stab_Mtype_To_Ty(MTYPE_U1));
01536 else
01537 wn1_ty = Stab_Pointer_To(Stab_Mtype_To_Ty(MTYPE_U1));
01538 }
01539
01540
01541
01542
01543 }
01544 }
01545
01546
01547
01548
01549 CONTEXT_reset_top_level_expr(context);
01550 if (!top_level_expr)
01551 Append_Token_Special(tokens, '(');
01552
01553 CONTEXT_set_ptr_arith(context);
01554
01555 if (!TY_Is_Pointer(wn0_ty))
01556 CONTEXT_reset_lvalue_type(context);
01557
01558 opnd_tokens = WN2C_Translate_Arithmetic_Operand(wn0, wn0_ty, context);
01559 Append_And_Reclaim_Token_List(tokens, &opnd_tokens);
01560
01561 Append_Token_Special(tokens, '+');
01562
01563 if (!TY_Is_Pointer(wn0_ty) && given_lvalue_ty != (TY_IDX) 0)
01564 CONTEXT_set_lvalue_type(context);
01565 opnd_tokens = WN2C_Translate_Arithmetic_Operand(wn1, wn1_ty, context);
01566 Append_And_Reclaim_Token_List(tokens, &opnd_tokens);
01567
01568 CONTEXT_reset_ptr_arith(context);
01569
01570 if (!top_level_expr)
01571 Append_Token_Special(tokens, ')');
01572
01573
01574 if (old_intconst > 0 && intconst != NULL)
01575 WN_const_val(intconst) = old_intconst;
01576
01577 return EMPTY_STATUS;
01578 }
01579
01580
01581 static STATUS
01582 WN2C_infix_op(TOKEN_BUFFER tokens,
01583 OPCODE opcode,
01584 TY_IDX result_ty,
01585 WN *wn0,
01586 WN *wn1,
01587 CONTEXT context)
01588 {
01589
01590
01591
01592
01593
01594 const char *op_char;
01595 const BOOL binary_op = (wn0 != NULL);
01596 const BOOL top_level_expr = CONTEXT_top_level_expr(context);
01597 const MTYPE descriptor_mtype = OPCODE_desc(opcode);
01598 TY_IDX wn0_ty;
01599 TY_IDX wn1_ty;
01600 TOKEN_BUFFER opnd_tokens;
01601
01602
01603
01604
01605 if (descriptor_mtype == MTYPE_V)
01606 {
01607 wn0_ty = wn1_ty = result_ty;
01608 }
01609 else
01610 {
01611 wn0_ty = wn1_ty = Stab_Mtype_To_Ty(descriptor_mtype);
01612 }
01613
01614
01615 if (OPCODE_operator(opcode) == OPR_NEG &&
01616 (WN_operator(wn1) == OPR_CONST ||
01617 WN_operator(wn1) == OPR_INTCONST))
01618 {
01619 TCON tcon, tcon1;
01620 BOOL folded;
01621
01622 if (WN_operator(wn1) == OPR_CONST)
01623 tcon1 = STC_val(WN_st(wn1));
01624 else
01625 tcon1 = Host_To_Targ(WN_opc_rtype(wn1), WN_const_val(wn1));
01626 tcon = Targ_WhirlOp(opcode, tcon1, tcon1, &folded);
01627
01628 if (folded)
01629 TCON2C_translate(tokens, tcon);
01630 else
01631 {
01632
01633 for (op_char = WN2C_Opc2cname[opcode]; *op_char != '\0'; op_char++)
01634 Append_Token_Special(tokens, *op_char);
01635 Append_Token_Special(tokens, '(');
01636 TCON2C_translate(tokens, tcon1);
01637 Append_Token_Special(tokens, ')');
01638 }
01639 return EMPTY_STATUS;
01640 }
01641 else if (OPCODE_operator(opcode) == OPR_MPY)
01642 {
01643 if (WN_operator(wn0) == OPR_INTCONST &&
01644 WN_const_val(wn0) == 1LL)
01645 {
01646 opnd_tokens = WN2C_Translate_Arithmetic_Operand(wn1, wn1_ty, context);
01647 Append_And_Reclaim_Token_List(tokens, &opnd_tokens);
01648 return EMPTY_STATUS;
01649 }
01650 else if (WN_operator(wn1) == OPR_INTCONST &&
01651 WN_const_val(wn1) == 1LL)
01652 {
01653 opnd_tokens = WN2C_Translate_Arithmetic_Operand(wn0, wn0_ty, context);
01654 Append_And_Reclaim_Token_List(tokens, &opnd_tokens);
01655 return EMPTY_STATUS;
01656 }
01657 }
01658
01659
01660 if (binary_op && WN2C_is_pointer_diff(opcode, wn0, wn1))
01661 {
01662 opcode = WN_opcode(wn0);
01663 wn1 = WN_kid1(wn0);
01664 wn0 = WN_kid0(wn0);
01665 wn0_ty = WN_Tree_Type(wn0);
01666 wn1_ty = WN_Tree_Type(wn1);
01667 }
01668 else if (binary_op && TY_Is_Pointer(result_ty))
01669 {
01670 return WN2C_address_add(tokens,
01671 opcode,
01672 result_ty,
01673 wn0,
01674 wn1,
01675 context);
01676 }
01677
01678
01679
01680
01681 CONTEXT_reset_top_level_expr(context);
01682 if (!top_level_expr)
01683 Append_Token_Special(tokens, '(');
01684
01685 if (binary_op)
01686 {
01687 opnd_tokens =
01688 WN2C_Translate_Arithmetic_Operand(wn0, wn0_ty, context);
01689 Append_And_Reclaim_Token_List(tokens, &opnd_tokens);
01690 }
01691
01692
01693 for (op_char = WN2C_Opc2cname[opcode]; *op_char != '\0'; op_char++)
01694 Append_Token_Special(tokens, *op_char);
01695
01696
01697 opnd_tokens = WN2C_Translate_Arithmetic_Operand(wn1, wn1_ty, context);
01698 Append_And_Reclaim_Token_List(tokens, &opnd_tokens);
01699
01700 if (!top_level_expr)
01701 Append_Token_Special(tokens, ')');
01702
01703 return EMPTY_STATUS;
01704 }
01705
01706
01707 static STATUS
01708 WN2C_funcall_op(TOKEN_BUFFER tokens,
01709 OPCODE opcode,
01710 WN *wn0,
01711 WN *wn1,
01712 CONTEXT context)
01713 {
01714
01715
01716
01717
01718
01719 const TY_IDX result_ty = Stab_Mtype_To_Ty(OPCODE_rtype(opcode));
01720 TY_IDX descriptor_ty = Stab_Mtype_To_Ty(OPCODE_desc(opcode));
01721 const BOOL binary_op = (wn0 != NULL);
01722 TOKEN_BUFFER opnd_tokens;
01723
01724
01725
01726
01727 if (binary_op && WN2C_is_pointer_diff(opcode, wn0, wn1))
01728 return WN2C_infix_op(tokens, opcode, result_ty, wn0, wn1, context);
01729
01730 CONTEXT_reset_needs_lvalue(context);
01731
01732
01733
01734
01735 if (TY_kind(descriptor_ty) == KIND_VOID)
01736 descriptor_ty = result_ty;
01737
01738
01739 Append_Token_String(tokens, WN2C_Opc2cname[opcode]);
01740
01741 CONTEXT_set_top_level_expr(context);
01742 Append_Token_Special(tokens, '(');
01743
01744
01745 if (binary_op)
01746 {
01747 opnd_tokens =
01748 WN2C_Translate_Arithmetic_Operand(wn0, descriptor_ty, context);
01749 Append_And_Reclaim_Token_List(tokens, &opnd_tokens);
01750 Append_Token_Special(tokens, ',');
01751 }
01752
01753
01754 opnd_tokens =
01755 WN2C_Translate_Arithmetic_Operand(wn1, descriptor_ty, context);
01756 Append_And_Reclaim_Token_List(tokens, &opnd_tokens);
01757
01758 Append_Token_Special(tokens, ')');
01759
01760 return EMPTY_STATUS;
01761 }
01762
01763
01764 static TY_IDX
01765 WN2C_MemAccess_Type(TY_IDX base_ty,
01766 TY_IDX load_ty,
01767 MTYPE load_mtype,
01768 STAB_OFFSET offset)
01769 {
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785 TY2C_FLD_INFO fld_info;
01786
01787 if (TY_Is_Array(base_ty))
01788 {
01789
01790
01791
01792
01793 return load_ty;
01794 }
01795 else if (!TY_Is_Structured(base_ty) ||
01796 WN2C_compatible_lvalues(load_ty, base_ty))
01797 {
01798
01799
01800
01801 return load_ty;
01802 }
01803 else
01804 {
01805
01806 fld_info = TY2C_get_field_info(base_ty,
01807 load_ty,
01808 load_mtype,
01809 offset);
01810 if (!fld_info.found_fld.Is_Null ())
01811 {
01812 Reclaim_Token_Buffer(&fld_info.select_tokens);
01813 return FLD_type(fld_info.found_fld);
01814 }
01815 else if (Stab_Mtype_To_Ty(load_mtype) != (TY_IDX) 0 &&
01816 TY_size(Stab_Mtype_To_Ty(load_mtype)) == TY_size(base_ty))
01817 {
01818 return base_ty;
01819 }
01820 else
01821 {
01822 return load_ty;
01823 }
01824 }
01825 }
01826
01827
01828 static void
01829 WN2C_SymAccess_Type(TY_IDX *base_addr_ty,
01830 TY_IDX *object_ty,
01831 TY_IDX base_ty,
01832 TY_IDX load_ty,
01833 MTYPE load_mtype,
01834 STAB_OFFSET offset)
01835 {
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851 TY2C_FLD_INFO fld_info;
01852 TY_IDX actual_loaded_ty = Stab_Mtype_To_Ty(load_mtype);
01853
01854 if (TY_Is_Array(base_ty) &&
01855 WN2C_compatible_lvalues(load_ty, TY_AR_etype(base_ty)))
01856 {
01857
01858 *object_ty = load_ty;
01859 if (TY_is_volatile(TY_AR_etype(base_ty)) == TY_is_volatile(load_ty))
01860 *base_addr_ty = Stab_Pointer_To(base_ty);
01861 else
01862 *base_addr_ty = Stab_Pointer_To(load_ty);
01863 }
01864 else if (!TY_Is_Structured(base_ty) ||
01865 WN2C_compatible_lvalues(load_ty, base_ty))
01866 {
01867
01868 if (actual_loaded_ty != (TY_IDX) 0 &&
01869 !WN2C_compatible_lvalues(actual_loaded_ty, load_ty) &&
01870 WN2C_compatible_lvalues(actual_loaded_ty, base_ty))
01871 {
01872
01873
01874
01875
01876 *object_ty = base_ty;
01877 *base_addr_ty = Stab_Pointer_To(base_ty);
01878 }
01879 else
01880 {
01881 *object_ty = load_ty;
01882 if (TY_is_volatile(base_ty) == TY_is_volatile(load_ty))
01883 *base_addr_ty = Stab_Pointer_To(base_ty);
01884 else
01885 *base_addr_ty = Stab_Pointer_To(load_ty);
01886 }
01887 }
01888 else
01889 {
01890
01891 fld_info = TY2C_get_field_info(base_ty,
01892 load_ty,
01893 load_mtype,
01894 offset);
01895 if (!fld_info.found_fld.Is_Null ())
01896 {
01897 const TY_IDX ftype = FLD_type(fld_info.found_fld);
01898
01899 Reclaim_Token_Buffer(&fld_info.select_tokens);
01900 if (WN2C_compatible_lvalues(load_ty, ftype) &&
01901 TY_is_volatile(ftype) == TY_is_volatile(load_ty))
01902 {
01903 *object_ty = ftype;
01904 *base_addr_ty = Stab_Pointer_To(base_ty);
01905 }
01906 else
01907 {
01908 *object_ty = load_ty;
01909 *base_addr_ty = Stab_Pointer_To(load_ty);
01910 }
01911 }
01912 else if (actual_loaded_ty != (TY_IDX) 0 &&
01913 TY_size(actual_loaded_ty) == TY_size(base_ty) &&
01914 TY_is_volatile(base_ty) == TY_is_volatile(load_ty))
01915 {
01916
01917
01918
01919
01920 *object_ty = base_ty;
01921 *base_addr_ty = Stab_Pointer_To(base_ty);
01922 }
01923 else
01924 {
01925
01926
01927
01928
01929 *object_ty = load_ty;
01930 *base_addr_ty = Stab_Pointer_To(load_ty);
01931 }
01932 }
01933 }
01934
01935
01936
01937 static void
01938 WN2C_append_addr_plus_const(TOKEN_BUFFER tokens,
01939 INT64 element_size,
01940 STAB_OFFSET byte_offset)
01941 {
01942
01943
01944
01945
01946
01947
01948
01949 if (element_size == 0) {
01950
01951
01952
01953
01954 element_size = 1;
01955 }
01956 Is_True(element_size!=0 && byte_offset!=0 && byte_offset%element_size==0,
01957 ("Illegal address increment in WN2C_addr_plus()"));
01958
01959 Append_Token_Special(tokens, '+');
01960 TCON2C_translate(tokens,
01961 Host_To_Targ(MTYPE_I8, byte_offset/element_size));
01962 WHIRL2C_parenthesize(tokens);
01963 }
01964
01965
01966 static void
01967 WN2C_append_addr_plus_expr(TOKEN_BUFFER tokens,
01968 INT64 element_size,
01969 TOKEN_BUFFER *byte_offset)
01970 {
01971
01972
01973
01974
01975
01976
01977
01978 Is_True(element_size!=0,
01979 ("Illegal element size in WN2C_addr_plus()"));
01980
01981 Append_Token_Special(tokens, '+');
01982 Append_And_Reclaim_Token_List(tokens, byte_offset);
01983 if (element_size != 1)
01984 {
01985 Append_Token_Special(tokens, '/');
01986 TCON2C_translate(tokens, Host_To_Targ(MTYPE_I8, element_size));
01987 }
01988 WHIRL2C_parenthesize(tokens);
01989 }
01990
01991 #define WN2C_MAX_FLD_LEVEL 10
01992 typedef struct {
01993 FLD_HANDLE ar[WN2C_MAX_FLD_LEVEL];
01994 int size;
01995 } FLD_list;
01996
01997
01998
01999 static FLD_HANDLE get_to_field_with_name(TY_IDX struct_ty_idx, UINT field_id, UINT& cur_field_id,
02000 FLD_list *fld_stack) {
02001
02002 FmtAssert(TY_Is_Structured(struct_ty_idx), ("expect a struct type"));
02003 FLD_ITER fld_iter = Make_fld_iter(TY_fld(struct_ty_idx));
02004 do {
02005 FLD_HANDLE fld(fld_iter);
02006 cur_field_id++;
02007 if (cur_field_id == field_id) {
02008 fld_stack->ar[fld_stack->size++] = fld;
02009 return fld;
02010 }
02011 TY_IDX fld_ty = FLD_type(fld);
02012 if (TY_kind(fld_ty) == KIND_ARRAY)
02013 fld_ty = Get_Inner_Array_Type(fld_ty);
02014
02015 if (TY_kind(fld_ty) == KIND_STRUCT &&
02016 TY_fld(fld_ty) != FLD_HANDLE()) {
02017 fld_stack->ar[fld_stack->size++] = fld;
02018 fld = get_to_field_with_name(fld_ty, field_id, cur_field_id, fld_stack);
02019 if (cur_field_id == field_id) {
02020 return fld;
02021 }
02022 fld_stack->size--;
02023 }
02024 } while (!FLD_last_field(fld_iter++));
02025 }
02026
02027
02028
02029
02030 static STAB_OFFSET WN2C_Gen_Const_Array_Index(TOKEN_BUFFER expr_tokens, TY_IDX ty_idx, STAB_OFFSET cur_offset) {
02031
02032
02033 for (TY_IDX tmp_ty = ty_idx; TY_Is_Array(tmp_ty); tmp_ty = TY_etype(tmp_ty)) {
02034 int elt_size = TY_size(TY_etype(tmp_ty));
02035 int index = cur_offset / elt_size;
02036 Append_Token_Special(expr_tokens, '[');
02037 char buf[32];
02038 sprintf(buf, "%1d", index);
02039 Append_Token_String(expr_tokens, buf);
02040 Append_Token_Special(expr_tokens, ']');
02041 cur_offset -= index * elt_size;
02042
02043 }
02044 return cur_offset;
02045 }
02046
02047
02048
02049
02050
02051
02052 static STAB_OFFSET WN2C_Gen_Field_Access(TOKEN_BUFFER expr_tokens, TY_IDX fld_ty,
02053 STAB_OFFSET cur_offset, UINT field_id) {
02054
02055
02056 UINT cur_fld = 0;
02057
02058
02059 FLD_list fld_stack;
02060 fld_stack.size = 0;
02061 FLD_HANDLE found_fld = get_to_field_with_name(fld_ty, field_id, cur_fld, &fld_stack);
02062 FmtAssert(!found_fld.Is_Null(), ("Could not find field with the field id %d", field_id));
02063
02064 FmtAssert(fld_stack.size < WN2C_MAX_FLD_LEVEL, ("too many level of field accesses"));
02065 for (int i = 0; i < fld_stack.size; i++) {
02066 cur_offset -= FLD_ofst(fld_stack.ar[i]);
02067 Append_Token_Special(expr_tokens, '.');
02068 Append_Token_String(expr_tokens, FLD_name(fld_stack.ar[i]));
02069 if (i != fld_stack.size-1) {
02070
02071
02072 if (TY_Is_Array(FLD_type(fld_stack.ar[i]))) {
02073 cur_offset = WN2C_Gen_Const_Array_Index(expr_tokens, FLD_type(fld_stack.ar[i]), cur_offset);
02074 }
02075 }
02076 }
02077 return cur_offset;
02078 }
02079
02080 static STATUS
02081 WN2C_based_lvalue(TOKEN_BUFFER expr_tokens,
02082 BOOL expr_is_lvalue,
02083 TY_IDX expr_ty,
02084 TY_IDX addr_ty,
02085 TY_IDX object_ty,
02086 STAB_OFFSET addr_offset,
02087 UINT field_id = 0)
02088
02089 {
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107 STATUS status = EMPTY_STATUS;
02108 BOOL incompat_addr_tys;
02109 BOOL incompat_obj_tys;
02110 TY_IDX base_obj_ty;
02111 TY2C_FLD_INFO field_info;
02112 field_info.select_tokens = NULL;
02113 field_info.found_fld = FLD_HANDLE();
02114
02115
02116 Is_True(expr_ty != (TY_IDX) 0 &&
02117 addr_ty != (TY_IDX) 0 && TY_Is_Pointer(addr_ty) &&
02118 object_ty != (TY_IDX) 0,
02119 ("Expected non-null types in WN2C_based_lvalue()"));
02120
02121
02122
02123
02124
02125
02126 base_obj_ty = TY_pointed(addr_ty);
02127 incompat_addr_tys = !WN2C_assignment_compatible_types(addr_ty, expr_ty);
02128 incompat_obj_tys = !WN2C_compatible_lvalues(object_ty, base_obj_ty);
02129
02130
02131
02132
02133
02134 if (incompat_addr_tys)
02135 {
02136 if (WN2C_array_lvalue_as_ptr(expr_ty,
02137 addr_ty))
02138 {
02139
02140
02141
02142
02143
02144
02145 }
02146 else
02147 {
02148
02149 if (expr_is_lvalue)
02150 {
02151 Prepend_Token_Special(expr_tokens, '&');
02152 }
02153 WN2C_prepend_cast(expr_tokens, addr_ty, FALSE);
02154 WHIRL2C_parenthesize(expr_tokens);
02155 }
02156
02157
02158 expr_is_lvalue = FALSE;
02159 expr_ty = addr_ty;
02160 incompat_addr_tys = FALSE;
02161 }
02162 else if (WN2C_array_lvalue_as_ptr(addr_ty,
02163 Stab_Pointer_To(object_ty)))
02164 {
02165
02166
02167
02168
02169
02170
02171 expr_is_lvalue = FALSE;
02172 expr_ty = addr_ty = Stab_Pointer_To(object_ty);
02173 base_obj_ty = object_ty;
02174 incompat_obj_tys = FALSE;
02175 }
02176
02177
02178 expr_ty = addr_ty;
02179 incompat_addr_tys = FALSE;
02180
02181
02182
02183
02184
02185
02186
02187 if (TY_Is_Array(base_obj_ty) && addr_offset > 0) {
02188
02189 STAB_OFFSET cur_offset = WN2C_Gen_Const_Array_Index(expr_tokens, base_obj_ty, addr_offset);
02190
02191 if (field_id != 0) {
02192 while (TY_Is_Array(base_obj_ty)) {
02193 base_obj_ty = TY_etype(base_obj_ty);
02194 }
02195 cur_offset = WN2C_Gen_Field_Access(expr_tokens, base_obj_ty, cur_offset, field_id);
02196 }
02197
02198
02199
02200 if (field_id == 0) {
02201 Prepend_Token_Special(expr_tokens, '&');
02202 }
02203 goto ret_point;
02204 }
02205
02206 if (TY_Is_Structured(base_obj_ty) && field_id != 0) {
02207 UINT cur_offset = WN2C_Gen_Field_Access(expr_tokens, base_obj_ty, addr_offset, field_id);
02208 FmtAssert(cur_offset == 0, ("offset should be zero after field generation"));
02209 goto ret_point;
02210 }
02211
02212
02213
02214
02215
02216
02217 if ((addr_offset != 0 || incompat_obj_tys) && TY_Is_Structured(base_obj_ty))
02218 {
02219 field_info =
02220 TY2C_get_field_info(base_obj_ty,
02221 object_ty,
02222 TY_mtype(object_ty),
02223 addr_offset);
02224 }
02225
02226
02227
02228
02229 if (!field_info.found_fld.Is_Null ())
02230 {
02231 WHIRL2C_parenthesize(expr_tokens);
02232 if (expr_is_lvalue)
02233 Append_Token_Special(expr_tokens, '.');
02234 else
02235 Append_Token_String(expr_tokens, "->");
02236 Append_And_Reclaim_Token_List(expr_tokens, &field_info.select_tokens);
02237 expr_is_lvalue = TRUE;
02238 }
02239 else if (addr_offset != (STAB_OFFSET) 0 || incompat_obj_tys)
02240 {
02241
02242 if (expr_is_lvalue) {
02243 if (TY_Is_Array(TY_pointed(addr_ty)) &&
02244 WN2C_arithmetic_compatible_types(Get_Inner_Array_Type(TY_pointed(addr_ty)), object_ty)) {
02245
02246
02247
02248 } else if (addr_offset == 0 && TY_kind(object_ty) == KIND_SCALAR && TY_kind(base_obj_ty) == KIND_SCALAR) {
02249
02250 WN2C_prepend_cast(expr_tokens, object_ty, FALSE);
02251 goto ret_point;
02252 }
02253 else {
02254 Prepend_Token_Special(expr_tokens, '&');
02255 }
02256 }
02257
02258 if (addr_offset != 0 && TY_size(object_ty) != 0 && addr_offset%TY_size(object_ty) != 0)
02259 {
02260
02261
02262
02263
02264 WN2C_prepend_cast(expr_tokens,
02265 Stab_Mtype_To_Ty(MTYPE_I1),
02266 TRUE);
02267 WHIRL2C_parenthesize(expr_tokens);
02268 WN2C_append_addr_plus_const(expr_tokens,
02269 TY_size(Stab_Mtype_To_Ty(MTYPE_I1)),
02270 addr_offset);
02271 TY_IDX tty = object_ty;
02272
02273
02274 if(TY_kind(tty) == KIND_ARRAY) {
02275 tty = Get_Inner_Array_Type(object_ty);
02276 }
02277 WN2C_prepend_cast(expr_tokens, object_ty, TRUE);
02278 }
02279 else
02280 {
02281
02282
02283
02284
02285 if (incompat_obj_tys)
02286 {
02287 WHIRL2C_parenthesize(expr_tokens);
02288 WN2C_prepend_cast(expr_tokens, object_ty, TRUE);
02289 }
02290
02291 if (addr_offset != 0)
02292 WN2C_append_addr_plus_const(expr_tokens,
02293 TY_size(object_ty),
02294 addr_offset);
02295 }
02296 expr_is_lvalue = FALSE;
02297 }
02298 else if (TY_is_logical(base_obj_ty) && !TY_is_logical(object_ty)) {
02299
02300
02301 WN2C_prepend_cast(expr_tokens, object_ty, FALSE);
02302 }
02303
02304 ret_point:
02305 if (expr_is_lvalue)
02306 STATUS_set_lvalue(status);
02307 return status;
02308 }
02309
02310
02311 static STATUS
02312 WN2C_lvalue_st(TOKEN_BUFFER tokens,
02313 const ST *st,
02314 TY_IDX addr_ty,
02315 TY_IDX object_ty,
02316 STAB_OFFSET addr_offset,
02317 CONTEXT context,
02318 UINT field_id = 0)
02319 {
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332 STATUS status;
02333 TY_IDX base_ptr_ty;
02334
02335 Is_True(ST_sym_class(st) != CLASS_PREG,
02336 ("Did not expect a preg in WN2C_lvalue_st()"));
02337
02338 if (ST_sym_class(st) == CLASS_CONST)
02339 {
02340 TCON2C_translate(tokens, STC_val(st));
02341 status = EMPTY_STATUS;
02342 }
02343 else
02344 {
02345
02346 if (Stab_Is_Based_At_Common_Or_Equivalence(st))
02347 {
02348 addr_offset += ST_ofst(st);
02349 st = ST_base(st);
02350 addr_ty = Stab_Pointer_To(ST_type(st));
02351 }
02352
02353 if (ST_is_split_common(st))
02354 {
02355 addr_offset += Stab_Full_Split_Offset(st);
02356 st = ST_full(st);
02357 addr_ty = Stab_Pointer_To(ST_type(st));
02358 }
02359
02360 ST2C_use_translate(tokens, st, context);
02361 base_ptr_ty = Stab_Pointer_To(ST_sym_class(st) == CLASS_FUNC ?
02362 ST_pu_type(st) : ST_type(st));
02363
02364
02365
02366 status = WN2C_based_lvalue(tokens,
02367 TRUE,
02368 base_ptr_ty,
02369 addr_ty,
02370 object_ty,
02371 addr_offset,
02372 field_id);
02373 }
02374 return status;
02375 }
02376
02377 static STATUS WN2C_ptr_array_wn(TOKEN_BUFFER tokens,
02378 const WN *wn,
02379 TY_IDX object_ty,
02380 STAB_OFFSET addr_offset,
02381 CONTEXT context)
02382
02383 {
02384
02385
02386
02387
02388
02389
02390
02391
02392 STATUS status = EMPTY_STATUS;
02393 FmtAssert(WN_operator(wn) == OPR_LDID, ("Expecting LDID node in function %s\n", __func__));
02394
02395 ST2C_use_translate(tokens, WN_st(wn), context);
02396 WN2C_prepend_cast(tokens, object_ty, TRUE);
02397 if (addr_offset != 0) {
02398 WN2C_append_addr_plus_const(tokens,
02399 TY_size(object_ty),
02400 addr_offset);
02401 WHIRL2C_parenthesize(tokens);
02402 }
02403 return status;
02404 }
02405
02406 static STATUS
02407 WN2C_lvalue_wn(TOKEN_BUFFER tokens,
02408 const WN *wn,
02409 TY_IDX addr_ty,
02410 TY_IDX object_ty,
02411 STAB_OFFSET addr_offset,
02412 CONTEXT context)
02413 {
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426 STATUS status;
02427 TY_IDX tree_type = WN_Tree_Type(wn);
02428
02429
02430
02431
02432 CONTEXT_set_needs_lvalue(context);
02433 CONTEXT_reset_top_level_expr(context);
02434 if (WN_operator(wn) == OPR_ARRAY)
02435 {
02436 TY_IDX array_base_ty = WN_Tree_Type(WN_kid0(wn));
02437
02438 if (!TY_Is_Pointer(array_base_ty))
02439 {
02440
02441
02442
02443
02444 CONTEXT_set_array_basetype(context);
02445 CONTEXT_set_given_base_ty(context, addr_ty);
02446 tree_type = addr_ty;
02447 }
02448 }
02449 else if (WN_operator(wn) == OPR_ADD &&
02450 TY_Is_Pointer(tree_type) &&
02451 WN_Get_PtrAdd_Intconst(WN_kid0(wn),
02452 WN_kid1(wn),
02453 TY_pointed(tree_type)) == NULL)
02454 {
02455
02456
02457
02458
02459
02460 CONTEXT_set_lvalue_type(context);
02461 CONTEXT_set_given_lvalue_ty(context, object_ty);
02462 addr_ty = tree_type = Stab_Pointer_To(object_ty);
02463 }
02464 else if (WN_operator(wn) == OPR_LDID) {
02465 TY_IDX wn_ty = ST_type(WN_st(wn));
02466 if (TY_Is_Pointer(wn_ty) && TY_Is_Array(TY_pointed(wn_ty))) {
02467 TY_IDX base_ty = Get_Inner_Array_Type(TY_pointed(wn_ty));
02468 if (WN2C_assignment_compatible_types(base_ty, object_ty)) {
02469
02470 return WN2C_ptr_array_wn(tokens, wn, base_ty, addr_offset, context);
02471 }
02472 }
02473 }
02474
02475 status = WN2C_translate(tokens, wn, context);
02476
02477 if (WN_operator(wn) == OPR_ILOAD &&
02478 WN_field_id(wn) != 0) {
02479 TY_IDX fld_ty = WN_ty(wn);
02480 if (TY_kind(fld_ty) == KIND_POINTER
02481 && TY_kind(TY_pointed(fld_ty)) == KIND_VOID) {
02482
02483
02484
02485
02486
02487 WN2C_prepend_cast(tokens, addr_ty, FALSE);
02488 }
02489 }
02490
02491 if (WN_operator(wn) == OPR_LDA) {
02492
02493
02494
02495
02496
02497 BOOL reset = TY_Is_Array(ST_type(WN_st(wn)));
02498 if(WN_field_id(wn) && TY_Is_Array(Get_Field_Type(ST_type(WN_st(wn)), WN_field_id(wn))))
02499 reset = TRUE;
02500 if (reset)
02501 STATUS_reset_lvalue(status);
02502 }
02503
02504
02505
02506 status = WN2C_based_lvalue(tokens,
02507 STATUS_is_lvalue(status),
02508
02509 tree_type,
02510 addr_ty,
02511 object_ty,
02512 addr_offset);
02513
02514 return status;
02515 }
02516
02517
02518 static void
02519 WN2C_create_ref_param_lda(WN *lda, const WN *ldid)
02520 {
02521 const TY_IDX lhs_addr_ty = Stab_Pointer_To(WN_ty(ldid));
02522
02523 BZERO(lda, sizeof(WN));
02524 WN_set_opcode(lda, OPCODE_make_op(OPR_LDA, TY_mtype(lhs_addr_ty), MTYPE_V));
02525 WN_set_kid_count(lda, 0);
02526 WN_set_map_id(lda, (WN_MAP_ID) (-1));
02527 WN_load_offset(lda) = 0;
02528 WN_st_idx(lda) = WN_st_idx(ldid);
02529 WN_set_ty(lda, lhs_addr_ty);
02530 }
02531
02532
02533 static void
02534 WN2C_Append_Preg(TOKEN_BUFFER tokens,
02535 const ST *st,
02536 PREG_IDX preg_idx,
02537 TY_IDX ty,
02538 CONTEXT context)
02539 {
02540
02541
02542
02543 TY_IDX preg_ty;
02544 TOKEN_BUFFER preg_tokens;
02545
02546 Is_True(ST_sym_class(st) == CLASS_PREG,
02547 ("Expected preg in WN2C_Append_Preg()"));
02548
02549
02550 preg_tokens = New_Token_Buffer();
02551 preg_ty = PUinfo_Preg_Type(ST_type(st), preg_idx);
02552 ST2C_Use_Preg(preg_tokens, preg_ty, preg_idx, context);
02553
02554
02555
02556
02557
02558 if (TY_Is_Pointer(ty) && TY_mtype(ty) != TY_mtype(preg_ty))
02559 {
02560 WN2C_prepend_cast(preg_tokens,
02561 Stab_Mtype_To_Ty(TY_mtype(ty)),
02562 FALSE);
02563 }
02564
02565
02566
02567
02568 if (!WN2C_arithmetic_compatible_types(preg_ty, ty))
02569 WN2C_prepend_cast(preg_tokens, ty, FALSE);
02570
02571 Append_And_Reclaim_Token_List(tokens, &preg_tokens);
02572 }
02573
02574
02575 static void
02576 WN2C_Load_From_PregIdx(TOKEN_BUFFER tokens,
02577 const ST *preg1,
02578 PREG_IDX preg_idx1,
02579 const ST *preg2,
02580 PREG_IDX preg_idx2,
02581 TY_IDX object_ty,
02582 CONTEXT context)
02583 {
02584
02585
02586
02587 TOKEN_BUFFER base_buffer, offset_buffer;
02588
02589
02590
02591
02592 base_buffer = New_Token_Buffer();
02593 WN2C_Append_Preg(base_buffer,
02594 preg1,
02595 preg_idx1,
02596 Stab_Pointer_To(Stab_Mtype_To_Ty(MTYPE_U1)),
02597 context);
02598
02599
02600 offset_buffer = New_Token_Buffer();
02601 WN2C_Append_Preg(offset_buffer,
02602 preg2,
02603 preg_idx2,
02604 ST_type(preg2),
02605 context);
02606
02607
02608 WN2C_append_addr_plus_expr(base_buffer, 1, &offset_buffer);
02609
02610
02611
02612
02613 WN2C_prepend_cast(base_buffer, object_ty, TRUE);
02614 Prepend_Token_Special(base_buffer, '*');
02615
02616 Append_And_Reclaim_Token_List(tokens, &base_buffer);
02617 }
02618
02619
02620 static void
02621 WN2C_Append_Assignment(TOKEN_BUFFER tokens,
02622 TOKEN_BUFFER *lhs_tokens,
02623 const WN *rhs,
02624 TY_IDX assign_ty,
02625 CONTEXT context)
02626 {
02627 TOKEN_BUFFER rhs_buffer = New_Token_Buffer();
02628 TY_IDX rhs_ty = WN_Tree_Type(rhs);
02629
02630
02631 if (!WN2C_assignment_compatible_types(assign_ty, rhs_ty))
02632 {
02633 if (!TY_Is_Structured(assign_ty) && !TY_Is_Structured(rhs_ty))
02634 {
02635 (void)WN2C_translate(rhs_buffer, rhs, context);
02636 WHIRL2C_parenthesize(rhs_buffer);
02637 WN2C_prepend_cast(rhs_buffer,
02638 assign_ty,
02639 FALSE);
02640 }
02641 else
02642 {
02643
02644
02645
02646 const UINT tmp_idx = Stab_Lock_Tmpvar(rhs_ty,
02647 ST2C_Declare_Tempvar);
02648 const char *tmpvar_name = W2CF_Symtab_Nameof_Tempvar(tmp_idx);
02649
02650
02651 Append_Token_String(tokens, tmpvar_name);
02652 Append_Token_Special(tokens, '=');
02653 (void)WN2C_translate(tokens, rhs, context);
02654 Append_Token_Special(tokens, ';');
02655 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
02656
02657
02658 Append_Token_Special(rhs_buffer, '&');
02659 Append_Token_String(rhs_buffer, tmpvar_name);
02660 WN2C_prepend_cast(rhs_buffer,
02661 assign_ty,
02662 TRUE);
02663 Prepend_Token_Special(rhs_buffer, '*');
02664 Stab_Unlock_Tmpvar(tmp_idx);
02665 }
02666 }
02667 else
02668 {
02669 (void)WN2C_translate(rhs_buffer, rhs, context);
02670 }
02671
02672
02673 Append_And_Reclaim_Token_List(tokens, lhs_tokens);
02674 Append_Token_Special(tokens, '=');
02675 Append_And_Reclaim_Token_List(tokens, &rhs_buffer);
02676 }
02677
02678
02679 static void
02680 WN2C_Normalize_Idx_To_Onedim(TOKEN_BUFFER tokens,
02681 const WN *wn,
02682 CONTEXT context)
02683 {
02684
02685
02686
02687
02688 static char dim_string[128];
02689 char *dim_stringp = &dim_string[0];
02690 INT32 dim1, dim2;
02691
02692 for (dim1 = 0; dim1 < WN_num_dim(wn); dim1++)
02693 {
02694 if (dim1 > 0)
02695 Append_Token_Special(tokens, '+');
02696
02697
02698
02699
02700
02701
02702 if (dim1+1 == WN_num_dim(wn))
02703 CONTEXT_set_top_level_expr(context);
02704 (void)WN2C_translate(tokens, WN_array_index(wn, dim1), context);
02705 for (dim2 = dim1+1; dim2 < WN_num_dim(wn); dim2++)
02706 {
02707 Append_Token_Special(tokens, '*');
02708 (void)WN2C_translate(tokens, WN_array_dim(wn, dim2), context);
02709 }
02710
02711 if (W2C_Emit_Adims)
02712 {
02713
02714 sprintf(dim_stringp, "/*Dim%d*/", WN_num_dim(wn)-dim1);
02715 Append_Token_String(tokens, dim_stringp);
02716 }
02717 }
02718
02719 }
02720
02721
02722 static void
02723 WN2C_append_label_name(TOKEN_BUFFER tokens, const WN *wn)
02724 {
02725
02726
02727
02728 Append_Token_String(tokens, WHIRL2C_number_as_c_name(WN_label_number(wn)));
02729 }
02730
02731 extern int debug_requested;
02732
02733 static void
02734 WN2C_Append_Symtab_Types(TOKEN_BUFFER tokens, UINT lines_between_decls)
02735 {
02736
02737
02738
02739
02740 TY_IDX ty;
02741 TOKEN_BUFFER tmp_tokens;
02742
02743
02744 for (ty = 1; ty < TY_Table_Size(); ty++)
02745 {
02746 if (TY_Is_Structured(ty) &&
02747 !TY_split(Ty_Table[ty]) &&
02748 !TY_is_translated_to_c(ty) &&
02749 !Stab_Reserved_Ty(ty))
02750 {
02751 tmp_tokens = New_Token_Buffer();
02752 TY2C_translate_unqualified(tmp_tokens, ty);
02753 Append_Token_Special(tmp_tokens, ';');
02754 Append_Indented_Newline(tmp_tokens, lines_between_decls);
02755 if (tokens != NULL)
02756 Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
02757 else
02758 Write_And_Reclaim_Tokens(W2C_File[W2C_DOTH_FILE],
02759 NULL,
02760 &tmp_tokens);
02761 }
02762 }
02763 }
02764
02765 static void
02766 WN2C_Append_Symtab_Consts(TOKEN_BUFFER tokens,
02767 BOOL use_const_tab,
02768 UINT lines_between_decls,
02769 CONTEXT context)
02770 {
02771
02772
02773
02774
02775 const ST *st;
02776 TOKEN_BUFFER tmp_tokens;
02777
02778
02779 ST_IDX st_idx;
02780 FOREACH_SYMBOL(CURRENT_SYMTAB, st, st_idx)
02781 {
02782 if ((ST_sym_class(st) == CLASS_VAR && ST_is_const_var(st)) ||
02783 (ST_sym_class(st) == CLASS_CONST))
02784 {
02785 tmp_tokens = New_Token_Buffer();
02786 ST2C_decl_translate(tmp_tokens, st, context);
02787 Append_Token_Special(tmp_tokens, ';');
02788 Append_Indented_Newline(tmp_tokens, lines_between_decls);
02789 if (tokens != NULL)
02790 Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
02791 else
02792 Write_And_Reclaim_Tokens(W2C_File[W2C_DOTH_FILE],
02793 NULL,
02794 &tmp_tokens);
02795 }
02796 }
02797 }
02798
02799 static TY_IDX WN2C_get_base_type(TY_IDX idx) {
02800
02801 switch(TY_kind(idx)) {
02802 case KIND_POINTER:
02803 return TY_pointed(idx);
02804 case KIND_ARRAY:
02805 return TY_etype(idx);
02806 default:
02807 return idx;
02808 }
02809 }
02810
02811 static void
02812 WN2C_Append_Symtab_Vars(TOKEN_BUFFER tokens,
02813 INT lines_between_decls,
02814 CONTEXT context)
02815 {
02816
02817
02818
02819
02820 const ST *st;
02821 TOKEN_BUFFER tmp_tokens;
02822 ST_IDX st_idx;
02823
02824
02825
02826
02827
02828
02829 FOREACH_SYMBOL(CURRENT_SYMTAB, st, st_idx)
02830 {
02831 TY_IDX st_ty = ST_class(st) == CLASS_VAR ? ST_type(st) :
02832 ST_class(st) == CLASS_FUNC ? ST_pu_type(st) : ST_type(st);
02833 if (!ST_is_not_used(st) &&
02834 ST_sclass(st) != SCLASS_FORMAL &&
02835 ST_sclass(st) != SCLASS_FORMAL_REF &&
02836 ((ST_sym_class(st) == CLASS_VAR && !ST_is_const_var(st)) ||
02837 ST_sym_class(st) == CLASS_FUNC) &&
02838 !Stab_Reserved_St(st) &&
02839 !Stab_Is_Based_At_Common_Or_Equivalence(st) &&
02840 #ifndef TARG_NVISA
02841 !Stab_Is_Common_Block(st) &&
02842 #endif
02843 !Stab_Is_Equivalence_Block(st) &&
02844 (Stab_External_Def_Linkage(st) ||
02845 (ST_sym_class(st) == CLASS_VAR && ST_sclass(st) == SCLASS_CPLINIT) ||
02846 BE_ST_w2fc_referenced(st)))
02847 {
02848 tmp_tokens = New_Token_Buffer();
02849 if (ST_is_weak_symbol(st))
02850 {
02851 ST2C_weakext_translate(tmp_tokens, st, context);
02852 }
02853 else
02854 {
02855 ST2C_decl_translate(tmp_tokens, st, context);
02856 Append_Token_Special(tmp_tokens, ';');
02857 }
02858 Append_Indented_Newline(tmp_tokens, lines_between_decls);
02859 if (tokens != NULL)
02860 Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
02861 else
02862 Write_And_Reclaim_Tokens(W2C_File[W2C_DOTH_FILE],
02863 NULL,
02864 &tmp_tokens);
02865 }
02866 }
02867 }
02868
02869
02870 static void
02871 WN2C_Declare_Return_Variable(TOKEN_BUFFER tokens)
02872 {
02873
02874
02875
02876
02877 TOKEN_BUFFER tmp_tokens;
02878
02879
02880 tmp_tokens = New_Token_Buffer();
02881 Append_Token_String(tmp_tokens, WN2C_Return_Value_Name);
02882 TY2C_translate_unqualified(tmp_tokens, PUINFO_RETURN_TY);
02883 Append_Token_Special(tmp_tokens, ';');
02884 Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
02885 }
02886
02887
02888 static void
02889 WN2C_Declare_Return_Parameter(TOKEN_BUFFER tokens, CONTEXT context)
02890 {
02891
02892
02893
02894
02895
02896
02897
02898
02899 WN2C_Declare_Return_Variable(tokens);
02900 Append_Indented_Newline(tokens, 1);
02901
02902
02903
02904
02905 ST2C_decl_translate(tokens, PUINFO_RETURN_PARAM, context);
02906 Append_Token_Special(tokens, '=');
02907 Append_Token_Special(tokens, '&');
02908 Append_Token_String(tokens, WN2C_Return_Value_Name);
02909 Append_Token_Special(tokens, ';');
02910 Append_Indented_Newline(tokens, 1);
02911 }
02912
02913
02914 static void
02915 WN2C_Store_Return_Reg(TOKEN_BUFFER tokens,
02916 const char *var_name,
02917 STAB_OFFSET var_offset,
02918 MTYPE preg_mtype,
02919 PREG_IDX preg_offset,
02920 CONTEXT context)
02921 {
02922
02923
02924
02925 const TY_IDX preg_ty = Stab_Mtype_To_Ty(preg_mtype);
02926 TOKEN_BUFFER tmp_tokens = New_Token_Buffer();
02927 STATUS status = EMPTY_STATUS;
02928
02929
02930
02931
02932 Append_Token_String(tmp_tokens, var_name);
02933 status = WN2C_based_lvalue(tmp_tokens,
02934 TRUE,
02935 Stab_Pointer_To(PUINFO_RETURN_TY),
02936
02937 Stab_Pointer_To(PUINFO_RETURN_TY),
02938
02939 preg_ty,
02940 var_offset);
02941
02942 if (!STATUS_is_lvalue(status))
02943 Prepend_Token_Special(tmp_tokens, '*');
02944 Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
02945
02946
02947 Append_Token_Special(tokens, '=');
02948 ST2C_Use_Preg(tokens, preg_ty, preg_offset, context);
02949 Append_Token_Special(tokens, ';');
02950 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
02951 }
02952
02953
02954 static void
02955 WN2C_Load_Return_Reg(TOKEN_BUFFER tokens,
02956 TY_IDX return_ty,
02957 const char *var_name,
02958 STAB_OFFSET var_offset,
02959 MTYPE preg_mtype,
02960 PREG_IDX preg_offset,
02961 CONTEXT context)
02962 {
02963
02964
02965
02966 const TY_IDX preg_ty = Stab_Mtype_To_Ty(preg_mtype);
02967 TOKEN_BUFFER tmp_tokens = New_Token_Buffer();
02968 STATUS status = EMPTY_STATUS;
02969
02970
02971
02972
02973 Append_Token_String(tmp_tokens, var_name);
02974 status = WN2C_based_lvalue(tmp_tokens,
02975 TRUE,
02976 Stab_Pointer_To(return_ty),
02977
02978 Stab_Pointer_To(return_ty),
02979
02980 preg_ty,
02981 var_offset);
02982
02983 if (!STATUS_is_lvalue(status))
02984 Prepend_Token_Special(tmp_tokens, '*');
02985
02986
02987 ST2C_Use_Preg(tokens, preg_ty, preg_offset, context);
02988 Append_Token_Special(tokens, '=');
02989 Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
02990
02991 }
02992
02993
02994 static void
02995 WN2C_Function_Call_Lhs(TOKEN_BUFFER rhs_tokens,
02996 BOOL parm_return,
02997 TY_IDX return_ty,
02998 const WN *first_arg,
02999 CONTEXT context)
03000 {
03001
03002
03003
03004
03005
03006
03007 TOKEN_BUFFER lhs_tokens = New_Token_Buffer();
03008 STAB_OFFSET value_offset;
03009 STATUS status;
03010 BOOL return_value_is_used = TRUE;
03011 RETURN_PREG return_info = PUinfo_Get_ReturnPreg(return_ty);
03012 const RETURN_PREG *const return_info_ptr = &return_info;
03013
03014 if (parm_return)
03015 {
03016
03017
03018
03019 status = WN2C_lvalue_wn(lhs_tokens,
03020 first_arg,
03021 WN_Tree_Type(first_arg),
03022 return_ty,
03023 0,
03024 context);
03025 if (!STATUS_is_lvalue(status))
03026 Prepend_Token_Special(lhs_tokens, '*');
03027 }
03028 else
03029 {
03030 const ST *result_var = CALLSITE_return_var(WN2C_Prev_CallSite);
03031 const WN *result_store = CALLSITE_store1(WN2C_Prev_CallSite);
03032 MTYPE preg_mtype = RETURN_PREG_mtype(return_info_ptr, 0);
03033 PREG_IDX preg_offset = RETURN_PREG_offset(return_info_ptr, 0);
03034
03035
03036
03037
03038
03039 if (preg_mtype == MTYPE_V && !(TY_mtype(return_ty) != MTYPE_V))
03040 {
03041
03042 return_value_is_used = FALSE;
03043 }
03044 else if (result_var != NULL)
03045 {
03046
03047
03048
03049
03050 if (!WN2C_assignment_compatible_types(return_ty, ST_type(result_var))) {
03051 WN2C_prepend_cast(rhs_tokens, ST_type(result_var), false);
03052 }
03053 STAB_OFFSET var_offset = CALLSITE_var_offset(WN2C_Prev_CallSite);
03054 TY_IDX var_ty = ST_type(result_var);
03055
03056 Is_True(!CALLSITE_in_regs(WN2C_Prev_CallSite),
03057 ("Encountered unexpected reference to a return register"));
03058
03059
03060
03061
03062
03063
03064 if (ST_sym_class(result_var) == CLASS_PREG)
03065 {
03066 Is_True(RETURN_PREG_num_pregs(return_info_ptr) == 1,
03067 ("Unexpected number of call-value save registers"));
03068
03069 var_ty = PUinfo_Preg_Type(var_ty, var_offset);
03070 ST2C_Use_Preg(lhs_tokens,
03071 var_ty,
03072 var_offset,
03073 context);
03074 if (!WN2C_assignment_compatible_types(var_ty, return_ty))
03075 {
03076 WN2C_prepend_cast(rhs_tokens,
03077 var_ty,
03078 FALSE);
03079 }
03080 }
03081 else
03082 {
03083
03084
03085
03086
03087 if (strcmp(TY_name(ST_type(result_var)), "reg_handle_t") == 0 ||
03088 strcmp(TY_name(ST_type(result_var)), "mem_handle_t") == 0) {
03089 WN2C_prepend_cast(rhs_tokens, ST_type(result_var), FALSE);
03090 }
03091 status = WN2C_lvalue_st(lhs_tokens,
03092 result_var,
03093 Stab_Pointer_To(var_ty),
03094 ST_type(result_var),
03095 var_offset,
03096 context);
03097 if (!STATUS_is_lvalue(status))
03098 Prepend_Token_Special(lhs_tokens, '*');
03099 }
03100 }
03101 else if (result_store != NULL)
03102 {
03103 TY_IDX base_ty;
03104 TY_IDX stored_ty;
03105
03106
03107
03108
03109
03110
03111
03112 Is_True(WN_operator(result_store) == OPR_ISTORE &&
03113 WN_operator(WN_kid0(result_store)) == OPR_LDID,
03114 ("Unexpected store1 in WN2C_Function_Call_Lhs()"));
03115
03116 Is_True(!CALLSITE_in_regs(WN2C_Prev_CallSite),
03117 ("Encountered unexpected reference to a return register"));
03118
03119
03120 base_ty = WN_Tree_Type(WN_kid1(result_store));
03121 if (!TY_Is_Pointer(base_ty))
03122 base_ty = WN_ty(result_store);
03123 stored_ty = TY_pointed(WN_ty(result_store));
03124 stored_ty =
03125 WN2C_MemAccess_Type(TY_pointed(base_ty),
03126 stored_ty,
03127 WN_opc_dtype(result_store),
03128 WN_store_offset(result_store));
03129
03130 status = WN2C_lvalue_wn(lhs_tokens,
03131 WN_kid1(result_store),
03132 base_ty,
03133 stored_ty,
03134 WN_store_offset(result_store),
03135 context);
03136 if (!STATUS_is_lvalue(status))
03137 Prepend_Token_Special(lhs_tokens, '*');
03138
03139 if (!WN2C_assignment_compatible_types(stored_ty, return_ty))
03140 WN2C_prepend_cast(rhs_tokens, stored_ty, FALSE);
03141 }
03142 else if (!CALLSITE_in_regs(WN2C_Prev_CallSite))
03143 {
03144
03145
03146
03147 return_value_is_used = FALSE;
03148 }
03149 else if (RETURN_PREG_num_pregs(return_info_ptr) == 1 &&
03150 TY_Is_Preg_Type(return_ty))
03151 {
03152 TY_IDX preg_ty =
03153 PUinfo_Preg_Type(Stab_Mtype_To_Ty(preg_mtype), preg_offset);
03154
03155
03156
03157
03158
03159 ST2C_Use_Preg(lhs_tokens, preg_ty, preg_offset, context);
03160 if (!WN2C_assignment_compatible_types(preg_ty, return_ty))
03161 {
03162 WN2C_prepend_cast(rhs_tokens,
03163 preg_ty,
03164 FALSE);
03165 }
03166 }
03167 else
03168 {
03169
03170
03171
03172 const UINT tmp_idx = Stab_Lock_Tmpvar(return_ty,
03173 ST2C_Declare_Tempvar);
03174 const char *tmpvar_name = W2CF_Symtab_Nameof_Tempvar(tmp_idx);
03175
03176
03177 Append_Token_String(lhs_tokens, tmpvar_name);
03178
03179 if (TY_kind(return_ty) == KIND_STRUCT) {
03180
03181
03182
03183 strncpy(last_ret_tmp, tmpvar_name, 64);
03184 }
03185 else {
03186
03187
03188
03189 Append_Token_Special(rhs_tokens, ';');
03190 WN2C_Stmt_Newline(rhs_tokens, CONTEXT_srcpos(context));
03191 WN2C_Load_Return_Reg(rhs_tokens,
03192 return_ty,
03193 tmpvar_name,
03194 0,
03195 preg_mtype,
03196 preg_offset,
03197 context);
03198
03199 if (RETURN_PREG_num_pregs(return_info_ptr) > 1)
03200 {
03201
03202
03203
03204 value_offset = TY_size(Stab_Mtype_To_Ty(preg_mtype));
03205
03206
03207 Append_Token_Special(rhs_tokens, ';');
03208 WN2C_Stmt_Newline(rhs_tokens, CONTEXT_srcpos(context));
03209 preg_offset = RETURN_PREG_offset(return_info_ptr, 1);
03210 preg_mtype = RETURN_PREG_mtype(return_info_ptr, 1);
03211 WN2C_Load_Return_Reg(rhs_tokens,
03212 return_ty,
03213 tmpvar_name,
03214 value_offset,
03215 preg_mtype,
03216 preg_offset,
03217 context);
03218 }
03219 }
03220 Stab_Unlock_Tmpvar(tmp_idx);
03221
03222 }
03223 }
03224
03225
03226 if (return_value_is_used)
03227 {
03228 Prepend_Token_Special(rhs_tokens, '=');
03229 Prepend_And_Reclaim_Token_List(rhs_tokens, &lhs_tokens);
03230 }
03231 else
03232 {
03233 Reclaim_Token_Buffer(&lhs_tokens);
03234 }
03235 }
03236
03237
03238 static void
03239 WN2C_Function_Return_Value(TOKEN_BUFFER tokens,
03240 CONTEXT context)
03241 {
03242
03243
03244
03245
03246 TOKEN_BUFFER value_tokens;
03247 STAB_OFFSET value_offset;
03248 STATUS status;
03249
03250 value_tokens = New_Token_Buffer();
03251 if (PUINFO_RETURN_TO_PARAM)
03252 {
03253
03254
03255
03256 Append_Token_String(value_tokens, WN2C_Return_Value_Name);
03257 WN2C_Used_Return_Value = TRUE;
03258 }
03259 else
03260 {
03261 MTYPE preg_mtype;
03262 PREG_IDX preg_offset;
03263 const ST *result_var = RETURNSITE_return_var(WN2C_Next_ReturnSite);
03264 const WN *result_store = RETURNSITE_store1(WN2C_Next_ReturnSite);
03265
03266
03267 preg_offset = RETURN_PREG_offset(PUinfo_return_preg, 0);
03268 preg_mtype = RETURN_PREG_mtype(PUinfo_return_preg, 0);
03269
03270
03271
03272
03273
03274
03275 if (result_var != NULL)
03276 {
03277 STAB_OFFSET var_offset = RETURNSITE_var_offset(WN2C_Next_ReturnSite);
03278 TY_IDX var_ty = ST_type(result_var);
03279
03280
03281
03282
03283
03284 if (ST_sym_class(result_var) == CLASS_PREG)
03285 {
03286 Is_True(RETURN_PREG_num_pregs(PUinfo_return_preg) == 1,
03287 ("Unexpected number of return-value save registers"));
03288
03289 var_ty = PUinfo_Preg_Type(var_ty, var_offset);
03290 ST2C_Use_Preg(value_tokens,
03291 var_ty,
03292 var_offset,
03293 context);
03294 if (!WN2C_assignment_compatible_types(PUINFO_RETURN_TY, var_ty))
03295 {
03296 WN2C_prepend_cast(value_tokens,
03297 PUINFO_RETURN_TY,
03298 FALSE);
03299 }
03300 }
03301 else
03302 {
03303 status = WN2C_lvalue_st(value_tokens,
03304 result_var,
03305 Stab_Pointer_To(var_ty),
03306 PUINFO_RETURN_TY,
03307 var_offset,
03308 context);
03309 if (!STATUS_is_lvalue(status))
03310 Prepend_Token_Special(value_tokens, '*');
03311 }
03312 }
03313 else if (result_store != NULL)
03314 {
03315
03316
03317
03318 Is_True(WN_operator(result_store) == OPR_STID,
03319 ("Unexpected store1 in WN2C_Function_Return_Value()"));
03320
03321
03322 CONTEXT_reset_needs_lvalue(context);
03323 CONTEXT_set_top_level_expr(context);
03324 status = WN2C_translate(value_tokens, WN_kid0(result_store), context);
03325 if (!WN2C_assignment_compatible_types(PUINFO_RETURN_TY,
03326 WN_Tree_Type(WN_kid0(result_store))))
03327 {
03328 WN2C_prepend_cast(value_tokens,
03329 PUINFO_RETURN_TY,
03330 FALSE);
03331 }
03332 }
03333 else if (RETURN_PREG_num_pregs(PUinfo_return_preg) == 1 &&
03334 TY_Is_Preg_Type(PUINFO_RETURN_TY))
03335 {
03336 TY_IDX preg_ty =
03337 PUinfo_Preg_Type(Stab_Mtype_To_Ty(preg_mtype), preg_offset);
03338
03339
03340
03341
03342
03343 ST2C_Use_Preg(value_tokens, preg_ty, preg_offset, context);
03344 if (!WN2C_assignment_compatible_types(PUINFO_RETURN_TY, preg_ty))
03345 {
03346 WN2C_prepend_cast(value_tokens,
03347 PUINFO_RETURN_TY,
03348 FALSE);
03349 }
03350 }
03351 else
03352 {
03353
03354
03355
03356
03357
03358 WN2C_Store_Return_Reg(tokens,
03359 WN2C_Return_Value_Name,
03360 0,
03361 preg_mtype,
03362 preg_offset,
03363 context);
03364
03365 if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 1)
03366 {
03367
03368
03369
03370 value_offset = TY_size(Stab_Mtype_To_Ty(preg_mtype));
03371
03372
03373 preg_offset = RETURN_PREG_offset(PUinfo_return_preg, 1);
03374 preg_mtype = RETURN_PREG_mtype(PUinfo_return_preg, 1);
03375 WN2C_Store_Return_Reg(tokens,
03376 WN2C_Return_Value_Name,
03377 value_offset,
03378 preg_mtype,
03379 preg_offset,
03380 context);
03381 }
03382 Append_Token_String(value_tokens, WN2C_Return_Value_Name);
03383 WN2C_Used_Return_Value = TRUE;
03384 }
03385 }
03386
03387 Append_Token_String(tokens, "return");
03388 Append_And_Reclaim_Token_List(tokens, &value_tokens);
03389
03390 }
03391
03392
03393 static void
03394 WN2C_Append_Pragma_Newline(TOKEN_BUFFER tokens, SRCPOS srcpos)
03395 {
03396 UINT current_indent = Current_Indentation();
03397
03398 Set_Current_Indentation(0);
03399 WN2C_Stmt_Newline(tokens, srcpos);
03400 Set_Current_Indentation(current_indent);
03401 }
03402
03403
03404 static void
03405 WN2C_Callsite_Directives(TOKEN_BUFFER tokens,
03406 const WN *call_wn,
03407 const ST *func_st,
03408 CONTEXT context)
03409 {
03410 if (WN_Call_Inline(call_wn))
03411 {
03412 WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
03413 Append_Token_String(tokens, "#pragma");
03414 Append_Token_String(tokens, "inline");
03415 Append_Token_Special(tokens, '(');
03416 ST2C_use_translate(tokens, func_st, context);
03417 Append_Token_Special(tokens, ')');
03418 }
03419 else if (WN_Call_Dont_Inline(call_wn))
03420 {
03421 WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
03422 Append_Token_String(tokens, "#pragma");
03423 Append_Token_String(tokens, "noinline");
03424 Append_Token_Special(tokens, '(');
03425 ST2C_use_translate(tokens, func_st, context);
03426 Append_Token_Special(tokens, ')');
03427 }
03428 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
03429 }
03430
03431
03432 static void
03433 WN2C_Translate_Stmt_Sequence(TOKEN_BUFFER tokens,
03434 const WN *first,
03435 BOOL first_on_newline,
03436 CONTEXT context)
03437 {
03438
03439
03440
03441 const WN *stmt;
03442 STATUS status;
03443
03444 for (stmt = first; stmt != NULL; stmt = WN_next(stmt))
03445 {
03446 if (!WN2C_Skip_Stmt(stmt))
03447 {
03448
03449 CONTEXT_set_srcpos(context, WN_Get_Linenum(stmt));
03450 if (first_on_newline || stmt != first)
03451 {
03452 if (WN_operator(stmt) == OPR_DO_LOOP ||
03453 WN_operator(stmt) == OPR_WHILE_DO ||
03454 WN_operator(stmt) == OPR_DO_WHILE ||
03455 WN_operator(stmt) == OPR_CALL ||
03456 WN_operator(stmt) == OPR_PICCALL ||
03457 WN_operator(stmt) == OPR_REGION ||
03458 WN_operator(stmt) == OPR_PRAGMA ||
03459 WN_operator(stmt) == OPR_XPRAGMA &&
03460 WN_operator(stmt) == OPR_TRAP ||
03461 WN_operator(stmt) == OPR_ASSERT ||
03462 WN_operator(stmt) == OPR_FORWARD_BARRIER ||
03463 WN_operator(stmt) == OPR_BACKWARD_BARRIER)
03464 {
03465
03466
03467 }
03468 else
03469 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
03470 }
03471 status = WN2C_translate(tokens, stmt, context);
03472 if (!STATUS_is_block(status) &&
03473 WN_operator(stmt) != OPR_REGION &&
03474 WN_operator(stmt) != OPR_PRAGMA &&
03475 WN_operator(stmt) != OPR_XPRAGMA &&
03476 WN_operator(stmt) != OPR_TRAP &&
03477 WN_operator(stmt) != OPR_ASSERT &&
03478 WN_operator(stmt) != OPR_COMMENT &&
03479 WN_operator(stmt) != OPR_FORWARD_BARRIER &&
03480 WN_operator(stmt) != OPR_BACKWARD_BARRIER)
03481 Append_Token_Special(tokens, ';');
03482
03483
03484
03485 if (W2C_Emit_Frequency &&
03486 W2C_Frequency_Map != WN_MAP_UNDEFINED &&
03487 WN_MAP32_Get(W2C_Frequency_Map, stmt) >= 0 &&
03488 WN_operator(stmt) != OPR_REGION &&
03489 WN_operator(stmt) != OPR_PRAGMA &&
03490 WN_operator(stmt) != OPR_XPRAGMA &&
03491 WN_operator(stmt) != OPR_TRAP &&
03492 WN_operator(stmt) != OPR_ASSERT &&
03493 WN_operator(stmt) != OPR_FORWARD_BARRIER &&
03494 WN_operator(stmt) != OPR_BACKWARD_BARRIER)
03495 {
03496 INT32 freq = WN_MAP32_Get(W2C_Frequency_Map, stmt);
03497 Append_Token_String(tokens, " /*FREQ=");
03498 Append_Token_String(tokens, Number_as_String(freq,"%lld"));
03499 Append_Token_String(tokens, "*/");
03500 }
03501 }
03502 }
03503 }
03504
03505
03506 static void
03507 WN2C_Translate_Comma_Sequence(TOKEN_BUFFER tokens,
03508 const WN *first,
03509 CONTEXT context)
03510 {
03511
03512
03513
03514 const WN *stmt;
03515
03516 for (stmt = first; stmt != NULL; stmt = WN_next(stmt))
03517 {
03518 if (!WN2C_Skip_Stmt(stmt))
03519 {
03520
03521 CONTEXT_set_srcpos(context, WN_Get_Linenum(stmt));
03522 if (stmt != first)
03523 {
03524 Append_Token_Special(tokens, ',');
03525 }
03526 WN2C_translate(tokens, stmt, context);
03527 }
03528 }
03529 }
03530
03531
03532 void
03533 WN2C_Append_Purple_Funcinfo(TOKEN_BUFFER tokens)
03534 {
03535 const char *name = W2C_Object_Name(PUINFO_FUNC_ST);
03536 ST_IDX id = PUINFO_FUNC_ST_IDX;
03537 ST_SCLASS sclass = ST_sclass(PUINFO_FUNC_ST);
03538 ST_EXPORT export_class = (ST_EXPORT)ST_export(PUINFO_FUNC_ST);
03539
03540 Append_Token_String(tokens, name);
03541 Append_Token_Special(tokens, ',');
03542 if (strcmp(name, WN2C_Purple_Region_Name) == 0)
03543 {
03544
03545
03546
03547 id = 0xffffffff;
03548 sclass = SCLASS_TEXT;
03549 export_class = EXPORT_INTERNAL;
03550 }
03551 Append_Token_String(tokens, Number_as_String(id, "%llu"));
03552 Append_Token_Special(tokens, ',');
03553 Append_Token_String(tokens, Number_as_String(sclass, "%lld"));
03554 Append_Token_Special(tokens, ',');
03555 Append_Token_String(tokens, Number_as_String(export_class, "%lld"));
03556 Append_Token_Special(tokens, ',');
03557 Append_Token_String(tokens, "0");
03558 }
03559
03560
03561 static void
03562 Append_Cplus_Initialization(TOKEN_BUFFER tokens, CONTEXT context)
03563 {
03564 Append_Token_String(tokens, "/* C++ specific initialization */");
03565 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
03566 Append_Token_String(tokens,
03567 "if (__cplinit.ctor != NULL) __cplinit.ctor();");
03568 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
03569 }
03570
03571
03572
03573
03574
03575 static void
03576 WN2C_Prefetch_Map(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
03577 {
03578 PF_POINTER* pfptr;
03579 const char *info_str;
03580
03581 pfptr = (PF_POINTER*)WN_MAP_Get(WN_MAP_PREFETCH, wn);
03582 info_str = "/* prefetch (ptr, lrnum): ";
03583 if (pfptr->wn_pref_1L)
03584 {
03585 info_str =
03586 Concat2_Strings( info_str,
03587 Concat2_Strings( "1st <",
03588 Concat2_Strings( Ptr_as_String(pfptr->wn_pref_1L),
03589 Concat2_Strings( ", ",
03590 Concat2_Strings(Number_as_String(pfptr->lrnum_1L,"%lld"),
03591 "> ")))));
03592 }
03593 if (pfptr->wn_pref_2L)
03594 {
03595 info_str =
03596 Concat2_Strings( info_str,
03597 Concat2_Strings( "2nd <",
03598 Concat2_Strings( Ptr_as_String(pfptr->wn_pref_2L),
03599 Concat2_Strings( ", ",
03600 Concat2_Strings(Number_as_String(pfptr->lrnum_2L,"%lld"),
03601 "> ")))));
03602 }
03603 info_str = Concat2_Strings(info_str, "*/");
03604 Append_Indented_Newline(tokens, 1);
03605 Append_Token_String (tokens, info_str);
03606 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
03607 }
03608
03609
03610
03611
03612
03613 static void
03614 WN2C_Append_Prompf_Flag_Newline(TOKEN_BUFFER tokens)
03615 {
03616 UINT current_indent = Current_Indentation();
03617
03618 Set_Current_Indentation(0);
03619 Append_Indented_Newline(tokens, 1);
03620 Set_Current_Indentation(current_indent);
03621 }
03622
03623
03624 static BOOL
03625 WN2C_Is_Loop_Region(const WN *region, CONTEXT context)
03626 {
03627
03628
03629
03630 BOOL predicate = (WN_operator(region) == OPR_REGION);
03631
03632 if (predicate)
03633 {
03634 const WN *pragma = WN_first(WN_region_pragmas(region));
03635
03636 predicate = (pragma != NULL &&
03637 (WN_pragma(pragma) == WN_PRAGMA_DOACROSS ||
03638 WN_pragma(pragma) == WN_PRAGMA_PARALLEL_DO ||
03639 WN_pragma(pragma) == WN_PRAGMA_PDO_BEGIN) &&
03640 WN_pragma_nest(pragma) <= 0 &&
03641 !Ignore_Synchronized_Construct(pragma, context));
03642 }
03643 return predicate;
03644 }
03645
03646
03647 static BOOL
03648 WN2C_Is_Parallel_Region(const WN *region, CONTEXT context)
03649 {
03650 BOOL predicate = (region != NULL && WN_operator(region) == OPR_REGION);
03651
03652 if (predicate)
03653 {
03654 const WN *pragma = WN_first(WN_region_pragmas(region));
03655
03656 predicate = (pragma != NULL &&
03657 (WN_pragma(pragma) == WN_PRAGMA_PARALLEL_BEGIN ||
03658 WN_pragma(pragma) == WN_PRAGMA_MASTER_BEGIN ||
03659 WN_pragma(pragma) == WN_PRAGMA_SINGLE_PROCESS_BEGIN ||
03660 WN_pragma(pragma) == WN_PRAGMA_PSECTION_BEGIN ||
03661 WN_pragma(pragma) == WN_PRAGMA_PARALLEL_SECTIONS) &&
03662 !Ignore_Synchronized_Construct(pragma, context));
03663 }
03664 return predicate;
03665 }
03666
03667
03668 static void
03669 WN2C_Prompf_Construct_Start(TOKEN_BUFFER tokens, const WN *construct)
03670 {
03671 INT32 construct_id = WN_MAP32_Get(*W2C_Construct_Map, construct);
03672
03673 if (construct_id != 0)
03674 {
03675 WN2C_Append_Prompf_Flag_Newline(tokens);
03676 Append_Token_String(tokens, "/*$SGI");
03677 Append_Token_String(tokens, "start");
03678 Append_Token_String(tokens, Number_as_String(construct_id, "%llu"));
03679 Append_Token_String(tokens, "*/");
03680 }
03681 }
03682
03683
03684 static void
03685 WN2C_Prompf_Construct_End(TOKEN_BUFFER tokens, const WN *construct)
03686 {
03687 INT32 construct_id = WN_MAP32_Get(*W2C_Construct_Map, construct);
03688
03689 if (construct_id != 0)
03690 {
03691 WN2C_Append_Prompf_Flag_Newline(tokens);
03692 Append_Token_String(tokens, "/*$SGI");
03693 Append_Token_String(tokens, "end");
03694 Append_Token_String(tokens, Number_as_String(construct_id, "%llu"));
03695 Append_Token_String(tokens, "*/");
03696 }
03697 }
03698
03699
03700 static void
03701 WN2C_Start_Prompf_Transformed_Loop(TOKEN_BUFFER tokens,
03702 const WN *loop,
03703 CONTEXT context)
03704 {
03705
03706
03707
03708
03709 if (!WN2C_Is_Loop_Region(W2CF_Get_Parent(W2CF_Get_Parent(loop)), context))
03710 WN2C_Prompf_Construct_Start(tokens, loop);
03711 }
03712
03713
03714 static void
03715 WN2C_End_Prompf_Transformed_Loop(TOKEN_BUFFER tokens,
03716 const WN *loop,
03717 CONTEXT context)
03718 {
03719
03720
03721
03722
03723 if (!WN2C_Is_Loop_Region(W2CF_Get_Parent(W2CF_Get_Parent(loop)), context))
03724 WN2C_Prompf_Construct_End(tokens, loop);
03725 }
03726
03727
03728 static void
03729 WN2C_Start_Prompf_Transformed_Region(TOKEN_BUFFER tokens,
03730 const WN *region,
03731 CONTEXT context)
03732 {
03733
03734
03735
03736 if (WN2C_Is_Loop_Region(region, context) ||
03737 WN2C_Is_Parallel_Region(region, context))
03738 WN2C_Prompf_Construct_Start(tokens, region);
03739 }
03740
03741
03742 static void
03743 WN2C_End_Prompf_Transformed_Region(TOKEN_BUFFER tokens,
03744 const WN *region,
03745 CONTEXT context)
03746 {
03747
03748
03749
03750 if (WN2C_Is_Loop_Region(region, context) ||
03751 WN2C_Is_Parallel_Region(region, context))
03752 WN2C_Prompf_Construct_End(tokens, region);
03753 }
03754
03755
03756
03757
03758
03759 static STATUS
03760 WN2C_ignore(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
03761 {
03762 return EMPTY_STATUS;
03763 }
03764
03765
03766 static STATUS
03767 WN2C_unsupported(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
03768 {
03769 fprintf(stderr,
03770 "==> wn2c cannot handle operator <%s> (%d): construct ignored!\n",
03771 WN_opc_name(wn), WN_operator(wn));
03772
03773 Append_Token_String(tokens, Concat3_Strings("<", WN_opc_name(wn), ">"));
03774
03775 return EMPTY_STATUS;
03776 }
03777
03778
03779 static STATUS
03780 WN2C_binaryop(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
03781 {
03782 STATUS status;
03783
03784 Is_True(WN_kid_count(wn) == 2,
03785 ("Expected 2 kids in WN2C_binaryop for op %s",WN_opc_name(wn)));
03786
03787 if (WN2C_IS_INFIX_OP(WN_opcode(wn)))
03788 status = WN2C_infix_op(tokens,
03789 WN_opcode(wn),
03790 WN_Tree_Type(wn),
03791 WN_kid0(wn),
03792 WN_kid1(wn),
03793 context);
03794 else if (WN2C_IS_FUNCALL_OP(WN_opcode(wn)))
03795 status = WN2C_funcall_op(tokens,
03796 WN_opcode(wn),
03797 WN_kid0(wn),
03798 WN_kid1(wn),
03799 context);
03800 else
03801 Is_True(FALSE, ("Illegal operator (%s=%d) in WN2C_binaryop()",
03802 WN_opc_name(wn), WN_opcode(wn)));
03803
03804 return status;
03805 }
03806
03807
03808 static STATUS
03809 WN2C_unaryop(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
03810 {
03811 Is_True(WN_kid_count(wn) == 1, ("Expected 1 kid in WN2C_unaryop()"));
03812
03813 if (WN2C_IS_INFIX_OP(WN_opcode(wn)))
03814 WN2C_infix_op(tokens,
03815 WN_opcode(wn),
03816 WN_Tree_Type(wn),
03817 NULL,
03818 WN_kid0(wn),
03819 context);
03820 else if (WN2C_IS_FUNCALL_OP(WN_opcode(wn)))
03821 WN2C_funcall_op(tokens, WN_opcode(wn), NULL, WN_kid0(wn), context);
03822 else
03823 Is_True(FALSE, ("Illegal operator (%s=%d) in WN2C_unaryop()",
03824 WN_opc_name(wn), WN_opcode(wn)));
03825
03826 return EMPTY_STATUS;
03827 }
03828
03829
03830 static STATUS
03831 WN2C_func_entry(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
03832 {
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843 ST **param_st;
03844 INT param;
03845
03846 Is_True(WN_operator(wn) == OPR_FUNC_ENTRY,
03847 ("Invalid opcode for WN2C_func_entry()"));
03848
03849
03850
03851
03852 CONTEXT_set_new_func_scope(context);
03853 WN2C_Used_Return_Value = FALSE;
03854 WN2C_Next_ReturnSite = PUinfo_Get_ReturnSites();
03855 WN2C_Prev_CallSite = NULL;
03856
03857
03858 if (!W2C_No_Pragmas)
03859 WN2C_pragma_list_begin(PUinfo_pragmas,
03860 WN_first(WN_region_pragmas(wn)),
03861 context);
03862
03863
03864 WN* pragma = WN_first(WN_func_pragmas(wn));
03865 while (pragma != NULL) {
03866 pragma = WN_next(pragma);
03867 }
03868
03869
03870
03871
03872 param_st = (ST **)alloca((WN_num_formals(wn) + 1)*sizeof(ST *));
03873 for (param = 0; param < WN_num_formals(wn); param++)
03874 {
03875 Is_True(WN_operator(WN_formal(wn, param)) == OPR_IDNAME,
03876 ("Invalid opcode for parameter of OPR_FUNC_ENTRY"));
03877 param_st[param] = WN_st(WN_formal(wn, param));
03878 }
03879 param_st[WN_num_formals(wn)] = NULL;
03880
03881
03882 if (W2C_Prompf_Emission)
03883 WN2C_Prompf_Construct_Start(tokens, wn);
03884
03885
03886 CONTEXT_set_srcpos(context, WN_Get_Linenum(wn));
03887 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
03888 ST2C_func_header(tokens, WN_st(wn), param_st, context);
03889
03890
03891 CONTEXT_set_incomplete_ty2c(context);
03892 ST2C_func_header(tokens, WN_st(wn), param_st, context);
03893
03894
03895 CONTEXT_set_srcpos(context, WN_Get_Linenum(WN_func_body(wn)));
03896 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
03897 Append_Token_Special(tokens, '{');
03898 Increment_Indentation();
03899
03900 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
03901
03902 (void)WN2C_translate(tokens, WN_func_body(wn), context);
03903 if (!W2C_No_Pragmas)
03904 WN2C_pragma_list_end(tokens,
03905 WN_first(WN_region_pragmas(wn)),
03906 context);
03907 Decrement_Indentation();
03908 Append_Indented_Newline(tokens, 1);
03909 Append_Token_Special(tokens, '}');
03910
03911
03912 Append_Token_String(tokens, "/*");
03913 ST2C_use_translate(tokens, &St_Table[WN_entry_name(wn)], context);
03914 Append_Token_String(tokens, "*/");
03915
03916 if (W2C_Prompf_Emission)
03917 WN2C_Prompf_Construct_End(tokens, wn);
03918
03919
03920 Append_Indented_Newline(tokens, 2);
03921
03922
03923 WN2C_Prev_CallSite = NULL;
03924 WN2C_Next_ReturnSite = NULL;
03925 WN2C_Used_Return_Value = FALSE;
03926
03927 return EMPTY_STATUS;
03928 }
03929
03930
03931 static STATUS
03932 WN2C_block(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
03933 {
03934
03935
03936
03937 const ST *st;
03938 TOKEN_BUFFER stmt_tokens;
03939 const BOOL new_func_scope = CONTEXT_new_func_scope(context);
03940 const BOOL new_symtab = WN2C_new_symtab();
03941 UINT current_indent;
03942 STATUS status;
03943 ST_IDX st_idx;
03944
03945 Is_True(WN_operator(wn) == OPR_BLOCK,
03946 ("Invalid operator for WN2C_block()"));
03947
03948
03949
03950
03951 if (new_symtab)
03952 {
03953 FOREACH_SYMBOL(CURRENT_SYMTAB, st, st_idx)
03954 {
03955 if (ST_sym_class(st) == CLASS_VAR &&
03956 Stab_Is_Common_Block(st) &&
03957 !ST_is_split_common(st))
03958 {
03959 ST2C_New_Common_Block(st);
03960 }
03961 }
03962 }
03963
03964
03965
03966
03967
03968 if (new_func_scope)
03969 {
03970
03971
03972 CONTEXT_reset_new_func_scope(context);
03973 PUinfo_local_decls_indent = Current_Indentation();
03974 }
03975 else
03976 {
03977
03978
03979
03980
03981 Append_Token_Special(tokens, '{');
03982 Increment_Indentation();
03983 }
03984
03985
03986
03987
03988 stmt_tokens = New_Token_Buffer();
03989 if (new_func_scope &&
03990 W2C_Cplus_Initializer &&
03991 (PU_is_mainpu(Pu_Table[ST_pu(PUINFO_FUNC_ST)]) ||
03992 strcmp(ST_name(PUINFO_FUNC_ST), "main") == 0))
03993 {
03994 Append_Cplus_Initialization(stmt_tokens, context);
03995 }
03996 CONTEXT_set_top_level_expr(context);
03997 if (WN_first(wn) != NULL)
03998 WN2C_Translate_Stmt_Sequence(
03999 stmt_tokens, WN_first(wn), TRUE, context);
04000
04001
04002
04003
04004
04005
04006
04007 if (new_symtab)
04008 {
04009 current_indent = Current_Indentation();
04010 Set_Current_Indentation(PUinfo_local_decls_indent);
04011 WN2C_Append_Symtab_Consts(NULL,
04012 FALSE,
04013 1,
04014 context);
04015 WN2C_Append_Symtab_Vars(PUinfo_local_decls, 1, context);
04016 Set_Current_Indentation(current_indent);
04017
04018
04019
04020
04021
04022 Stab_Reset_Referenced_Flag(CURRENT_SYMTAB);
04023 }
04024
04025
04026
04027
04028
04029 if (new_func_scope)
04030 {
04031 current_indent = Current_Indentation();
04032 Set_Current_Indentation(PUinfo_local_decls_indent);
04033 if (PUINFO_RETURN_TO_PARAM)
04034 WN2C_Declare_Return_Parameter(PUinfo_local_decls, context);
04035 else if (WN2C_Used_Return_Value)
04036 WN2C_Declare_Return_Variable(PUinfo_local_decls);
04037 Set_Current_Indentation(current_indent);
04038
04039
04040 Append_Indented_Newline(tokens, 1);
04041 Append_And_Reclaim_Token_List(tokens, &PUinfo_local_decls);
04042
04043 if (!Is_Empty_Token_Buffer(PUinfo_pragmas))
04044 Append_Indented_Newline(PUinfo_pragmas, 1);
04045 Append_And_Reclaim_Token_List(tokens, &PUinfo_pragmas);
04046
04047
04048
04049
04050 if (W2C_Purple_Emission)
04051 {
04052
04053
04054 Append_Indented_Newline(tokens, 1);
04055 Append_Token_String(tokens, "<#PRP_XSYM:INIT_DECL");
04056 WN2C_Append_Purple_Funcinfo(tokens);
04057 Append_Token_String(tokens, "#>");
04058 }
04059 }
04060
04061
04062 Append_And_Reclaim_Token_List(tokens, &stmt_tokens);
04063
04064 if (new_func_scope && W2C_Purple_Emission &&
04065 strcmp(W2C_Object_Name(PUINFO_FUNC_ST), WN2C_Purple_Region_Name) == 0)
04066 {
04067
04068
04069 Append_Indented_Newline(tokens, 1);
04070 Append_Token_String(tokens, "<#PRP_XSYM:TEST");
04071 WN2C_Append_Purple_Funcinfo(tokens);
04072 Append_Token_String(tokens, "#>");
04073 }
04074
04075
04076
04077
04078 if (!new_func_scope)
04079 {
04080 Decrement_Indentation();
04081 Append_Indented_Newline(tokens, 1);
04082 Append_Token_Special(tokens, '}');
04083 }
04084
04085 status = EMPTY_STATUS;
04086 STATUS_set_block(status);
04087 return status;
04088 }
04089
04090
04091 static STATUS
04092 WN2C_region(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04093 {
04094
04095
04096
04097 RID *rid;
04098 BOOL good_rid;
04099
04100 Is_True(WN_operator(wn) == OPR_REGION,
04101 ("Invalid operator for WN2C_region()"));
04102
04103 Is_True(WN_operator(WN_region_body(wn)) == OPR_BLOCK,
04104 ("Expected OPR_BLOCK as body of OPR_REGION in WN2C_region()"));
04105
04106 if (W2C_Prompf_Emission)
04107 WN2C_Start_Prompf_Transformed_Region(tokens, wn, context);
04108
04109 good_rid = RID_map >= 0;
04110 if (good_rid)
04111 rid = (RID *)WN_MAP_Get(RID_map, wn);
04112 if (W2C_Emit_All_Regions ||
04113 (!W2C_No_Pragmas && good_rid &&
04114 (rid == NULL ||
04115 RID_type(rid) == RID_TYPE_pragma)))
04116 {
04117 WN2C_Append_Pragma_Newline(tokens, CONTEXT_srcpos(context));
04118 Append_Token_String(tokens, "#pragma");
04119 Append_Token_String(tokens, "region_begin");
04120
04121
04122
04123
04124 if (!W2C_No_Pragmas)
04125 WN2C_pragma_list_begin(tokens,
04126 WN_first(WN_region_pragmas(wn)),
04127 context);
04128
04129 if (WN_first(WN_region_body(wn)) != NULL)
04130 WN2C_Translate_Stmt_Sequence(tokens,
04131 WN_first(WN_region_body(wn)),
04132 TRUE,
04133 context);
04134
04135 if (!W2C_No_Pragmas)
04136 WN2C_pragma_list_end(tokens,
04137 WN_first(WN_region_pragmas(wn)),
04138 context);
04139
04140 WN2C_Append_Pragma_Newline(tokens, WN_Get_Linenum(wn));
04141 Append_Token_String(tokens, "#pragma");
04142 Append_Token_String(tokens, "region_end");
04143 }
04144 else
04145 {
04146 if (!W2C_No_Pragmas)
04147 WN2C_pragma_list_begin(tokens,
04148 WN_first(WN_region_pragmas(wn)),
04149 context);
04150
04151
04152
04153
04154 if (WN_first(WN_region_body(wn)) != NULL)
04155 WN2C_Translate_Stmt_Sequence(tokens,
04156 WN_first(WN_region_body(wn)),
04157 TRUE,
04158 context);
04159
04160 if (!W2C_No_Pragmas)
04161 WN2C_pragma_list_end(tokens,
04162 WN_first(WN_region_pragmas(wn)),
04163 context);
04164 }
04165
04166 if (W2C_Prompf_Emission)
04167 WN2C_End_Prompf_Transformed_Region(tokens, wn, context);
04168
04169 return EMPTY_STATUS;
04170 }
04171
04172
04173 static STATUS
04174 WN2C_compgoto(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04175 {
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189
04190
04191 const WN *goto_stmt;
04192 INT32 goto_entry;
04193 MTYPE switch_mty;
04194 STATUS status = EMPTY_STATUS;
04195
04196 Is_True(WN_operator(wn) == OPR_COMPGOTO,
04197 ("Invalid operator for WN2C_compgoto()"));
04198
04199
04200 switch_mty = TY_mtype(WN_Tree_Type(WN_compgoto_idx(wn)));
04201 Append_Token_String(tokens, "switch");
04202 Append_Token_Special(tokens, '(');
04203 (void)WN2C_translate(tokens, WN_compgoto_idx(wn), context);
04204 Append_Token_Special(tokens, ')');
04205
04206
04207 Append_Indented_Newline(tokens, 1);
04208 Append_Token_Special(tokens, '{');
04209 Append_Indented_Newline(tokens, 1);
04210
04211
04212 goto_stmt = WN_first(WN_compgoto_table(wn));
04213 for (goto_entry = 0; goto_entry < WN_compgoto_num_cases(wn); goto_entry++)
04214 {
04215 Is_True(WN_operator(goto_stmt) == OPR_GOTO,
04216 ("Expected each COMPGOTO case to be an OPR_GOTO"));
04217 Append_Token_String(tokens, "case");
04218 if (switch_mty != MTYPE_M)
04219 TCON2C_translate(tokens, Host_To_Targ(switch_mty, goto_entry));
04220 Append_Token_Special(tokens, ':');
04221 Increment_Indentation();
04222 Append_Indented_Newline(tokens, 1);
04223 (void)WN2C_translate(tokens, goto_stmt, context);
04224 Append_Token_Special(tokens, ';');
04225 Decrement_Indentation();
04226 Append_Indented_Newline(tokens, 1);
04227 goto_stmt = WN_next(goto_stmt);
04228 }
04229 if (WN_compgoto_has_default_case(wn))
04230 {
04231 goto_stmt = WN_kid(wn,2);
04232 Is_True(WN_operator(goto_stmt) == OPR_GOTO,
04233 ("Expected COMPGOTO default case to be an OPR_GOTO"));
04234
04235 Append_Token_String(tokens, "default");
04236 Append_Token_Special(tokens, ':');
04237 Increment_Indentation();
04238 Append_Indented_Newline(tokens, 1);
04239 (void)WN2C_translate(tokens, goto_stmt, context);
04240 Append_Token_Special(tokens, ';');
04241 Decrement_Indentation();
04242 Append_Indented_Newline(tokens, 1);
04243 }
04244
04245
04246 Append_Token_Special(tokens, '}');
04247
04248 STATUS_set_block(status);
04249 return status;
04250 }
04251
04252
04253 static STATUS
04254 WN2C_switch(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04255 {
04256
04257
04258
04259
04260
04261
04262
04263
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273
04274
04275
04276
04277 const WN *goto_stmt;
04278 MTYPE switch_mty;
04279 STATUS status = EMPTY_STATUS;
04280
04281 Is_True(WN_operator(wn) == OPR_SWITCH,
04282 ("Invalid operator for WN2C_switch()"));
04283
04284
04285 switch_mty = TY_mtype(WN_Tree_Type(WN_compgoto_idx(wn)));
04286 Append_Token_String(tokens, "switch");
04287 Append_Token_Special(tokens, '(');
04288 (void)WN2C_translate(tokens, WN_switch_test(wn), context);
04289 Append_Token_Special(tokens, ')');
04290
04291
04292 Append_Indented_Newline(tokens, 1);
04293 Append_Token_Special(tokens, '{');
04294 Append_Indented_Newline(tokens, 1);
04295
04296
04297 for (goto_stmt = WN_first(WN_switch_table(wn));
04298 goto_stmt != NULL;
04299 goto_stmt = WN_next(goto_stmt))
04300 {
04301 Is_True(WN_operator(goto_stmt) == OPR_CASEGOTO,
04302 ("Expected each SWITCH case to be an OPR_CASEGOTO"));
04303 Append_Token_String(tokens, "case");
04304 TCON2C_translate(tokens,
04305 Host_To_Targ(switch_mty, WN_const_val(goto_stmt)));
04306 Append_Token_Special(tokens, ':');
04307 Increment_Indentation();
04308 Append_Indented_Newline(tokens, 1);
04309 (void)WN2C_translate(tokens, goto_stmt, context);
04310 Append_Token_Special(tokens, ';');
04311 Decrement_Indentation();
04312 Append_Indented_Newline(tokens, 1);
04313 }
04314 if (WN_switch_has_default_case(wn))
04315 {
04316 goto_stmt = WN_switch_default(wn);
04317 Is_True(WN_operator(goto_stmt) == OPR_GOTO,
04318 ("Expected SWITCH default case to be an OPR_GOTO"));
04319
04320 Append_Token_String(tokens, "default");
04321 Append_Token_Special(tokens, ':');
04322 Increment_Indentation();
04323 Append_Indented_Newline(tokens, 1);
04324 (void)WN2C_translate(tokens, goto_stmt, context);
04325 Append_Token_Special(tokens, ';');
04326 Decrement_Indentation();
04327 Append_Indented_Newline(tokens, 1);
04328 }
04329
04330
04331 Append_Token_Special(tokens, '}');
04332
04333 STATUS_set_block(status);
04334 return status;
04335 }
04336
04337
04338 static STATUS
04339 WN2C_do_loop(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04340 {
04341
04342
04343
04344
04345
04346 STATUS status;
04347 const WN *loop_info;
04348
04349 Is_True(WN_operator(wn) == OPR_DO_LOOP,
04350 ("Invalid operator for WN2C_do_loop()"));
04351
04352 if (W2C_Prompf_Emission)
04353 {
04354 WN2C_Start_Prompf_Transformed_Loop(tokens, wn, context);
04355 }
04356 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
04357
04358 loop_info = WN_do_loop_info(wn);
04359 if (W2C_Emit_Cgtag && loop_info != NULL)
04360 {
04361 Append_Token_String(tokens, "/* LOOPINFO #");
04362 Append_Token_String(tokens, Number_as_String(UINTPS(loop_info), "%ul"));
04363 Append_Token_String(tokens, "*/");
04364 Append_Indented_Newline(tokens, 1);
04365 }
04366
04367
04368 Append_Token_String(tokens, "for");
04369 Append_Token_Special(tokens, '(');
04370 (void)WN2C_translate(tokens, WN_start(wn), context);
04371 Append_Token_Special(tokens, ';');
04372 (void)WN2C_translate(tokens, WN_end(wn), context);
04373 Append_Token_Special(tokens, ';');
04374 (void)WN2C_translate(tokens, WN_step(wn), context);
04375 Append_Token_Special(tokens, ')');
04376
04377
04378 WN2C_incr_indentation_for_stmt_body(WN_do_body(wn));
04379 CONTEXT_set_srcpos(context, WN_Get_Linenum(WN_do_body(wn)));
04380 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
04381 status = WN2C_translate(tokens, WN_do_body(wn), context);
04382 WN2C_decr_indentation_for_stmt_body(WN_do_body(wn));
04383
04384 if (W2C_Prompf_Emission)
04385 WN2C_End_Prompf_Transformed_Loop(tokens, wn, context);
04386
04387 return status;
04388 }
04389
04390
04391 static STATUS
04392 WN2C_do_while(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04393 {
04394
04395
04396 Is_True(WN_operator(wn) == OPR_DO_WHILE,
04397 ("Invalid operator for WN2C_do_while()"));
04398
04399 if (W2C_Prompf_Emission)
04400 WN2C_Start_Prompf_Transformed_Loop(tokens, wn, context);
04401
04402 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
04403
04404
04405 Append_Token_String(tokens, "do");
04406
04407
04408 WN2C_incr_indentation_for_stmt_body(WN_while_body(wn));
04409 CONTEXT_set_srcpos(context, WN_Get_Linenum(WN_while_body(wn)));
04410 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
04411 (void)WN2C_translate(tokens, WN_while_body(wn), context);
04412 WN2C_decr_indentation_for_stmt_body(WN_while_body(wn));
04413
04414
04415 WN2C_Stmt_Newline(tokens, WN_Get_Linenum(wn));
04416 Append_Token_String(tokens, "while");
04417 Append_Token_Special(tokens, '(');
04418 (void)WN2C_translate(tokens, WN_while_test(wn), context);
04419 Append_Token_Special(tokens, ')');
04420
04421 if (W2C_Prompf_Emission)
04422 WN2C_End_Prompf_Transformed_Loop(tokens, wn, context);
04423
04424 return EMPTY_STATUS;
04425 }
04426
04427
04428 static STATUS
04429 WN2C_while_do(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04430 {
04431
04432 STATUS status;
04433
04434 Is_True(WN_operator(wn) == OPR_WHILE_DO,
04435 ("Invalid operator for WN2C_while_do()"));
04436
04437 if (W2C_Prompf_Emission)
04438 {
04439 WN2C_Start_Prompf_Transformed_Loop(tokens, wn, context);
04440 }
04441 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
04442
04443
04444 Append_Token_String(tokens, "while");
04445 Append_Token_Special(tokens, '(');
04446 (void)WN2C_translate(tokens, WN_while_test(wn), context);
04447 Append_Token_Special(tokens, ')');
04448
04449
04450 WN2C_incr_indentation_for_stmt_body(WN_while_body(wn));
04451 CONTEXT_set_srcpos(context, WN_Get_Linenum(WN_while_body(wn)));
04452 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
04453 status = WN2C_translate(tokens, WN_while_body(wn), context);
04454 WN2C_decr_indentation_for_stmt_body(WN_while_body(wn));
04455
04456 if (W2C_Prompf_Emission)
04457 WN2C_End_Prompf_Transformed_Loop(tokens, wn, context);
04458
04459 return status;
04460 }
04461
04462
04463 static STATUS
04464 WN2C_if(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04465 {
04466 STATUS status;
04467
04468 Is_True(WN_operator(wn) == OPR_IF, ("Invalid operator for WN2C_if()"));
04469
04470
04471
04472
04473 if (WN_Is_If_Guard(wn))
04474 {
04475
04476 if (WN_operator(WN_then(wn)) != OPR_BLOCK)
04477 {
04478 CONTEXT_set_srcpos(context, WN_Get_Linenum(WN_then(wn)));
04479 status = WN2C_translate(tokens, WN_then(wn), context);
04480 }
04481 else
04482 {
04483 WN2C_Translate_Stmt_Sequence(
04484 tokens, WN_first(WN_then(wn)), FALSE, context);
04485 }
04486 }
04487 else
04488 {
04489
04490 Append_Token_String(tokens, "if");
04491 Append_Token_Special(tokens, '(');
04492 (void)WN2C_translate(tokens, WN_if_test(wn), context);
04493 Append_Token_Special(tokens, ')');
04494
04495
04496 WN2C_incr_indentation_for_stmt_body(WN_then(wn));
04497 CONTEXT_set_srcpos(context, WN_Get_Linenum(WN_then(wn)));
04498 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
04499 status = WN2C_translate(tokens, WN_then(wn), context);
04500 WN2C_decr_indentation_for_stmt_body(WN_then(wn));
04501
04502
04503 if (!WN_else_is_empty(wn))
04504 {
04505
04506 Append_Indented_Newline(tokens, 1);
04507 Append_Token_String(tokens, "else");
04508 WN2C_incr_indentation_for_stmt_body(WN_else(wn));
04509 CONTEXT_set_srcpos(context, WN_Get_Linenum(WN_else(wn)));
04510 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
04511 status = WN2C_translate(tokens, WN_else(wn), context);
04512 WN2C_decr_indentation_for_stmt_body(WN_else(wn));
04513 }
04514 }
04515
04516 return status;
04517 }
04518
04519
04520 static STATUS
04521 WN2C_goto(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04522 {
04523 Is_True(WN_operator(wn) == OPR_GOTO ||
04524 WN_operator(wn) == OPR_CASEGOTO ||
04525 WN_operator(wn) == OPR_REGION_EXIT,
04526 ("Invalid operator for WN2C_goto()"));
04527 Append_Token_String(tokens, "goto");
04528 WN2C_append_label_name(tokens, wn);
04529
04530 return EMPTY_STATUS;
04531 }
04532
04533 static STATUS
04534 WN2C_agoto(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04535 {
04536 Is_True(WN_operator(wn) == OPR_AGOTO,
04537 ("Invalid operator for WN2C_agoto()"));
04538 Append_Token_String(tokens, "goto *");
04539
04540 if(WN_operator(WN_kid0(wn))==OPR_ILOAD)
04541 WN2C_iload(tokens,WN_kid0(wn),context);
04542
04543 if(WN_operator(WN_kid0(wn))==OPR_LDA_LABEL)
04544 WN2C_lda_label(tokens,WN_kid0(wn),context);
04545
04546 if(WN_operator(WN_kid0(wn))==OPR_CVT)
04547 WN2C_cvt(tokens,WN_kid0(wn),context);
04548
04549 if(WN_operator(WN_kid0(wn))==OPR_INTCONST)
04550 WN2C_intconst(tokens,WN_kid0(wn),context);
04551
04552 if(WN_operator(WN_kid0(wn))==OPR_LDID)
04553 WN2C_ldid(tokens,WN_kid0(wn),context);
04554 return EMPTY_STATUS;
04555 }
04556
04557
04558 static STATUS
04559 WN2C_altentry(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04560 {
04561
04562 Is_True(WN_operator(wn) == OPR_ALTENTRY,
04563 ("Invalid operator for WN2C_altentry()"));
04564 Append_Token_String(tokens, "__OPR_ALTENTRY");
04565 Append_Token_Special(tokens, '(');
04566 Append_Token_String(tokens, ST_name(WN_st(wn)));
04567 Append_Token_Special(tokens, ')');
04568
04569 return EMPTY_STATUS;
04570 }
04571
04572
04573 static STATUS
04574 WN2C_condbr(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04575 {
04576 Is_True(WN_operator(wn) == OPR_TRUEBR || WN_operator(wn) == OPR_FALSEBR,
04577 ("Invalid operator for WN2C_condbr()"));
04578
04579
04580 Append_Token_String(tokens, "if");
04581 Append_Token_Special(tokens, '(');
04582 if (WN_operator(wn) == OPR_FALSEBR)
04583 {
04584 Append_Token_Special(tokens, '!');
04585 Append_Token_Special(tokens, '(');
04586 (void)WN2C_translate(tokens, WN_condbr_cond(wn), context);
04587 Append_Token_Special(tokens, ')');
04588 }
04589 else
04590 {
04591 (void)WN2C_translate(tokens, WN_condbr_cond(wn), context);
04592 }
04593 Append_Token_Special(tokens, ')');
04594
04595
04596 Increment_Indentation();
04597 Append_Indented_Newline(tokens, 1);
04598 Append_Token_String(tokens, "goto");
04599 WN2C_append_label_name(tokens, wn);
04600 Decrement_Indentation();
04601
04602 return EMPTY_STATUS;
04603 }
04604
04605
04606 static STATUS
04607 WN2C_return(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04608 {
04609
04610
04611
04612 Is_True(WN_operator(wn) == OPR_RETURN,
04613 ("Invalid operator for WN2C_return()"));
04614 Is_True(RETURNSITE_return(WN2C_Next_ReturnSite) == wn,
04615 ("RETURNSITE out of sequence in WN2C_return()"));
04616
04617 if (PUINFO_RETURN_TY != (TY_IDX) 0 &&
04618 TY_kind(PUINFO_RETURN_TY) != KIND_VOID &&
04619 RETURN_PREG_mtype(PUinfo_return_preg, 0) != MTYPE_V)
04620 {
04621 WN2C_Function_Return_Value(tokens, context);
04622 }
04623 else
04624 {
04625 Append_Token_String(tokens, "return");
04626 }
04627
04628 WN2C_Next_ReturnSite = RETURNSITE_next(WN2C_Next_ReturnSite);
04629
04630 return EMPTY_STATUS;
04631 }
04632
04633 static STATUS
04634 WN2C_return_val(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04635 {
04636 char buf[64];
04637 Is_True(WN_operator(wn) == OPR_RETURN_VAL,
04638 ("Invalid operator for WN2C_return_val()"));
04639 Append_Token_String(tokens, "return ");
04640 Append_Token_Special(tokens, '(');
04641 (void) WN2C_translate(tokens, WN_kid0(wn), context);
04642 Append_Token_Special(tokens, ')');
04643 return EMPTY_STATUS;
04644 }
04645
04646 static STATUS
04647 WN2C_lda_label(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04648 {
04649 Is_True(WN_operator(wn) == OPR_LDA_LABEL,
04650 ("Invalid operator for WN2C_label()"));
04651
04652 Append_Token_Special(tokens, '&');
04653 Append_Token_Special(tokens, '&');
04654 WN2C_append_label_name(tokens, wn);
04655
04656 return EMPTY_STATUS;
04657 }
04658
04659 static STATUS
04660 WN2C_label(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04661 {
04662 Is_True(WN_operator(wn) == OPR_LABEL,
04663 ("Invalid operator for WN2C_label()"));
04664
04665 WN2C_append_label_name(tokens, wn);
04666 Append_Token_Special(tokens, ':');
04667
04668 return EMPTY_STATUS;
04669 }
04670
04671
04672 static STATUS
04673 WN2C_exc_scope_end(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04674 {
04675 UINT current_indent = Current_Indentation();
04676
04677 Set_Current_Indentation(0);
04678 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
04679 Append_Token_String(tokens, "#pragma");
04680 Set_Current_Indentation(current_indent);
04681 Append_Token_String(tokens, "EXCEPTION_SCOPE_END");
04682 return EMPTY_STATUS;
04683 }
04684
04685
04686 static STATUS
04687 WN2C_exc_scope_begin(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04688 {
04689 UINT current_indent = Current_Indentation();
04690
04691 Set_Current_Indentation(0);
04692 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
04693 Append_Token_String(tokens, "#pragma");
04694 Set_Current_Indentation(current_indent);
04695 Append_Token_String(tokens, "EXCEPTION_SCOPE_BEGIN");
04696 return EMPTY_STATUS;
04697 }
04698
04699
04700 static STATUS
04701 WN2C_istore(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04702 {
04703
04704
04705
04706 TY_IDX stored_ty;
04707 TOKEN_BUFFER lhs_tokens;
04708
04709 Is_True(WN_operator(wn) == OPR_ISTORE ||
04710 (WN_operator(wn) == OPR_STID &&
04711 ST_sclass(WN_st(wn)) == SCLASS_FORMAL_REF),
04712 ("Invalid operator for WN2C_istore()"));
04713 Is_True(WN_operator(wn) != OPR_ISTORE || TY_Is_Pointer(WN_ty(wn)),
04714 ("Expected WN_ty to be a pointer for WN2C_istore()"));
04715
04716
04717
04718
04719 if (W2C_Emit_Prefetch && WN_MAP_Get(WN_MAP_PREFETCH, wn))
04720 WN2C_Prefetch_Map(tokens, wn, context);
04721
04722
04723
04724 lhs_tokens = New_Token_Buffer();
04725 if (WN_operator(wn) == OPR_STID)
04726 {
04727 char lhs_address_area [sizeof (WN)];
04728 WN* lhs_address = (WN*) &lhs_address_area;;
04729
04730 WN2C_create_ref_param_lda(lhs_address, wn);
04731 WN2C_memref_lhs(lhs_tokens,
04732 &stored_ty,
04733 lhs_address,
04734 WN_store_offset(wn),
04735 WN_ty(lhs_address),
04736 WN_ty(wn),
04737 WN_opc_dtype(wn),
04738 context);
04739 }
04740 else
04741 {
04742
04743
04744 TY_IDX base_ty = TY_pointed(WN_ty(wn));
04745 TY_IDX actual_ty = (WN_field_id(wn) > 0) ? Make_Pointer_Type(Get_Field_Type(base_ty, WN_field_id(wn))) : WN_ty(wn);
04746
04747 STAB_OFFSET offt = WN_store_offset(wn);
04748 if (TY_is_union(base_ty) && WN_field_id(wn) > 0) {
04749 offt = WN2C_get_union_offset(base_ty, WN_field_id(wn));
04750 }
04751
04752 WN2C_memref_lhs(lhs_tokens,
04753 &stored_ty,
04754 WN_kid1(wn),
04755 offt,
04756 actual_ty,
04757 TY_pointed(WN_ty(wn)),
04758 WN_opc_dtype(wn),
04759 context);
04760 }
04761
04762
04763 WN2C_Append_Assignment(tokens,
04764 &lhs_tokens,
04765 WN_kid0(wn),
04766 stored_ty,
04767 context);
04768
04769 return EMPTY_STATUS;
04770 }
04771
04772
04773 static STATUS
04774 WN2C_istorex(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04775 {
04776
04777
04778
04779
04780
04781 TY_IDX object_ty;
04782 TOKEN_BUFFER lhs_tokens;
04783
04784 Is_True((WN_operator(wn) == OPR_ISTOREX &&
04785 WN_operator(WN_kid1(wn)) == OPR_LDID &&
04786 WN_operator(WN_kid(wn,2)) == OPR_LDID &&
04787 ST_sym_class(WN_st(WN_kid1(wn))) == CLASS_PREG &&
04788 ST_sym_class(WN_st(WN_kid(wn,2))) == CLASS_PREG),
04789 ("Invalid WN tree for WN2C_istorex()"));
04790 Is_True(TY_Is_Pointer(WN_ty(wn)),
04791 ("Expected WN_ty to be a pointer for WN2C_istorex()"));
04792
04793
04794 object_ty =
04795 WN2C_MemAccess_Type(TY_pointed(WN_ty(wn)),
04796 WN_Tree_Type(WN_kid0(wn)),
04797 WN_opc_dtype(wn),
04798 WN_store_offset(wn));
04799
04800 lhs_tokens = New_Token_Buffer();
04801 WN2C_Load_From_PregIdx(lhs_tokens,
04802 WN_st(WN_kid1(wn)),
04803 WN_load_offset(WN_kid1(wn)),
04804 WN_st(WN_kid(wn,2)),
04805 WN_load_offset(WN_kid(wn,2)),
04806 object_ty,
04807 context);
04808
04809
04810 WN2C_Append_Assignment(tokens,
04811 &lhs_tokens,
04812 WN_kid0(wn),
04813 object_ty,
04814 context);
04815
04816 return EMPTY_STATUS;
04817 }
04818
04819
04820 static STATUS
04821 WN2C_mstore(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04822 {
04823
04824
04825
04826
04827
04828
04829 TY_IDX base_ty;
04830 TY_IDX stored_ty;
04831 TOKEN_BUFFER lhs_tokens;
04832 STATUS lhs_status;
04833
04834 Is_True(WN_operator(wn) == OPR_MSTORE,
04835 ("Invalid operator for WN2C_mstore()"));
04836 Is_True(TY_Is_Pointer(WN_ty(wn)),
04837 ("Expected WN_ty to be a pointer for WN2C_mstore()"));
04838
04839
04840 base_ty = WN_Tree_Type(WN_kid1(wn));
04841 if (!TY_Is_Pointer(base_ty))
04842 base_ty = WN_ty(wn);
04843 stored_ty = TY_pointed(WN_ty(wn));
04844 if (WN_field_id(wn) != 0) {
04845
04846 stored_ty = Get_Field_Type(stored_ty, WN_field_id(wn));
04847 }
04848 else {
04849 stored_ty =
04850 WN2C_MemAccess_Type(TY_pointed(base_ty),
04851 stored_ty,
04852 MTYPE_M,
04853 WN_store_offset(wn));
04854 }
04855
04856 if (WN_operator(WN_kid0(wn)) == OPR_MLOAD)
04857 {
04858
04859
04860
04861 if (TY_Is_Structured(stored_ty) &&
04862 WN_operator(WN_kid1(WN_kid0(wn))) == OPR_INTCONST)
04863 {
04864
04865
04866 lhs_tokens = New_Token_Buffer();
04867 lhs_status = WN2C_lvalue_wn(lhs_tokens,
04868 WN_kid1(wn),
04869 base_ty,
04870 stored_ty,
04871 WN_store_offset(wn),
04872 context);
04873
04874
04875
04876 if (!STATUS_is_lvalue(lhs_status))
04877 Prepend_Token_Special(lhs_tokens, '*');
04878
04879
04880 WN2C_Append_Assignment(tokens,
04881 &lhs_tokens,
04882 WN_kid0(wn),
04883 stored_ty,
04884 context);
04885 }
04886 else
04887 {
04888
04889 Append_Token_String(tokens, "__MSTORE");
04890 Append_Token_Special(tokens, '(');
04891 (void)WN2C_translate(tokens, WN_kid0(WN_kid0(wn)), context);
04892 Append_Token_Special(tokens, ',');
04893 TCON2C_translate(tokens,
04894 Host_To_Targ(MTYPE_I8, WN_load_offset(WN_kid0(wn))));
04895 Append_Token_Special(tokens, ',');
04896 (void)WN2C_translate(tokens, WN_kid1(wn), context);
04897 Append_Token_Special(tokens, ',');
04898 TCON2C_translate(tokens, Host_To_Targ(MTYPE_I8, WN_store_offset(wn)));
04899
04900 Append_Token_Special(tokens, ',');
04901 (void)WN2C_translate(tokens, WN_kid(wn,2), context);
04902 Append_Token_Special(tokens, ')');
04903 }
04904 }
04905 else
04906 {
04907 TY_IDX rhs_ty = WN_Tree_Type(WN_kid0(wn));
04908 TY_IDX rhs_ptr = Stab_Pointer_To(rhs_ty);
04909 const INT32 rhs_size = TY_size(rhs_ty);
04910 const UINT tmp_idx1 = Stab_Lock_Tmpvar(rhs_ty, ST2C_Declare_Tempvar);
04911 const UINT tmp_idx2 = Stab_Lock_Tmpvar(rhs_ptr, ST2C_Declare_Tempvar);
04912 const char *induction_var_name = W2CF_Symtab_Nameof_Tempvar(tmp_idx1);
04913 const char *ptr_var_name = W2CF_Symtab_Nameof_Tempvar(tmp_idx2);
04914
04915
04916
04917
04918 Append_Token_String(tokens, ptr_var_name);
04919 Append_Token_Special(tokens, '=');
04920 WN2C_append_cast(tokens, rhs_ty, TRUE);
04921 (void)WN2C_translate(tokens, WN_kid1(wn), context);
04922 if (WN_store_offset(wn) > 0)
04923 {
04924 Append_Token_Special(tokens, '+');
04925 TCON2C_translate(tokens,
04926 Host_To_Targ(MTYPE_I8,
04927 WN_store_offset(wn)/rhs_size));
04928 }
04929 Append_Token_Special(tokens, ';');
04930 Append_Indented_Newline(tokens, 1);
04931
04932
04933
04934 Append_Token_String(tokens, "for");
04935 Append_Token_Special(tokens, '(');
04936 Append_Token_String(tokens, induction_var_name);
04937 Append_Token_Special(tokens, '=');
04938 TCON2C_translate(tokens, Host_To_Targ(MTYPE_I8, 0));
04939 Append_Token_Special(tokens, ';');
04940 Append_Token_String(tokens, induction_var_name);
04941 Append_Token_Special(tokens, '<');
04942 Append_Token_Special(tokens, '(');
04943 (void)WN2C_translate(tokens, WN_kid(wn,2), context);
04944 Append_Token_Special(tokens, '/');
04945 TCON2C_translate(tokens, Host_To_Targ(MTYPE_I8, rhs_size));
04946 Append_Token_Special(tokens, ')');
04947 Append_Token_Special(tokens, ';');
04948 Append_Token_String(tokens, Concat2_Strings(induction_var_name, "++"));
04949 Append_Token_Special(tokens, ')');
04950
04951
04952 Increment_Indentation();
04953 Append_Indented_Newline(tokens, 1);
04954 Append_Token_String(tokens, ptr_var_name);
04955 Append_Token_Special(tokens, '[');
04956 Append_Token_String(tokens, induction_var_name);
04957 Append_Token_Special(tokens, ']');
04958 Append_Token_Special(tokens, '=');
04959 (void)WN2C_translate(tokens, WN_kid0(wn), context);
04960 Decrement_Indentation();
04961
04962 Stab_Unlock_Tmpvar(tmp_idx1);
04963 Stab_Unlock_Tmpvar(tmp_idx2);
04964 }
04965
04966 return EMPTY_STATUS;
04967 }
04968
04969
04970 static STATUS
04971 WN2C_stid(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
04972 {
04973
04974
04975
04976 TOKEN_BUFFER lhs_tokens;
04977 TY_IDX stored_ty;
04978
04979 Is_True(WN_operator(wn) == OPR_STID,
04980 ("Invalid operator for WN2C_stid()"));
04981
04982 if (ST_sym_class(WN_st(wn))==CLASS_VAR && ST_is_not_used(WN_st(wn)))
04983 {
04984
04985
04986
04987 (void)WN2C_translate(tokens, WN_kid0(wn), context);
04988 }
04989 else if (ST_sclass(WN_st(wn)) == SCLASS_FORMAL_REF)
04990 {
04991 (void)WN2C_istore(tokens, wn, context);
04992 }
04993 else
04994 {
04995
04996 TY_IDX stored_ty = WN_ty(wn);
04997 STAB_OFFSET offt = WN_store_offset(wn);
04998 if (WN_field_id(wn) != 0) {
04999 if (TY_is_union(stored_ty)) {
05000 offt = WN2C_get_union_offset(stored_ty, WN_field_id(wn));
05001 }
05002 stored_ty = Get_Field_Type(stored_ty, WN_field_id(wn));
05003 }
05004
05005 lhs_tokens = New_Token_Buffer();
05006 WN2C_stid_lhs(lhs_tokens,
05007 &stored_ty,
05008 WN_st(wn),
05009 offt,
05010 stored_ty,
05011 WN_opc_dtype(wn),
05012 context,
05013 WN_field_id(wn));
05014
05015
05016 WN2C_Append_Assignment(tokens,
05017 &lhs_tokens,
05018 WN_kid0(wn),
05019 stored_ty,
05020 context);
05021 }
05022 return EMPTY_STATUS;
05023 }
05024
05025
05026 static STATUS
05027 WN2C_call(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05028 {
05029
05030
05031
05032
05033
05034
05035 INT arg_idx, first_arg_idx, last_arg_idx;
05036 TY_IDX func_ty, return_ty;
05037 TYLIST_IDX param_tylist;
05038 TOKEN_BUFFER call_tokens, arg_tokens;
05039 BOOL return_to_param;
05040
05041
05042
05043 if (WN_operator(wn) == OPR_CALL || WN_operator(wn) == OPR_PICCALL)
05044 {
05045 WN2C_Callsite_Directives(tokens, wn, &St_Table[WN_entry_name(wn)],
05046 context);
05047 }
05048
05049
05050 call_tokens = New_Token_Buffer();
05051
05052
05053
05054
05055
05056
05057 CONTEXT_reset_top_level_expr(context);
05058 if (WN_operator(wn) == OPR_CALL)
05059 {
05060 ST2C_use_translate(call_tokens, &St_Table[WN_entry_name(wn)], context);
05061 func_ty = ST_pu_type(&St_Table[WN_entry_name(wn)]);
05062 return_to_param = Func_Return_To_Param(func_ty);
05063 return_ty = Func_Return_Type(func_ty);
05064 first_arg_idx = (return_to_param? 1 : 0);
05065 last_arg_idx = WN_kid_count(wn) - 1;
05066 }
05067 else if (WN_operator(wn) == OPR_ICALL)
05068 {
05069 Is_True(WN_ty(wn) != (TY_IDX) 0,
05070 ("Expected non-null WN_ty for ICALL in WN_call()"));
05071
05072 (void)WN2C_translate(call_tokens,
05073 WN_kid(wn, WN_kid_count(wn) - 1),
05074 context);
05075
05076
05077 WHIRL2C_parenthesize(call_tokens);
05078
05079
05080
05081
05082
05083
05084
05085 func_ty = WN_ty(wn);
05086 return_to_param = Func_Return_To_Param(func_ty);
05087 return_ty = Func_Return_Type(func_ty);
05088 first_arg_idx = (return_to_param? 1 : 0);
05089 last_arg_idx = WN_kid_count(wn) - 2;
05090 }
05091 else if (WN_operator(wn) == OPR_PICCALL)
05092 {
05093 Is_True(WN_entry_name(wn) != 0,
05094 ("Expected non-null WN_entry_name for PICCALL in WN_call()"));
05095 ST2C_use_translate(call_tokens, &St_Table[WN_entry_name(wn)], context);
05096 func_ty = ST_pu_type(&St_Table[WN_entry_name(wn)]);
05097 return_to_param = Func_Return_To_Param(func_ty);
05098 return_ty = Func_Return_Type(func_ty);
05099 first_arg_idx = (return_to_param? 1 : 0);
05100 last_arg_idx = WN_kid_count(wn) - 2;
05101 }
05102 else
05103 {
05104 Is_True(WN_operator(wn) == OPR_INTRINSIC_CALL,
05105 ("Invalid operator for WN2C_call()"));
05106
05107 Append_Token_String(call_tokens,
05108 WN_intrinsic_name((INTRINSIC)WN_intrinsic(wn)));
05109
05110
05111
05112
05113
05114 func_ty = (TY_IDX) 0;
05115 return_ty = WN_intrinsic_return_ty(WN_opcode(wn),
05116 (INTRINSIC)WN_intrinsic(wn), wn);
05117 return_to_param = WN_intrinsic_return_to_param(return_ty);
05118 first_arg_idx = (return_to_param? 1 : 0);
05119 last_arg_idx = WN_kid_count(wn) - 1;
05120 }
05121
05122
05123
05124
05125
05126 Append_Token_Special(call_tokens, '(');
05127 CONTEXT_set_top_level_expr(context);
05128 if (func_ty != (TY_IDX) 0 && TY_has_prototype(func_ty))
05129 param_tylist = TY_parms(func_ty);
05130 else
05131 param_tylist = (TYLIST_IDX) 0;
05132 for (arg_idx = first_arg_idx; arg_idx <= last_arg_idx; arg_idx++)
05133 {
05134 arg_tokens = New_Token_Buffer();
05135
05136
05137
05138
05139 if (Tylist_Table[param_tylist] != TY_IDX_ZERO)
05140 CONTEXT_set_given_lvalue_ty(context,
05141 TYLIST_item(Tylist_Table[param_tylist]));
05142 else
05143 CONTEXT_set_given_lvalue_ty(context, TY_IDX_ZERO);
05144
05145 Is_True(WN_operator(WN_kid(wn, arg_idx)) == OPR_PARM,
05146 ("Expected OPR_PARM as CALL argument"));
05147
05148 (void)WN2C_translate(arg_tokens, WN_kid(wn, arg_idx), context);
05149
05150 Append_And_Reclaim_Token_List(call_tokens, &arg_tokens);
05151 if (Tylist_Table[param_tylist] != TY_IDX_ZERO)
05152 param_tylist = TYLIST_next(param_tylist);
05153 if (arg_idx < last_arg_idx)
05154 Append_Token_Special(call_tokens, ',');
05155 }
05156 Append_Token_Special(call_tokens, ')');
05157
05158
05159 if (WN2C_Prev_CallSite == NULL)
05160 WN2C_Prev_CallSite = PUinfo_Get_CallSites();
05161 else
05162 WN2C_Prev_CallSite = CALLSITE_next(WN2C_Prev_CallSite);
05163
05164 Is_True(CALLSITE_call(WN2C_Prev_CallSite) == wn,
05165 ("CALLSITE out of sequence in WN2C_call()"));
05166
05167
05168
05169
05170 if (return_ty != (TY_IDX) 0 &&
05171 TY_kind(return_ty) != KIND_VOID &&
05172 WN_opcode(wn) != OPC_VCALL &&
05173 WN_opcode(wn) != OPC_VICALL &&
05174 WN_opcode(wn) != OPC_VPICCALL &&
05175 WN_opcode(wn) != OPC_VINTRINSIC_CALL)
05176 {
05177 WN2C_Function_Call_Lhs(call_tokens,
05178 return_to_param,
05179 return_ty,
05180 WN_kid0(wn),
05181 context);
05182 }
05183 Append_And_Reclaim_Token_List(tokens, &call_tokens);
05184
05185 return EMPTY_STATUS;
05186 }
05187
05188 #ifdef KEY
05189 static STATUS
05190 WN2C_asm_stmt(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05191 {
05192 TOKEN_BUFFER asm_tokens;
05193
05194
05195 asm_tokens = New_Token_Buffer();
05196
05197 Append_Token_String(asm_tokens, "__asm__ ");
05198 Append_Token_String(asm_tokens, "( \"");
05199 const char *asmstr = ST_name(WN_st_idx(wn));
05200 char *line = Get_Name_Buf_Slot(strlen(asmstr)+15);
05201 INT i = -1;
05202 INT j;
05203 do {
05204 j = -1;
05205
05206 do {
05207 i++; j++;
05208 line[j] = asmstr[i];
05209 } while (asmstr[i] != 0 && asmstr[i] != '\n');
05210 if (asmstr[i] == '\n') {
05211 line[j++] = '\\';
05212 line[j++] = 'n';
05213 line[j++] = '\"';
05214 line[j++] = '\n';
05215 if (asmstr[i+1] != 0) {
05216 line[j++] = '\t';
05217 line[j++] = '\"';
05218 line[j++] = 0;
05219 }
05220 else {
05221 i++;
05222 line[j++] = '\t';
05223 line[j++] = ')';
05224 line[j++] = 0;
05225 }
05226 }
05227 else if (asmstr[i] == 0) {
05228 line[j++] = '\"';
05229 line[j++] = ' ';
05230 line[j++] = ')';
05231 line[j++] = 0;
05232 }
05233 Append_Token_String(asm_tokens, line);
05234 } while (asmstr[i] != 0);
05235
05236 Append_And_Reclaim_Token_List(tokens, &asm_tokens);
05237
05238 return EMPTY_STATUS;
05239 }
05240 #endif
05241
05242
05243 static STATUS
05244 WN2C_eval(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05245 {
05246
05247 Is_True(WN_operator(wn) == OPR_EVAL,
05248 ("Invalid operator for WN2C_eval()"));
05249
05250 return WN2C_translate(tokens, WN_kid0(wn), context);
05251 }
05252
05253
05254 static STATUS
05255 WN2C_prefetch(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05256 {
05257
05258 INT pflag;
05259
05260 Is_True(WN_operator(wn) == OPR_PREFETCH || WN_operator(wn) == OPR_PREFETCHX,
05261 ("Invalid operator for WN2C_prefetch()"));
05262
05263
05264 if (WN_operator(wn) == OPR_PREFETCH)
05265 {
05266 Append_Token_String(tokens,
05267 Concat3_Strings("/* PREFETCH(", Ptr_as_String(wn), ")"));
05268 (void)WN2C_translate(tokens, WN_kid0(wn), context);
05269 Append_Token_String(tokens,
05270 Concat2_Strings("OFFS=", Number_as_String(WN_offset(wn), "%lld")));
05271 }
05272 else
05273 {
05274 Append_Token_String(tokens,
05275 Concat3_Strings("/* PREFETCHX(", Ptr_as_String(wn), ")"));
05276 (void)WN2C_translate(tokens, WN_kid0(wn), context);
05277 Append_Token_Special(tokens, '+');
05278 (void)WN2C_translate(tokens, WN_kid1(wn), context);
05279 }
05280
05281
05282 pflag = WN_prefetch_flag(wn);
05283 Set_Current_Indentation(Current_Indentation()+3);
05284 Append_Indented_Newline(tokens, 1);
05285 Append_Token_String(tokens, PF_GET_READ(pflag)? "read" : "write");
05286 Append_Token_String(tokens, PF_GET_KEEP_ANYWAY(pflag)? "keep-anyway" : "non-temproal");
05287 Append_Token_String(tokens, PF_GET_STRIDE_1L(pflag)? "Level-1" : "Level-2");
05288 Append_Token_String(tokens,
05289 Concat2_Strings("strid1=",
05290 Number_as_String(PF_GET_STRIDE_1L(pflag), "%lld")));
05291 Append_Token_String(tokens,
05292 Concat2_Strings("strid2=",
05293 Number_as_String(PF_GET_STRIDE_2L(pflag), "%lld")));
05294 Append_Token_String(tokens,
05295 Concat2_Strings("conf=",
05296 Number_as_String(PF_GET_CONFIDENCE(pflag), "%lld")));
05297 Set_Current_Indentation(Current_Indentation()-3);
05298
05299
05300 Append_Token_String(tokens, "*/");
05301
05302 return EMPTY_STATUS;
05303 }
05304
05305
05306 static STATUS
05307 WN2C_comment(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05308 {
05309 char * s;
05310 Is_True(WN_operator(wn) == OPR_COMMENT,
05311 ("Invalid operator for WN2C_comment()"));
05312
05313 s = Index_To_Str(WN_GetComment(wn));
05314 if (strncmp(s, "#pragma", 7) == 0) {
05315
05316
05317
05318 Append_Token_String(tokens, s);
05319 } else
05320 Append_Token_String(tokens,
05321 Concat3_Strings("/* ", Index_To_Str(WN_GetComment(wn)), " */"));
05322
05323 return EMPTY_STATUS;
05324 }
05325
05326
05327 static STATUS
05328 WN2C_iload(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05329 {
05330
05331
05332
05333
05334
05335
05336
05337 TY_IDX loaded_ty;
05338 TOKEN_BUFFER expr_tokens;
05339
05340 Is_True(WN_operator(wn) == OPR_ILOAD ||
05341 (WN_operator(wn) == OPR_LDID &&
05342 ST_sclass(WN_st(wn)) == SCLASS_FORMAL_REF),
05343 ("Invalid operator for WN2C_iload()"));
05344
05345
05346 if (W2C_Only_Mark_Loads && !TY_Is_Pointer(WN_ty(wn)))
05347 {
05348 char buf[64];
05349 sprintf(buf, "#<%p>#", wn);
05350 Append_Token_String(tokens, buf);
05351 return EMPTY_STATUS;
05352 }
05353
05354
05355 expr_tokens = New_Token_Buffer();
05356 if (WN_operator(wn) == OPR_LDID)
05357 {
05358 char load_address_area [sizeof (WN)];
05359 WN* load_address = (WN*) &load_address_area;
05360
05361 WN2C_create_ref_param_lda(load_address, wn);
05362 WN2C_memref_lhs(expr_tokens,
05363 &loaded_ty,
05364 load_address,
05365 WN_store_offset(wn),
05366 WN_ty(load_address),
05367 WN_ty(wn),
05368 WN_opc_dtype(wn),
05369 context);
05370 }
05371 else
05372 {
05373 STAB_OFFSET offt = WN_load_offset(wn);
05374 TY_IDX base_ty = TY_pointed(WN_load_addr_ty(wn));
05375 if (TY_is_union(base_ty) && WN_field_id(wn) > 0) {
05376 offt = WN2C_get_union_offset(base_ty, WN_field_id(wn));
05377 }
05378
05379
05380
05381 TY_IDX actual_ty = (WN_field_id(wn) > 0) ?
05382 Make_Pointer_Type(Get_Field_Type(base_ty, WN_field_id(wn)))
05383 : WN_load_addr_ty(wn);
05384
05385 WN2C_memref_lhs(expr_tokens,
05386 &loaded_ty,
05387 WN_kid0(wn),
05388 offt,
05389 actual_ty,
05390 WN_ty(wn),
05391 WN_opc_dtype(wn),
05392 context);
05393
05394 }
05395
05396 TY_IDX type_loaded = WN_Tree_Type(wn);
05397
05398
05399
05400
05401 if (!WN2C_arithmetic_compatible_types(loaded_ty, type_loaded))
05402 WN2C_prepend_cast(expr_tokens, type_loaded, FALSE);
05403
05404 Append_And_Reclaim_Token_List(tokens, &expr_tokens);
05405
05406
05407 if (W2C_Emit_Prefetch && WN_MAP_Get(WN_MAP_PREFETCH, wn))
05408 {
05409 Set_Current_Indentation(Current_Indentation()+3);
05410 WN2C_Prefetch_Map(tokens, wn, context);
05411 Set_Current_Indentation(Current_Indentation()-3);
05412 }
05413 return EMPTY_STATUS;
05414 }
05415
05416
05417 static STATUS
05418 WN2C_iloadx(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05419 {
05420 TY_IDX object_ty;
05421
05422
05423
05424
05425
05426 Is_True((WN_operator(wn) == OPR_ILOADX &&
05427 WN_operator(WN_kid0(wn)) == OPR_LDID &&
05428 WN_operator(WN_kid1(wn)) == OPR_LDID &&
05429 ST_sym_class(WN_st(WN_kid0(wn))) == CLASS_PREG &&
05430 ST_sym_class(WN_st(WN_kid1(wn))) == CLASS_PREG),
05431 ("Invalid WN tree for for WN2C_iloadx()"));
05432
05433
05434 object_ty =
05435 WN2C_MemAccess_Type(TY_pointed(WN_load_addr_ty(wn)),
05436 WN_load_addr_ty(wn),
05437 WN_opc_dtype(wn),
05438 WN_load_offset(wn));
05439
05440 WN2C_Load_From_PregIdx(tokens,
05441 WN_st(WN_kid0(wn)),
05442 WN_load_offset(WN_kid0(wn)),
05443 WN_st(WN_kid1(wn)),
05444 WN_load_offset(WN_kid1(wn)),
05445 object_ty,
05446 context);
05447
05448
05449
05450
05451 if (!WN2C_arithmetic_compatible_types(object_ty, WN_ty(wn)))
05452 WN2C_prepend_cast(tokens, WN_ty(wn), FALSE);
05453
05454 return EMPTY_STATUS;
05455 }
05456
05457
05458 static STATUS
05459 WN2C_mload(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05460 {
05461
05462
05463
05464 TY_IDX base_ty;
05465 TY_IDX loaded_ty;
05466 STATUS load_status;
05467 TOKEN_BUFFER expr_tokens;
05468
05469 Is_True(WN_operator(wn) == OPR_MLOAD,
05470 ("Invalid operator for WN2C_mload()"));
05471 Is_True(TY_Is_Pointer(WN_ty(wn)),
05472 ("Expected WN_ty to be a pointer in WN2C_mload()"));
05473 Is_True(WN_operator(WN_kid1(wn)) == OPR_INTCONST,
05474 ("Expected statically known size for WN2C_mload()"));
05475
05476
05477 if (W2C_Only_Mark_Loads)
05478 {
05479 char buf[64];
05480 sprintf(buf, "#<%p>#", wn);
05481 Append_Token_String(tokens, buf);
05482 return EMPTY_STATUS;
05483 }
05484
05485
05486 base_ty = WN_Tree_Type(WN_kid0(wn));
05487 if (!TY_Is_Pointer(base_ty))
05488 base_ty = WN_ty(wn);
05489 if (WN_field_id(wn) != 0) {
05490 loaded_ty = Get_Field_Type(TY_pointed(WN_ty(wn)), WN_field_id(wn));
05491 }
05492 else {
05493 loaded_ty = TY_pointed(WN_ty(wn));
05494 loaded_ty =
05495 WN2C_MemAccess_Type(TY_pointed(base_ty),
05496 loaded_ty,
05497 MTYPE_M,
05498 WN_load_offset(wn));
05499 }
05500
05501
05502 expr_tokens = New_Token_Buffer();
05503 load_status = WN2C_lvalue_wn(expr_tokens,
05504 WN_kid0(wn),
05505 base_ty,
05506 loaded_ty,
05507 WN_load_offset(wn),
05508 context);
05509
05510
05511 if (!STATUS_is_lvalue(load_status))
05512 Prepend_Token_Special(expr_tokens, '*');
05513
05514 Append_And_Reclaim_Token_List(tokens, &expr_tokens);
05515
05516 return EMPTY_STATUS;
05517 }
05518
05519
05520 static STATUS
05521 WN2C_array(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05522 {
05523
05524
05525
05526
05527 STATUS base_addr_status;
05528 STATUS return_status = EMPTY_STATUS;
05529 BOOL treat_ptr_as_array;
05530 BOOL set_ptr_as_array = FALSE;
05531 const BOOL context_provides_base_ty = CONTEXT_array_basetype(context);
05532 const BOOL context_needs_lvalue = CONTEXT_needs_lvalue(context);
05533 TOKEN_BUFFER tmp_tokens;
05534 INT32 dim;
05535 TY_IDX base_ty;
05536 TY_IDX ety;
05537
05538 Is_True(WN_operator(wn) == OPR_ARRAY,
05539 ("Invalid operator for WN2C_array()"));
05540
05541 vector<WN*> array_dims;
05542
05543 bool has_ptr_arith = false;
05544 WN* base_wn;
05545 for (base_wn = (WN*) wn; WN_operator(base_wn) == OPR_ARRAY || WN_operator(base_wn) == OPR_ADD;
05546 base_wn = WN_kid0(base_wn)) {
05547 if (WN_operator(base_wn) == OPR_ARRAY) {
05548 array_dims.push_back(base_wn);
05549 } else {
05550
05551 WN* kid1 = WN_kid1(base_wn);
05552 if (WN_operator(kid1) == OPR_MPY && WN_operator(WN_kid1(kid1)) == OPR_INTCONST) {
05553 WN* new_array = WN_Ternary(OPR_ARRAY, Pointer_Mtype, WN_kid0(base_wn), WN_kid1(kid1), WN_kid0(kid1));
05554 WN_element_size(new_array) = WN_const_val(WN_kid1(kid1));
05555 array_dims.push_back(new_array);
05556 } else {
05557 has_ptr_arith = true;
05558 }
05559 }
05560 }
05561
05562 if (!has_ptr_arith && WN_operator(base_wn) == OPR_LDA && WN_field_id(base_wn) != 0) {
05563
05564
05565
05566
05567
05568
05569
05570
05571
05572 FLD_list fld_stack;
05573 fld_stack.size = 0;
05574 UINT cur_fld = 0;
05575 TY2C_FLD_INFO field_info;
05576 int num_dim = array_dims.size();
05577 UINT cur_dim = 1;
05578 base_ty = ST_type(WN_st(base_wn));
05579 if (TY_kind(base_ty) == KIND_ARRAY)
05580 base_ty = Get_Inner_Array_Type(base_ty);
05581
05582 field_info.found_fld = get_to_field_with_name(base_ty, WN_field_id(base_wn), cur_fld, &fld_stack);
05583 if (!field_info.found_fld.Is_Null()) {
05584
05585 FmtAssert(fld_stack.size < WN2C_MAX_FLD_LEVEL, ("too many level of field accesses"));
05586 UINT cur_offset = WN_offset(base_wn);
05587 ST2C_use_translate(tokens, WN_st(base_wn), context);
05588 base_ty = ST_type(WN_st(base_wn));
05589
05590
05591 for (TY_IDX tmp_ty = base_ty; TY_Is_Array(tmp_ty); tmp_ty = TY_etype(tmp_ty)) {
05592 int elt_size = TY_size(TY_etype(tmp_ty));
05593 WN* index = array_dims[num_dim - cur_dim];
05594
05595 if (elt_size == WN_element_size(index)) {
05596 Append_Token_Special(tokens, '[');
05597 WN2C_translate(tokens, WN_array_index(index, 0), context);
05598 Append_Token_Special(tokens, ']');
05599 cur_dim++;
05600 } else {
05601
05602 int index = cur_offset / elt_size;
05603 Append_Token_Special(tokens, '[');
05604 char buf[32];
05605 sprintf(buf, "%1d", index);
05606 Append_Token_String(tokens, buf);
05607 Append_Token_Special(tokens, ']');
05608 cur_offset -= index * elt_size;
05609 }
05610 }
05611
05612
05613 for (int i = 0; i < fld_stack.size; i++) {
05614 cur_offset -= FLD_ofst(fld_stack.ar[i]);
05615 Append_Token_Special(tokens, '.');
05616 Append_Token_String(tokens, FLD_name(fld_stack.ar[i]));
05617 for (TY_IDX tmp_ty = FLD_type(fld_stack.ar[i]); TY_Is_Array(tmp_ty); tmp_ty = TY_etype(tmp_ty)) {
05618 WN* index = array_dims[num_dim - cur_dim];
05619 int elt_size = TY_size(TY_etype(tmp_ty));
05620 if (elt_size == WN_element_size(index)) {
05621 Append_Token_Special(tokens, '[');
05622 WN2C_translate(tokens, WN_array_index(index, 0), context);
05623 Append_Token_Special(tokens, ']');
05624 cur_dim++;
05625 } else {
05626
05627 int index = cur_offset / elt_size;
05628 Append_Token_Special(tokens, '[');
05629 char buf[32];
05630 sprintf(buf, "%1d", index);
05631 Append_Token_String(tokens, buf);
05632 Append_Token_Special(tokens, ']');
05633 cur_offset -= index * elt_size;
05634 }
05635 }
05636 }
05637
05638
05639 FmtAssert(cur_offset == 0, ("current offset should be 0 at the end\n"));
05640
05641 STATUS_set_lvalue(return_status);
05642 } else {
05643
05644 WN* offset = WN_Mpy(Integer_type, WN_array_index(wn, 0), WN_Intconst(Integer_type, WN_element_size(wn)));
05645 for (WN* tmp = WN_kid0(wn); WN_operator(tmp) == OPR_ARRAY; tmp = WN_kid0(tmp)) {
05646 offset = WN_Add(Integer_type, offset,
05647 WN_Mpy(Integer_type, WN_array_index(tmp, 0),
05648 WN_Intconst(Integer_type, WN_element_size(tmp))));
05649 }
05650
05651 offset = WN_Add(Integer_type, offset, WN_Intconst(Integer_type, WN_offset(base_wn)));
05652 ST2C_use_translate(tokens, WN_st(base_wn), context);
05653 if (TY_kind(ST_type(WN_st(base_wn))) == KIND_STRUCT) {
05654
05655 Prepend_Token_Special(tokens, '&');
05656 }
05657 WN2C_prepend_cast(tokens, Stab_Mtype_To_Ty(MTYPE_I1), TRUE);
05658
05659 TOKEN_BUFFER offset_buffer = New_Token_Buffer();
05660 WN2C_translate(offset_buffer, offset, context);
05661 WN2C_append_addr_plus_expr(tokens, 1, &offset_buffer);
05662 WN2C_prepend_cast(tokens, WN_Tree_Type(WN_kid0(wn)), FALSE);
05663 }
05664 return return_status;
05665 }
05666
05667
05668
05669
05670
05671 base_ty = WN_Tree_Type(WN_kid0(wn));
05672 if (TY_Is_Pointer(base_ty) &&
05673 (!TY_Is_Array(TY_pointed(base_ty)) ||
05674 (TY_size(TY_AR_etype(TY_pointed(base_ty))) < WN_element_size(wn) &&
05675 TY_size(TY_pointed(base_ty)) == WN_element_size(wn))))
05676 {
05677 if (!TY_ptr_as_array(Ty_Table[base_ty]))
05678 {
05679 Set_TY_ptr_as_array(Ty_Table[base_ty]);
05680 set_ptr_as_array = TRUE;
05681 }
05682 treat_ptr_as_array = TRUE;
05683 }
05684 else
05685 treat_ptr_as_array = FALSE;
05686
05687
05688
05689
05690
05691
05692
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702
05703
05704
05705 tmp_tokens = New_Token_Buffer();
05706 CONTEXT_set_needs_lvalue(context);
05707 CONTEXT_reset_array_basetype(context);
05708 base_addr_status = WN2C_translate(tmp_tokens, WN_kid0(wn), context);
05709
05710 if (treat_ptr_as_array)
05711 {
05712 if (set_ptr_as_array)
05713 Clear_TY_ptr_as_array(Ty_Table[base_ty]);
05714 ety = TY_pointed(base_ty);
05715 WHIRL2C_parenthesize(tmp_tokens);
05716 }
05717 else if (!TY_Is_Pointer(base_ty))
05718 {
05719
05720
05721
05722 treat_ptr_as_array = TRUE;
05723 if (context_provides_base_ty)
05724 base_ty = CONTEXT_given_base_ty(context);
05725 else
05726 base_ty = WN_Tree_Type(wn);
05727 ety = TY_pointed(base_ty);
05728 WN2C_prepend_cast(tmp_tokens, base_ty, FALSE);
05729 WHIRL2C_parenthesize(tmp_tokens);
05730 }
05731 else
05732 {
05733 treat_ptr_as_array = FALSE;
05734 ety = TY_AR_etype(TY_pointed(base_ty));
05735
05736
05737
05738
05739
05740 if (!STATUS_is_lvalue(base_addr_status) &&
05741 !STATUS_is_array_as_address(base_addr_status))
05742 {
05743 Prepend_Token_Special(tmp_tokens, '*');
05744 WHIRL2C_parenthesize(tmp_tokens);
05745 }
05746 }
05747
05748
05749
05750
05751 if (TY_Is_Array(ety))
05752 STATUS_set_array_as_address(return_status);
05753 else if (context_needs_lvalue)
05754 STATUS_set_lvalue(return_status);
05755 else
05756 Prepend_Token_Special(tmp_tokens, '&');
05757 Append_And_Reclaim_Token_List(tokens, &tmp_tokens);
05758 CONTEXT_reset_needs_lvalue(context);
05759
05760
05761 if (treat_ptr_as_array ||
05762 Stab_Array_Has_Dynamic_Bounds(TY_pointed(base_ty)))
05763 {
05764
05765
05766
05767 Append_Token_Special(tokens, '[');
05768 CONTEXT_reset_top_level_expr(context);
05769 WN2C_Normalize_Idx_To_Onedim(tokens, wn, context);
05770 Append_Token_Special(tokens, ']');
05771 }
05772 else
05773 {
05774 CONTEXT_set_top_level_expr(context);
05775 for (dim = 0; dim < WN_num_dim(wn); dim++)
05776 {
05777 Append_Token_Special(tokens, '[');
05778 (void)WN2C_translate(tokens, WN_array_index(wn, dim), context);
05779 Append_Token_Special(tokens, ']');
05780 }
05781 }
05782
05783 return return_status;
05784 }
05785
05786
05787 static STATUS
05788 WN2C_intrinsic_op(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05789 {
05790
05791
05792
05793
05794
05795 INT arg_idx;
05796 TY_IDX return_ty, result_ty;
05797 TOKEN_BUFFER call_tokens;
05798
05799 Is_True(WN_operator(wn) == OPR_INTRINSIC_OP,
05800 ("Invalid operator for WN2C_intrinsic_op()"));
05801
05802
05803 call_tokens = New_Token_Buffer();
05804 Append_Token_String(call_tokens,
05805 WN_intrinsic_name((INTRINSIC)WN_intrinsic(wn)));
05806
05807
05808
05809 Append_Token_Special(call_tokens, '(');
05810 CONTEXT_reset_needs_lvalue(context);
05811 CONTEXT_set_top_level_expr(context);
05812 for (arg_idx = 0; arg_idx <= WN_kid_count(wn) - 1; arg_idx++)
05813 {
05814 (void)WN2C_translate(call_tokens, WN_kid(wn, arg_idx), context);
05815 if (arg_idx < WN_kid_count(wn) - 1)
05816 Append_Token_Special(call_tokens, ',');
05817 }
05818 Append_Token_Special(call_tokens, ')');
05819
05820
05821 result_ty = Stab_Mtype_To_Ty(WN_opc_rtype(wn));
05822 return_ty = Stab_Mtype_To_Ty(TY_mtype(WN_intrinsic_return_ty(
05823 WN_opcode(wn),
05824 (INTRINSIC)WN_intrinsic(wn),
05825 wn)));
05826 if (!WN2C_arithmetic_compatible_types(return_ty, result_ty))
05827 WN2C_prepend_cast(call_tokens, result_ty, FALSE);
05828
05829 Append_And_Reclaim_Token_List(tokens, &call_tokens);
05830
05831 return EMPTY_STATUS;
05832 }
05833
05834
05835 static STATUS
05836 WN2C_tas(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05837 {
05838 STATUS status;
05839 TOKEN_BUFFER cast_tokens;
05840
05841 Is_True(WN_operator(wn) == OPR_TAS,
05842 ("Invalid operator for WN2C_tas()"));
05843
05844 TY_IDX from = WN_Tree_Type(WN_kid0(wn));
05845 TY_IDX to = WN_ty(wn);
05846
05847 if (WN2C_compatible_qualified_types(to, from) &&
05848 !TY_is_logical(to))
05849 {
05850 status = WN2C_translate(tokens, WN_kid0(wn), context);
05851 }
05852 else
05853 {
05854 cast_tokens = New_Token_Buffer();
05855 CONTEXT_reset_needs_lvalue(context);
05856 status = WN2C_translate(cast_tokens, WN_kid0(wn), context);
05857 WHIRL2C_parenthesize(cast_tokens);
05858 WN2C_prepend_cast(cast_tokens, WN_ty(wn), FALSE);
05859 Append_And_Reclaim_Token_List(tokens, &cast_tokens);
05860 }
05861
05862 return status;
05863 }
05864
05865
05866 static STATUS
05867 WN2C_select(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05868 {
05869
05870
05871
05872
05873
05874 Is_True(WN_operator(wn) == OPR_SELECT ||
05875 WN_operator(wn) == OPR_CSELECT,
05876 ("Invalid operator for WN2C_select()"));
05877
05878 Append_Token_Special(tokens, '(');
05879 (void)WN2C_translate(tokens, WN_kid0(wn), context);
05880 Append_Token_Special(tokens, '?');
05881 (void)WN2C_translate(tokens, WN_kid1(wn), context);
05882 Append_Token_Special(tokens, ':');
05883 (void)WN2C_translate(tokens, WN_kid((wn),2), context);
05884 Append_Token_Special(tokens, ')');
05885
05886 return EMPTY_STATUS;
05887 }
05888
05889
05890 static STATUS
05891 WN2C_cvt(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05892 {
05893 TOKEN_BUFFER expr_tokens;
05894
05895 Is_True(WN_operator(wn) == OPR_CVT,
05896 ("Invalid operator for WN2C_cvt()"));
05897
05898
05899
05900 expr_tokens = New_Token_Buffer();
05901 CONTEXT_reset_needs_lvalue(context);
05902 (void)WN2C_translate(expr_tokens, WN_kid0(wn), context);
05903 WHIRL2C_parenthesize(expr_tokens);
05904
05905
05906
05907
05908 if (TY_kind(WN_Tree_Type(WN_kid0(wn))) == KIND_POINTER &&
05909 WN_rtype(WN_kid0(wn)) != WN_opc_rtype(wn)) {
05910 Prepend_Token_String(expr_tokens, "(intptr_t)");
05911 WHIRL2C_parenthesize(expr_tokens);
05912 }
05913
05914 WN2C_prepend_cast(expr_tokens,
05915 Stab_Mtype_To_Ty(WN_opc_rtype(wn)),
05916 FALSE);
05917 Append_And_Reclaim_Token_List(tokens, &expr_tokens);
05918
05919 return EMPTY_STATUS;
05920 }
05921
05922
05923 static STATUS
05924 WN2C_cvtl(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05925 {
05926
05927
05928
05929
05930 TY_IDX object_ty, result_ty;
05931 TOKEN_BUFFER expr_tokens;
05932 STATUS status;
05933
05934 Is_True(WN_operator(wn) == OPR_CVTL,
05935 ("Invalid operator for WN2C_cvtl()"));
05936
05937
05938 result_ty = WN_Tree_Type(wn);
05939 object_ty = WN_Tree_Type(WN_kid0(wn));
05940
05941
05942
05943
05944 expr_tokens = New_Token_Buffer();
05945 if (WN2C_arithmetic_compatible_types(result_ty, object_ty))
05946 {
05947
05948 status = WN2C_translate(expr_tokens, WN_kid0(wn), context);
05949 }
05950 else
05951 {
05952
05953 CONTEXT_reset_needs_lvalue(context);
05954 status = WN2C_translate(expr_tokens, WN_kid0(wn), context);
05955 WHIRL2C_parenthesize(expr_tokens);
05956 WN2C_prepend_cast(expr_tokens, result_ty, FALSE);
05957 }
05958 Append_And_Reclaim_Token_List(tokens, &expr_tokens);
05959
05960 return status;
05961 }
05962
05963
05964 static STATUS
05965 WN2C_realpart(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05966 {
05967 Is_True(WN_operator(wn) == OPR_REALPART,
05968 ("Invalid operator for WN2C_realpart"));
05969
05970 CONTEXT_reset_needs_lvalue(context);
05971 WN2C_translate(tokens, WN_kid0(wn), context);
05972 Append_Token_Special(tokens, '.');
05973 Append_Token_String(tokens, TY2C_Complex_Realpart_Name);
05974
05975 return EMPTY_STATUS;
05976 }
05977
05978
05979 static STATUS
05980 WN2C_imagpart(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05981 {
05982 Is_True(WN_operator(wn) == OPR_IMAGPART,
05983 ("Invalid operator for WN2C_imagpart"));
05984
05985 CONTEXT_reset_needs_lvalue(context);
05986 WN2C_translate(tokens, WN_kid0(wn), context);
05987 Append_Token_Special(tokens, '.');
05988 Append_Token_String(tokens, TY2C_Complex_Imagpart_Name);
05989
05990 return EMPTY_STATUS;
05991 }
05992
05993
05994 static STATUS
05995 WN2C_paren(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
05996 {
05997 STATUS status;
05998
05999 Is_True(WN_operator(wn) == OPR_PAREN,
06000 ("Invalid operator for WN2C_paren()"));
06001
06002 Append_Token_Special(tokens, '(');
06003 CONTEXT_set_top_level_expr(context);
06004 status = WN2C_translate(tokens, WN_kid0(wn), context);
06005 Append_Token_Special(tokens, ')');
06006
06007 return status;
06008 }
06009
06010
06011 static STATUS
06012 WN2C_complex(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06013 {
06014 UINT tmp_idx;
06015 const char *tmpvar_name;
06016
06017 Is_True(WN_operator(wn) == OPR_COMPLEX,
06018 ("Invalid operator for WN2C_complex()"));
06019
06020 tmp_idx = Stab_Lock_Tmpvar(Stab_Mtype_To_Ty(WN_opc_rtype(wn)),
06021 ST2C_Declare_Tempvar);
06022 tmpvar_name = W2CF_Symtab_Nameof_Tempvar(tmp_idx);
06023
06024
06025 CONTEXT_reset_needs_lvalue(context);
06026
06027 Append_Token_Special(tokens, '(');
06028
06029
06030 Append_Token_Special(tokens, '(');
06031 Append_Token_String(tokens, tmpvar_name);
06032 Append_Token_Special(tokens, '.');
06033 Append_Token_String(tokens, TY2C_Complex_Realpart_Name);
06034 Append_Token_Special(tokens, '=');
06035 (void)WN2C_translate(tokens, WN_kid0(wn), context);
06036 Append_Token_Special(tokens, ')');
06037 Append_Token_Special(tokens, ',');
06038
06039
06040 Append_Token_Special(tokens, '(');
06041 Append_Token_String(tokens, tmpvar_name);
06042 Append_Token_Special(tokens, '.');
06043 Append_Token_String(tokens, TY2C_Complex_Imagpart_Name);
06044 Append_Token_Special(tokens, '=');
06045 (void)WN2C_translate(tokens, WN_kid1(wn), context);
06046 Append_Token_Special(tokens, ')');
06047 Append_Token_Special(tokens, ',');
06048
06049
06050 Append_Token_String(tokens, tmpvar_name);
06051 Append_Token_Special(tokens, ')');
06052
06053 Stab_Unlock_Tmpvar(tmp_idx);
06054
06055 return EMPTY_STATUS;
06056 }
06057
06058
06059 static STATUS
06060 WN2C_bnor(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06061 {
06062 const TY_IDX result_ty = Stab_Mtype_To_Ty(WN_opc_rtype(wn));
06063 TOKEN_BUFFER opnd;
06064
06065 Is_True(WN_operator(wn) == OPR_BNOR,
06066 ("Invalid operator for WN2C_bnor()"));
06067
06068
06069 CONTEXT_reset_needs_lvalue(context);
06070
06071 CONTEXT_reset_top_level_expr(context);
06072 Append_Token_Special(tokens, '~');
06073 Append_Token_Special(tokens, '(');
06074 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid0(wn), result_ty, context);
06075 Append_And_Reclaim_Token_List(tokens, &opnd);
06076 Append_Token_Special(tokens, '|');
06077 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid1(wn), result_ty, context);
06078 Append_And_Reclaim_Token_List(tokens, &opnd);
06079 Append_Token_Special(tokens, ')');
06080
06081 return EMPTY_STATUS;
06082 }
06083
06084
06085 static STATUS
06086 WN2C_madd(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06087 {
06088 const TY_IDX result_ty = Stab_Mtype_To_Ty(WN_opc_rtype(wn));
06089 TOKEN_BUFFER opnd;
06090
06091 Is_True(WN_operator(wn) == OPR_MADD,
06092 ("Invalid operator for WN2C_madd()"));
06093
06094
06095 CONTEXT_reset_needs_lvalue(context);
06096
06097 CONTEXT_reset_top_level_expr(context);
06098 Append_Token_Special(tokens, '(');
06099 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid1(wn), result_ty, context);
06100 Append_And_Reclaim_Token_List(tokens, &opnd);
06101 Append_Token_Special(tokens, '*');
06102 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid(wn,2), result_ty, context);
06103 Append_And_Reclaim_Token_List(tokens, &opnd);
06104 Append_Token_Special(tokens, '+');
06105 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid0(wn), result_ty, context);
06106 Append_And_Reclaim_Token_List(tokens, &opnd);
06107 Append_Token_Special(tokens, ')');
06108
06109 return EMPTY_STATUS;
06110 }
06111
06112
06113 static STATUS
06114 WN2C_msub(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06115 {
06116 const TY_IDX result_ty = Stab_Mtype_To_Ty(WN_opc_rtype(wn));
06117 TOKEN_BUFFER opnd;
06118
06119 Is_True(WN_operator(wn) == OPR_SUB,
06120 ("Invalid operator for WN2C_msub()"));
06121
06122
06123 CONTEXT_reset_needs_lvalue(context);
06124
06125 CONTEXT_reset_top_level_expr(context);
06126 Append_Token_Special(tokens, '(');
06127 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid1(wn), result_ty, context);
06128 Append_And_Reclaim_Token_List(tokens, &opnd);
06129 Append_Token_Special(tokens, '*');
06130 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid(wn,2), result_ty, context);
06131 Append_And_Reclaim_Token_List(tokens, &opnd);
06132 Append_Token_Special(tokens, '-');
06133 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid0(wn), result_ty, context);
06134 Append_And_Reclaim_Token_List(tokens, &opnd);
06135 Append_Token_Special(tokens, ')');
06136
06137 return EMPTY_STATUS;
06138 }
06139
06140
06141 static STATUS
06142 WN2C_nmadd(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06143 {
06144 const TY_IDX result_ty = Stab_Mtype_To_Ty(WN_opc_rtype(wn));
06145 TOKEN_BUFFER opnd;
06146
06147 Is_True(WN_operator(wn) == OPR_NMADD,
06148 ("Invalid operator for WN2C_nmadd()"));
06149
06150
06151 CONTEXT_reset_needs_lvalue(context);
06152
06153 CONTEXT_reset_top_level_expr(context);
06154 Append_Token_Special(tokens, '-');
06155 Append_Token_Special(tokens, '(');
06156 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid1(wn), result_ty, context);
06157 Append_And_Reclaim_Token_List(tokens, &opnd);
06158 Append_Token_Special(tokens, '*');
06159 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid(wn,2), result_ty, context);
06160 Append_And_Reclaim_Token_List(tokens, &opnd);
06161 Append_Token_Special(tokens, '+');
06162 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid0(wn), result_ty, context);
06163 Append_And_Reclaim_Token_List(tokens, &opnd);
06164 Append_Token_Special(tokens, ')');
06165
06166 return EMPTY_STATUS;
06167 }
06168
06169
06170 static STATUS
06171 WN2C_nmsub(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06172 {
06173 const TY_IDX result_ty = Stab_Mtype_To_Ty(WN_opc_rtype(wn));
06174 TOKEN_BUFFER opnd;
06175
06176 Is_True(WN_operator(wn) == OPR_NMSUB,
06177 ("Invalid operator for WN2C_nmsub()"));
06178
06179
06180 CONTEXT_reset_needs_lvalue(context);
06181
06182 CONTEXT_reset_top_level_expr(context);
06183 Append_Token_Special(tokens, '-');
06184 Append_Token_Special(tokens, '(');
06185 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid1(wn), result_ty, context);
06186 Append_And_Reclaim_Token_List(tokens, &opnd);
06187 Append_Token_Special(tokens, '*');
06188 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid(wn,2), result_ty, context);
06189 Append_And_Reclaim_Token_List(tokens, &opnd);
06190 Append_Token_Special(tokens, '-');
06191 opnd = WN2C_Translate_Arithmetic_Operand(WN_kid0(wn), result_ty, context);
06192 Append_And_Reclaim_Token_List(tokens, &opnd);
06193 Append_Token_Special(tokens, ')');
06194
06195 return EMPTY_STATUS;
06196 }
06197
06198
06199 static STATUS
06200 WN2C_ldid(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06201 {
06202
06203
06204
06205 TY_IDX object_ty;
06206 TY_IDX base_addr_ty;
06207 TY_IDX lda_st_ty;
06208 STATUS load_status;
06209 TOKEN_BUFFER expr_tokens;
06210 STAB_OFFSET addr_offset;
06211
06212 Is_True(WN_operator(wn) == OPR_LDID ||
06213 (WN_operator(wn) == OPR_LDA &&
06214 ST_sclass(WN_st(wn)) == SCLASS_FORMAL_REF),
06215 ("Invalid operator for WN2C_ldid()"));
06216
06217
06218 if (W2C_Only_Mark_Loads && !TY_Is_Pointer(WN_ty(wn)))
06219 {
06220 char buf[64];
06221 sprintf(buf, "#<%p>#", wn);
06222 Append_Token_String(tokens, buf);
06223 return EMPTY_STATUS;
06224 }
06225
06226 if (WN_operator(wn) == OPR_LDID &&
06227 ST_sclass(WN_st(wn)) == SCLASS_FORMAL_REF)
06228 return WN2C_iload(tokens, wn, context);
06229 else if (WN_operator(wn) == OPR_LDA)
06230 {
06231 lda_st_ty = ST_type(WN_st(wn));
06232 Set_ST_type(WN_st(wn), Stab_Pointer_To(ST_type(WN_st(wn))));
06233 }
06234
06235
06236 addr_offset = WN_load_offset(wn);
06237 #ifdef KEY // special case for asm outputs
06238 if (addr_offset < -1) {
06239 char buff[64];
06240 sprintf(buff, "reg%%%lld", -addr_offset-2);
06241 expr_tokens = New_Token_Buffer();
06242 Append_Token_String(expr_tokens, buff);
06243 Append_And_Reclaim_Token_List(tokens, &expr_tokens);
06244 return EMPTY_STATUS;
06245 }
06246 #endif
06247 expr_tokens = New_Token_Buffer();
06248 TY_IDX prefered_ty = WN_Tree_Type(wn);
06249 if (ST_sym_class(WN_st(wn)) == CLASS_PREG)
06250 {
06251
06252
06253
06254 char buffer[64];
06255 object_ty = PUinfo_Preg_Type(ST_type(WN_st(wn)), addr_offset);
06256 if (addr_offset == -1) {
06257 switch (TY_mtype(Ty_Table[WN_ty(wn)])) {
06258 case MTYPE_I8:
06259 case MTYPE_U8:
06260 case MTYPE_I1:
06261 case MTYPE_I2:
06262 case MTYPE_I4:
06263 case MTYPE_U1:
06264 case MTYPE_U2:
06265 case MTYPE_U4:
06266 sprintf(buffer, "reg%d", First_Int_Preg_Return_Offset);
06267 Append_Token_String(expr_tokens, buffer);
06268 break;
06269 case MTYPE_F4:
06270 case MTYPE_F8:
06271 case MTYPE_F10:
06272 case MTYPE_FQ:
06273 case MTYPE_C4:
06274 case MTYPE_C8:
06275 case MTYPE_C10:
06276 case MTYPE_CQ:
06277 sprintf(buffer, "reg%d", First_Float_Preg_Return_Offset);
06278 Append_Token_String(expr_tokens, buffer);
06279 break;
06280 case MTYPE_M:
06281
06282 sprintf(buffer, "%s", last_ret_tmp);
06283 Append_Token_String(expr_tokens, buffer);
06284 object_ty = prefered_ty;
06285 break;
06286 default:
06287 Fail_FmtAssertion ("Unexpected type in WN2C_ldid()");
06288 break;
06289 }
06290 }
06291 else
06292 {
06293 WN2C_Append_Preg(expr_tokens,
06294 WN_st(wn),
06295 addr_offset,
06296 object_ty,
06297 context);
06298 }
06299 }
06300 else
06301 {
06302 if (TY_is_union(WN_ty(wn)) && WN_field_id(wn) > 0) {
06303 addr_offset = WN2C_get_union_offset(WN_ty(wn), WN_field_id(wn));
06304 }
06305
06306
06307 WN2C_SymAccess_Type(&base_addr_ty,
06308 &object_ty,
06309 ST_type(WN_st(wn)),
06310 prefered_ty,
06311 WN_opc_dtype(wn),
06312 addr_offset);
06313
06314
06315 load_status = WN2C_lvalue_st(expr_tokens,
06316 WN_st(wn),
06317 base_addr_ty,
06318 object_ty,
06319 addr_offset,
06320 context);
06321
06322
06323 if (!STATUS_is_lvalue(load_status))
06324 Prepend_Token_Special(expr_tokens, '*');
06325 }
06326
06327
06328
06329
06330 if (!WN2C_arithmetic_compatible_types(object_ty, prefered_ty))
06331 {
06332
06333 if (!TY_Is_Structured(object_ty) && !TY_Is_Structured(WN_ty(wn)))
06334 WN2C_prepend_cast(expr_tokens, WN_ty(wn), FALSE);
06335 else
06336 {
06337
06338
06339
06340 const UINT tmp_idx = Stab_Lock_Tmpvar(object_ty,
06341 ST2C_Declare_Tempvar);
06342 const char *tmpvar_name = W2CF_Symtab_Nameof_Tempvar(tmp_idx);
06343
06344
06345 Append_Token_Special(tokens, '(');
06346 Append_Token_String(tokens, tmpvar_name);
06347 Append_Token_Special(tokens, '=');
06348 Append_And_Reclaim_Token_List(tokens, &expr_tokens);
06349 Append_Token_Special(tokens, ',');
06350
06351
06352 expr_tokens = New_Token_Buffer();
06353 Append_Token_Special(expr_tokens, '&');
06354 Append_Token_String(expr_tokens, tmpvar_name);
06355 WN2C_prepend_cast(expr_tokens, WN_ty(wn), TRUE);
06356 Prepend_Token_Special(expr_tokens, '*');
06357 Append_Token_Special(expr_tokens, ')');
06358 Stab_Unlock_Tmpvar(tmp_idx);
06359 }
06360 } else {
06361
06362
06363
06364 TY_IDX exp_ty = ST_type(WN_st(wn));
06365 if (WN2C_is_void_ptr(exp_ty) && !WN2C_is_void_ptr(object_ty)) {
06366 WN2C_prepend_cast(expr_tokens, object_ty, FALSE);
06367 }
06368 }
06369 Append_And_Reclaim_Token_List(tokens, &expr_tokens);
06370
06371 if (WN_operator(wn) == OPR_LDA)
06372 Set_ST_type(WN_st(wn), lda_st_ty);
06373
06374 return EMPTY_STATUS;
06375 }
06376
06377
06378 static STATUS
06379 WN2C_lda(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06380 {
06381 TY_IDX object_ty;
06382 STATUS lda_status;
06383 TOKEN_BUFFER expr_tokens;
06384 STAB_OFFSET lda_offset;
06385
06386 Is_True(WN_operator(wn) == OPR_LDA,
06387 ("Invalid operator for WN2C_lda()"));
06388 Is_True(ST_sym_class(WN_st(wn)) != CLASS_PREG,
06389 ("Cannot take the address of a preg"));
06390
06391 if (ST_sclass(WN_st(wn)) == SCLASS_FORMAL_REF)
06392 return WN2C_ldid(tokens, wn, context);
06393
06394 expr_tokens = New_Token_Buffer();
06395 if (ST_sym_class(WN_st(wn)) == CLASS_CONST &&
06396 TCON_ty(STC_val(WN_st(wn))) != MTYPE_STRING)
06397 {
06398
06399
06400
06401 UINT tmp_idx =
06402 Stab_Lock_Tmpvar(ST_type(WN_st(wn)), &ST2C_Declare_Tempvar);
06403 const char *tmp_name = W2CF_Symtab_Nameof_Tempvar(tmp_idx);
06404
06405 Append_Token_Special(tokens, '(');
06406 if (TY_Is_Complex(ST_type(WN_st(wn))))
06407 WN2C_Assign_Complex_Const(expr_tokens,
06408 tmp_name,
06409 Extract_Complex_Real(STC_val(WN_st(wn))),
06410 Extract_Complex_Imag(STC_val(WN_st(wn))));
06411 else
06412 {
06413 Append_Token_String(expr_tokens, tmp_name);
06414 Append_Token_Special(expr_tokens, '=');
06415 TCON2C_translate(expr_tokens, STC_val(WN_st(wn)));
06416 }
06417 Append_Token_Special(expr_tokens, ',');
06418 Append_Token_Special(expr_tokens, '&');
06419 Append_Token_String(expr_tokens, tmp_name);
06420 Append_Token_Special(expr_tokens, ')');
06421
06422 if (!TY_Is_Pointer(WN_ty(wn)) ||
06423 !WN2C_arithmetic_compatible_types(ST_type(WN_st(wn)),
06424 TY_pointed(WN_ty(wn))))
06425 {
06426 WN2C_prepend_cast(expr_tokens, WN_ty(wn), FALSE);
06427 }
06428 lda_status = EMPTY_STATUS;
06429 }
06430 else if ((ST_sym_class(WN_st(wn)) == CLASS_FUNC ?
06431 ST_pu_type(WN_st(wn)) : ST_type(WN_st(wn))) == 0)
06432 {
06433
06434 const char *tmp_name = ST_name(WN_st(wn));
06435 if (tmp_name == NULL)
06436 {
06437 UINT tmp_idx =
06438 Stab_Lock_Tmpvar(MTYPE_To_TY(MTYPE_I4), &ST2C_Declare_Tempvar);
06439 tmp_name = W2CF_Symtab_Nameof_Tempvar(tmp_idx);
06440 }
06441 Append_Token_String(expr_tokens, tmp_name);
06442 lda_status = EMPTY_STATUS;
06443 }
06444 else
06445 {
06446 TY_IDX prefered_ty = TY_pointed(WN_ty(wn));
06447 lda_offset = WN_lda_offset(wn);
06448 if (ST_sym_class(WN_st(wn)) == CLASS_CONST &&
06449 TCON_ty(STC_val(WN_st(wn))) == MTYPE_STRING)
06450 {
06451
06452
06453
06454 object_ty = Stab_Mtype_To_Ty(MTYPE_U1);
06455 }
06456 else if (TY_Is_Pointer(WN_ty(wn)))
06457 {
06458 TY_IDX wn_st_type = ST_sym_class(WN_st(wn)) == CLASS_FUNC ?
06459 ST_pu_type(WN_st(wn)) : ST_type(WN_st(wn));
06460 if (TY_kind(wn_st_type) == KIND_ARRAY &&
06461 TY_size(wn_st_type) == 0) {
06462
06463
06464
06465
06466 prefered_ty = TY_etype(wn_st_type);
06467 }
06468
06469 if (WN_field_id(wn) > 0) {
06470 if (TY_Is_Structured(prefered_ty)) {
06471
06472
06473
06474
06475 prefered_ty = TY_pointed(WN_Tree_Type(wn));
06476 }
06477
06478
06479 object_ty = prefered_ty;
06480 } else {
06481 object_ty = WN2C_MemAccess_Type(
06482 wn_st_type,
06483 prefered_ty,
06484 TY_mtype(wn_st_type),
06485 lda_offset);
06486 }
06487 }
06488 else
06489 {
06490 object_ty = ST_sym_class(WN_st(wn)) == CLASS_FUNC ?
06491 ST_pu_type(WN_st(wn)) : ST_type(WN_st(wn));
06492 }
06493
06494
06495 expr_tokens = New_Token_Buffer();
06496 lda_status =
06497 WN2C_lvalue_st(expr_tokens,
06498 WN_st(wn),
06499 Stab_Pointer_To(ST_sym_class(WN_st(wn)) == CLASS_FUNC ?
06500 ST_pu_type(WN_st(wn)) : ST_type(WN_st(wn))),
06501 object_ty,
06502 lda_offset,
06503 context,
06504 WN_field_id(wn));
06505
06506
06507 if (!TY_Is_Pointer(WN_ty(wn)) ||
06508 !WN2C_arithmetic_compatible_types(object_ty, prefered_ty))
06509 {
06510 if (STATUS_is_lvalue(lda_status))
06511 Prepend_Token_Special(expr_tokens, '&');
06512
06513 if (!(ST_sym_class(WN_st(wn)) == CLASS_CONST &&
06514 TCON_ty(STC_val(WN_st(wn))) == MTYPE_STRING)) {
06515 WN2C_prepend_cast(expr_tokens, WN_ty(wn), FALSE);
06516 }
06517 STATUS_reset_lvalue(lda_status);
06518 }
06519 else if (STATUS_is_lvalue(lda_status) && !CONTEXT_needs_lvalue(context))
06520 {
06521 if (TY_kind(object_ty) == KIND_ARRAY) {
06522
06523 }
06524 else
06525 Prepend_Token_Special(expr_tokens, '&');
06526 STATUS_reset_lvalue(lda_status);
06527 }
06528 }
06529 Append_And_Reclaim_Token_List(tokens, &expr_tokens);
06530
06531 return lda_status;
06532 }
06533
06534
06535 static STATUS
06536 WN2C_const(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06537 {
06538
06539
06540
06541 Is_True(WN_operator(wn) == OPR_CONST &&
06542 ST_sym_class(WN_st(wn)) == CLASS_CONST,
06543 ("Invalid operator for WN2C_const"));
06544
06545 CONTEXT_reset_needs_lvalue(context);
06546 if (!TY_Is_Complex(WN_Tree_Type(wn)))
06547 TCON2C_translate(tokens, STC_val(WN_st(wn)));
06548 else
06549 {
06550 UINT tmp_idx =
06551 Stab_Lock_Tmpvar(WN_Tree_Type(wn), &ST2C_Declare_Tempvar);
06552 const char *tmp_name = W2CF_Symtab_Nameof_Tempvar(tmp_idx);
06553
06554
06555
06556
06557 Append_Token_Special(tokens, '(');
06558 WN2C_Assign_Complex_Const(tokens,
06559 tmp_name,
06560 Extract_Complex_Real(STC_val(WN_st(wn))),
06561 Extract_Complex_Imag(STC_val(WN_st(wn))));
06562 Append_Token_Special(tokens, ',');
06563 Append_Token_String(tokens, tmp_name);
06564 Append_Token_Special(tokens, ')');
06565 }
06566
06567 return EMPTY_STATUS;
06568 }
06569
06570
06571 static STATUS
06572 WN2C_intconst(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06573 {
06574 Is_True(WN_operator(wn) == OPR_INTCONST,
06575 ("Invalid operator for WN2C_intconst()"));
06576
06577 CONTEXT_reset_needs_lvalue(context);
06578 TCON2C_translate(tokens, Host_To_Targ(WN_opc_rtype(wn), WN_const_val(wn)));
06579
06580 return EMPTY_STATUS;
06581 }
06582
06583
06584 static STATUS
06585 WN2C_comma(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06586 {
06587 Is_True(WN_operator(wn) == OPR_COMMA,
06588 ("Invalid operator for WN2C_comma()"));
06589
06590 CONTEXT_reset_top_level_expr(context);
06591 Append_Token_Special(tokens, '(');
06592 Append_Token_Special(tokens, '(');
06593 WN2C_Translate_Comma_Sequence(tokens, WN_first(WN_kid0(wn)), context);
06594 Append_Token_Special(tokens, ')');
06595 Append_Token_Special(tokens, ',');
06596 WN2C_translate(tokens, WN_kid1(wn), context);
06597 Append_Token_Special(tokens, ')');
06598 return EMPTY_STATUS;
06599 }
06600
06601
06602 static STATUS
06603 WN2C_rcomma(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06604 {
06605
06606
06607
06608 UINT tmp_idx;
06609 const char *tmp_name;
06610
06611 Is_True(WN_operator(wn) == OPR_RCOMMA,
06612 ("Invalid operator for WN2C_romma()"));
06613
06614 CONTEXT_reset_top_level_expr(context);
06615 Append_Token_Special(tokens, '(');
06616
06617 tmp_idx = Stab_Lock_Tmpvar(WN_Tree_Type(WN_kid0(wn)),
06618 &ST2C_Declare_Tempvar);
06619 tmp_name = W2CF_Symtab_Nameof_Tempvar(tmp_idx);
06620 Append_Token_String(tokens, tmp_name);
06621 Append_Token_Special(tokens, '=');
06622 WN2C_translate(tokens, WN_kid0(wn), context);
06623 Append_Token_Special(tokens, ',');
06624 Append_Token_Special(tokens, '(');
06625 WN2C_Translate_Comma_Sequence(tokens, WN_first(WN_kid1(wn)), context);
06626 Append_Token_Special(tokens, ')');
06627 Append_Token_Special(tokens, ',');
06628 Append_Token_String(tokens, tmp_name);
06629 Append_Token_Special(tokens, ')');
06630 return EMPTY_STATUS;
06631 }
06632
06633
06634
06635
06636
06637
06638 static BOOL WN2C_int_downcast(TY_IDX from, TY_IDX to) {
06639
06640 if (TY_kind(from) == KIND_SCALAR &&
06641 TY_kind(to) == KIND_SCALAR) {
06642 if (TY_size(from) > TY_size(to)) {
06643
06644 return true;
06645 } else if (MTYPE_is_signed(TY_mtype(from)) ^ MTYPE_is_signed(TY_mtype(to))) {
06646
06647
06648
06649 return true;
06650 } else if ( TY_is_logical(to) ) {
06651
06652
06653
06654 return strcmp(TY_name(from), TY_name(to)) != 0;
06655 }
06656 }
06657 return false;
06658 }
06659
06660 static STATUS
06661 WN2C_parm(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06662 {
06663
06664
06665
06666
06667 TOKEN_BUFFER parm_tokens;
06668 STATUS status;
06669 TY_IDX parm_ty = CONTEXT_given_lvalue_ty(context);
06670
06671 CONTEXT_reset_given_lvalue_ty(context);
06672
06673 Is_True(WN_operator(wn) == OPR_PARM,
06674 ("Invalid operator for WN2C_parm()"));
06675
06676 TY_IDX arg_ty = WN_Tree_Type(WN_kid0(wn));
06677 bool volatile_arg = false;
06678 if (parm_ty == TY_IDX_ZERO)
06679 {
06680
06681 if (TY_Is_Pointer(arg_ty) && TY_is_volatile(TY_pointed(arg_ty))) {
06682
06683
06684
06685 volatile_arg = true;
06686 }
06687 parm_ty = WN_ty(wn);
06688 }
06689
06690 if (!volatile_arg &&
06691 WN2C_assignment_compatible_types(parm_ty, WN_Tree_Type(WN_kid0(wn))) &&
06692 !WN2C_int_downcast(arg_ty, parm_ty))
06693 status = WN2C_translate(tokens, WN_kid0(wn), context);
06694 else
06695 {
06696 parm_tokens = New_Token_Buffer();
06697 CONTEXT_reset_top_level_expr(context);
06698 WN2C_translate(parm_tokens, WN_kid0(wn), context);
06699 WN2C_prepend_cast(parm_tokens, parm_ty, FALSE);
06700 Append_And_Reclaim_Token_List(tokens, &parm_tokens);
06701 status = EMPTY_STATUS;
06702 }
06703 return status;
06704 }
06705
06706
06707 static STATUS
06708 WN2C_alloca(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06709 {
06710 STATUS status ;
06711
06712 Append_Token_String(tokens,"alloca");
06713 Append_Token_Special(tokens,'(');
06714 status = WN2C_translate(tokens,WN_kid0(wn),context);
06715 Append_Token_Special(tokens,')');
06716
06717 return status;
06718 }
06719
06720 static STATUS
06721 WN2C_dealloca(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06722 {
06723
06724 INT16 n,i;
06725 STATUS status ;
06726
06727 n = WN_kid_count(wn);
06728
06729 WN2C_Stmt_Newline(tokens,WN_linenum(wn));
06730 Append_Token_String(tokens,"dealloca");
06731 Append_Token_Special(tokens,'(');
06732
06733 i = 0 ;
06734 while (i < n)
06735 {
06736 status = WN2C_translate(tokens,WN_kid(wn,i),context);
06737 if (++i < n)
06738 Append_Token_Special(tokens,',');
06739 }
06740 Append_Token_Special(tokens,')');
06741 return status ;
06742 }
06743
06744 static STATUS
06745 WN2C_extract_bits(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06746 {
06747
06748 TOKEN_BUFFER opnd_tokens;
06749 WN *wn0 = WN_kid0(wn);
06750 TY_IDX wn0_ty = WN_Tree_Type(wn0);
06751 Append_Token_Special(tokens,'(');
06752 Append_Token_Special(tokens,'(');
06753 opnd_tokens = WN2C_Translate_Arithmetic_Operand(wn0, wn0_ty, context);
06754 Append_And_Reclaim_Token_List(tokens, &opnd_tokens);
06755 Append_Token_String(tokens, ">>");
06756 Append_Token_String(tokens,
06757 Number_as_String((UINT64) WN_bit_offset(wn), "%llu"));
06758 Append_Token_Special(tokens,')');
06759 Append_Token_Special(tokens,'&');
06760 Append_Token_String(tokens,
06761 Number_as_String((UINT64) ((1 << WN_bit_size(wn)) - 1), "%#llx"));
06762 Append_Token_Special(tokens,')');
06763 return EMPTY_STATUS;
06764 }
06765
06766
06767
06768
06769
06770 void
06771 WN2C_initialize(void)
06772 {
06773 INT opr;
06774 INT map;
06775
06776
06777 for (opr = 0; opr < NUMBER_OF_OPERATORS; opr++)
06778 WN2C_Opr_Handler[opr] = &WN2C_unsupported;
06779
06780
06781 for (map = 0; map < NUMBER_OF_OPR2HANDLER_MAPS; map++)
06782 WN2C_Opr_Handler[WN2C_Opr_Handler_Map[map].opr] =
06783 WN2C_Opr_Handler_Map[map].handler;
06784
06785
06786
06787
06788
06789
06790
06791
06792
06793
06794 for (map = 0; map < NUMBER_OF_OPC2CNAME_MAPS; map++)
06795 WN2C_Opc2cname[WN2C_Opc2cname_Map[map].opc] =
06796 WN2C_Opc2cname_Map[map].cname;
06797
06798 }
06799
06800
06801 void
06802 WN2C_finalize(void)
06803 {
06804
06805
06806
06807
06808
06809 Stab_Free_Tmpvars();
06810 }
06811
06812
06813 BOOL
06814 WN2C_new_symtab(void)
06815 {
06816
06817
06818
06819
06820
06821 static SYMTAB_IDX WN2C_Current_Symtab = 0;
06822 const BOOL new_symtab = (CURRENT_SYMTAB != WN2C_Current_Symtab);
06823
06824 if (new_symtab)
06825 WN2C_Current_Symtab = CURRENT_SYMTAB;
06826 return new_symtab;
06827 }
06828
06829
06830 STATUS
06831 WN2C_translate(TOKEN_BUFFER tokens, const WN *wn, CONTEXT context)
06832 {
06833
06834
06835
06836
06837
06838 #define OPR_LOC OPERATOR_LAST+12 //this comes from ir_reader.cxx
06839 if(WN_operator(wn) == OPR_LOC)
06840 last_loc = &wn;
06841
06842 return WN2C_Opr_Handler[WN_operator(wn)](tokens, wn, context);
06843 }
06844
06845
06846 void
06847 WN2C_translate_structured_types(void)
06848 {
06849 Write_String(W2C_File[W2C_DOTH_FILE], NULL,
06850 "/* Types */\n");
06851 WN2C_Append_Symtab_Types(NULL,
06852 2);
06853 }
06854
06855
06856 STATUS
06857 WN2C_translate_file_scope_defs(CONTEXT context)
06858 {
06859
06860
06861
06862 CURRENT_SYMTAB = GLOBAL_SYMTAB;
06863 WN2C_new_symtab();
06864
06865
06866 #if 0
06867 Write_String(W2C_File[W2C_DOTH_FILE], NULL,
06868 "/* File-level symbolic constants */\n");
06869 WN2C_Append_Symtab_Consts(NULL,
06870 TRUE,
06871 2,
06872 context);
06873 #endif
06874
06875 Write_String(W2C_File[W2C_DOTH_FILE], NULL,
06876 "/* File-level vars and routines */\n");
06877 WN2C_Append_Symtab_Vars(NULL,
06878 2,
06879 context);
06880
06881 return EMPTY_STATUS;
06882 }
06883
06884
06885 STATUS
06886 WN2C_translate_purple_main(TOKEN_BUFFER tokens,
06887 const WN *pu,
06888 const char *region_name,
06889 CONTEXT context)
06890 {
06891 static const char prp_return_var_name[] = "prp___return";
06892
06893 TY_IDX return_ty;
06894 const ST *param_st;
06895 INT first_param, param;
06896
06897 Is_True(WN_operator(pu) == OPR_FUNC_ENTRY,
06898 ("Invalid opcode for WN2C_translate_purple_main()"));
06899
06900
06901
06902 CONTEXT_set_srcpos(context, WN_Get_Linenum(pu));
06903 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
06904 Append_Token_String(tokens, "int main()");
06905
06906 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
06907 Append_Token_Special(tokens, '{');
06908
06909
06910
06911 Increment_Indentation();
06912 first_param = (PUINFO_RETURN_TO_PARAM? 1 : 0);
06913 for (param = first_param; param < WN_num_formals(pu); param++)
06914 {
06915 param_st = WN_st(WN_formal(pu, param));
06916 Append_Indented_Newline(tokens, 1);
06917 ST2C_decl_translate(tokens, param_st, context);
06918 Append_Token_Special(tokens, ';');
06919 }
06920
06921
06922
06923
06924
06925 return_ty = PUINFO_RETURN_TY;
06926 if (return_ty != (TY_IDX) 0 && TY_kind(return_ty) != KIND_VOID)
06927 {
06928 TOKEN_BUFFER return_tokens = New_Token_Buffer();
06929
06930 Append_Token_String(return_tokens, prp_return_var_name);
06931 TY2C_translate_unqualified(return_tokens, return_ty);
06932 Append_Indented_Newline(tokens, 1);
06933 Append_And_Reclaim_Token_List(tokens, &return_tokens);
06934 }
06935
06936
06937
06938 Append_Indented_Newline(tokens, 1);
06939 Append_Token_String(tokens, "<#PRP_XSYM:INIT_PARAM ");
06940 WN2C_Append_Purple_Funcinfo(tokens);
06941 Append_Token_String(tokens, "#>");
06942
06943
06944
06945 Append_Indented_Newline(tokens, 1);
06946 Append_Token_String(tokens,
06947 "/***** Call to extracted purple region ****");
06948 Append_Indented_Newline(tokens, 1);
06949 Append_Token_String(tokens, "*/");
06950 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
06951 if (return_ty != (TY_IDX) 0 && TY_kind(return_ty) != KIND_VOID)
06952 {
06953 Append_Token_String(tokens, prp_return_var_name);
06954 Append_Token_Special(tokens, '=');
06955 }
06956 Append_Token_String(tokens, region_name);
06957 Append_Token_Special(tokens, '(');
06958 for (param = 0; param < WN_num_formals(pu); param++)
06959 {
06960 if (param > 0)
06961 Append_Token_Special(tokens, ',');
06962 param_st = WN_st(WN_formal(pu, param));
06963 Append_Token_String(tokens, W2CF_Symtab_Nameof_St(param_st));
06964 }
06965 Append_Token_Special(tokens, ')');
06966 Append_Token_Special(tokens, ';');
06967
06968
06969
06970 Append_Indented_Newline(tokens, 1);
06971 Append_Token_String(tokens, "<#PRP_XSYM:TEST_PARAM ");
06972 WN2C_Append_Purple_Funcinfo(tokens);
06973 Append_Token_String(tokens, "#>");
06974
06975 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
06976 Append_Token_String(tokens, "return 0;");
06977
06978 Decrement_Indentation();
06979 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
06980 Append_Token_Special(tokens, '}');
06981 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
06982 WN2C_Stmt_Newline(tokens, CONTEXT_srcpos(context));
06983
06984 return EMPTY_STATUS;
06985 }
06986
06987
06988 void
06989 WN2C_memref_lhs(TOKEN_BUFFER tokens,
06990 TY_IDX *memref_typ,
06991 const WN *lhs,
06992 STAB_OFFSET memref_ofst,
06993 TY_IDX memref_addr_ty,
06994 TY_IDX memref_object_ty,
06995 MTYPE dtype,
06996 CONTEXT context)
06997 {
06998
06999
07000
07001 TY_IDX base_ty;
07002 STATUS lhs_status;
07003
07004
07005
07006
07007 base_ty = WN_Tree_Type(lhs);
07008 if (!TY_Is_Pointer(base_ty))
07009 base_ty = memref_addr_ty;
07010 *memref_typ = TY_pointed(memref_addr_ty);
07011 *memref_typ = WN2C_MemAccess_Type(TY_pointed(base_ty),
07012 *memref_typ,
07013 dtype,
07014 memref_ofst);
07015
07016
07017 if (TY_mtype(*memref_typ) == TY_mtype(memref_object_ty))
07018 *memref_typ = memref_object_ty;
07019
07020
07021
07022
07023 lhs_status = WN2C_lvalue_wn(tokens,
07024 lhs,
07025 base_ty,
07026 *memref_typ,
07027 memref_ofst,
07028 context);
07029
07030
07031
07032
07033 if (!STATUS_is_lvalue(lhs_status))
07034 Prepend_Token_Special(tokens, '*');
07035 }
07036
07037
07038 void
07039 WN2C_stid_lhs(TOKEN_BUFFER tokens,
07040 TY_IDX *stored_typ,
07041 const ST *lhs_st,
07042 STAB_OFFSET stid_ofst,
07043 TY_IDX stid_ty,
07044 MTYPE dtype,
07045 CONTEXT context,
07046 UINT field_id)
07047 {
07048
07049
07050 TY_IDX base_ty;
07051 STATUS lhs_status;
07052
07053 if (ST_sym_class(lhs_st) == CLASS_PREG)
07054 {
07055
07056
07057
07058 *stored_typ = PUinfo_Preg_Type(ST_type(lhs_st), stid_ofst);
07059 WN2C_Append_Preg(tokens,
07060 lhs_st,
07061 stid_ofst,
07062 *stored_typ,
07063 context);
07064 }
07065 else
07066 {
07067
07068
07069
07070 WN2C_SymAccess_Type(&base_ty,
07071 stored_typ,
07072 ST_type(lhs_st),
07073 stid_ty,
07074 dtype,
07075 stid_ofst);
07076 lhs_status = WN2C_lvalue_st(tokens,
07077 lhs_st,
07078 base_ty,
07079 *stored_typ,
07080 stid_ofst,
07081 context,
07082 field_id);
07083
07084
07085
07086
07087 if (!STATUS_is_lvalue(lhs_status))
07088 Prepend_Token_Special(tokens, '*');
07089 }
07090 }
07091
07092