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