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 #include <stdio.h>
00052 #include <string.h>
00053 #include <vector>
00054
00055 #include "defs.h"
00056 #include "errors.h"
00057 #include "srcpos.h"
00058 #include "opcode.h"
00059 #include "wn.h"
00060 #include "wn_simp.h"
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #include "DaVinci.h"
00071 #include "wb_util.h"
00072 #include "com_whirlview.h"
00073 #include "fb_whirl.h"
00074
00075 #define MAXEXPR 5000
00076
00077 static MEM_POOL DV_wv_mempool;
00078 static BOOL DV_wv_mempool_init = FALSE;
00079 static DaVinci *DV = NULL;
00080 static WN *Func_wn = NULL;
00081
00082 static void draw_expr(WN *);
00083 static void draw_stmt(WN *);
00084
00085 static char *
00086 id_str(WN *wn)
00087 {
00088 static char dv_id[64];
00089 INT len;
00090
00091 if ( wn ) {
00092
00093 len = sprintf( dv_id, "%d:%d",
00094 OPCODE_mapcat(WN_opcode(wn)), WN_map_id(wn) );
00095 } else {
00096 strcpy( dv_id, "NULL-WN" );
00097 }
00098
00099 if ( Cur_PU_Feedback ) {
00100 FB_FREQ freq = Cur_PU_Feedback->Query_total_out( wn );
00101 freq.Sprintf( dv_id + len );
00102 }
00103
00104 return dv_id;
00105 }
00106
00107 static void
00108 draw_expr(WN *wn)
00109
00110 {
00111 NODE_TYPE nt;
00112 EDGE_TYPE et;
00113 INT i;
00114
00115 DV->Node_Begin( NODE_ID(wn), id_str(wn), nt );
00116
00117 for (i = 0; i < WN_kid_count(wn); i++) {
00118 WN *wn2 = WN_kid(wn,i);
00119 DV->Out_Edge( EDGE_ID(wn, wn2), et, NODE_ID(wn2) );
00120 }
00121 DV->Node_End();
00122
00123 for (i = 0; i < WN_kid_count(wn); i++) {
00124 draw_expr( WN_kid(wn,i) );
00125 }
00126 }
00127
00128 static void
00129 draw_stmt(WN *wn, BOOL show_expr)
00130 {
00131 NODE_TYPE nt;
00132 EDGE_TYPE et;
00133
00134 vector<WN*> kids;
00135
00136 switch (WN_opcode(wn)) {
00137 case OPC_BLOCK: {
00138 WN *wn2 = WN_first(wn);
00139 while (wn2) {
00140 kids.push_back( wn2 );
00141 wn2 = WN_next(wn2);
00142 }
00143 break;
00144 }
00145 case OPC_IF:
00146 nt.Shape( NS_RHOMBUS );
00147 if ( WN_then(wn) ) {
00148 kids.push_back( WN_then(wn) );
00149 }
00150 if ( show_expr ) {
00151 kids.push_back( WN_if_test(wn) );
00152 }
00153 if ( WN_else(wn) ) {
00154 kids.push_back( WN_else(wn) );
00155 }
00156 break;
00157
00158 case OPC_DO_LOOP:
00159 nt.Shape( NS_ELLIPSE );
00160 if ( show_expr ) kids.push_back( WN_index(wn) );
00161 kids.push_back( WN_start(wn) );
00162 if ( show_expr ) kids.push_back( WN_end(wn) );
00163 kids.push_back( WN_do_body(wn) );
00164 kids.push_back( WN_step(wn) );
00165 break;
00166
00167 case OPC_COMPGOTO:
00168 if ( show_expr ) kids.push_back( WN_kid(wn,0) );
00169 kids.push_back( WN_kid(wn,1) );
00170 if ( WN_kid_count(wn) > 2 ) {
00171 kids.push_back( WN_kid(wn,2) );
00172 }
00173 break;
00174
00175 case OPC_XGOTO:
00176 if ( show_expr ) kids.push_back( WN_kid(wn,0) );
00177 kids.push_back( WN_kid(wn,1) );
00178 break;
00179
00180 default:
00181 {
00182 for (INT i = 0; i < WN_kid_count(wn); ++i) {
00183 WN* wn2 = WN_kid(wn,i);
00184 FmtAssert(wn2, ("Null kid in draw_stmt"));
00185 OPCODE opc2 = WN_opcode(wn2);
00186 if ( show_expr && OPCODE_is_expression(opc2) ) {
00187 kids.push_back( wn2 );
00188 } else if ( OPCODE_is_stmt(opc2) || OPCODE_is_scf(opc2) ) {
00189 kids.push_back( wn2 );
00190 }
00191 }
00192 }
00193 }
00194
00195
00196 if ( Cur_PU_Feedback ) {
00197 FB_FREQ freq = Cur_PU_Feedback->Query_total_out( wn );
00198 if ( freq.Known() ) {
00199 nt.Color( "wheat1" );
00200 }
00201 }
00202
00203 DV->Node_Begin( NODE_ID(wn), id_str(wn), nt );
00204
00205 vector<WN*>::iterator wn_iter;
00206
00207 for (wn_iter = kids.begin(); wn_iter != kids.end(); ++wn_iter) {
00208 WN *wn2 = *wn_iter;
00209
00210 DV->Out_Edge( EDGE_ID(wn,wn2), et, NODE_ID(wn2) );
00211 }
00212 DV->Node_End();
00213
00214 for (wn_iter = kids.begin(); wn_iter != kids.end(); ++wn_iter) {
00215 WN *wn2 = *wn_iter;
00216
00217 draw_stmt( wn2, show_expr );
00218 }
00219 }
00220
00221 static void
00222 draw_whirl_tree(WN *wn, BOOL show_expr)
00223 {
00224 DV->Graph_Begin();
00225
00226 if ( OPCODE_is_expression(WN_opcode(wn)) ) {
00227 draw_expr( wn );
00228 } else if ( OPCODE_is_stmt(WN_opcode(wn))
00229 || OPCODE_is_scf(WN_opcode(wn)) ) {
00230 draw_stmt( wn, show_expr );
00231 } else {
00232 FmtAssert( FALSE, ("opcode of unknown type") );
00233 }
00234 DV->Graph_End();
00235 }
00236
00237 class Callback : public DaVinci_Callback {
00238 WN *node_sel;
00239 public:
00240 virtual void Node_Select(const INT n_ids, const NODE_ID id_array[]);
00241 virtual void Edge_Select(const EDGE_ID& id);
00242 virtual void Menu_Select(const char *menu_id);
00243 };
00244
00245 void
00246 Callback::Node_Select(const INT n_ids, const NODE_ID id_array[])
00247 {
00248 char buf[ MAXEXPR ];
00249
00250 for (INT i = 0; i < n_ids; ++i) {
00251 WN *wn = (WN *)id_array[i];
00252 WN *head_wn = ( Func_wn ? Func_wn : wn );
00253 INT end = WB_Dump_Whirl_Expr(head_wn, wn, buf, 0);
00254 buf[end] = '\0';
00255 printf("%p: %s\n", wn, buf);
00256 }
00257 node_sel = (n_ids > 0 ? (WN *)id_array[n_ids - 1] : NULL);
00258 }
00259
00260 void
00261 Callback::Edge_Select(const EDGE_ID& id)
00262 {
00263 EDGE_TYPE et;
00264
00265 et.Color( "red" );
00266 DV->Change_Attr( id, et );
00267 }
00268
00269 void
00270 Callback::Menu_Select(const char *menu_id)
00271 {
00272 if ( strcmp( menu_id, "EXPAND" ) == 0 && node_sel ) {
00273 printf("selecting EXPAND for node %s\n", id_str(node_sel));
00274
00275
00276 }
00277 }
00278
00279
00280 static MENU_INFO DV_Menu[] = {
00281 { "EXPAND", "Expand Subtree", true, 0, NULL }
00282
00283 };
00284 #define N_DV_MENU ( sizeof(DV_Menu) / sizeof(DV_Menu[0]) )
00285
00286
00287
00288 void
00289 dV_view_whirl(WN *wn, const char *title, BOOL show_expr, FILE *trace_fp)
00290 {
00291 if ( ! DaVinci::enabled(true) ) return;
00292
00293 DaVinci dv(&DV_wv_mempool, trace_fp);
00294 Func_wn = (WN_operator(wn) == OPR_FUNC_ENTRY ? wn : NULL);
00295
00296 const char *trace_fname = getenv("DV_TRACE_FILE");
00297 bool local_trace = false;
00298
00299 if ( trace_fp == NULL && trace_fname ) {
00300 if ( (trace_fp = fopen(trace_fname, "w")) != NULL ) {
00301 local_trace = true;
00302 } else {
00303 fprintf(stderr, "DV_TRACE_FILE not writeable\n");
00304 perror( trace_fname );
00305 }
00306 }
00307 FmtAssert( DV == NULL, ("dV_view_fb_cfg: DV is null"));
00308 if ( ! DV_wv_mempool_init ) {
00309 MEM_POOL_Initialize(&DV_wv_mempool, "DV_wv_mempool", FALSE);
00310 DV_wv_mempool_init = TRUE;
00311 }
00312
00313 DV=&dv;
00314 const char *window_title = (title ? title : "com_whirlview tree display");
00315 DV->Title( window_title );
00316 draw_whirl_tree( wn, show_expr );
00317 DV->Menu_Create( N_DV_MENU, DV_Menu );
00318
00319 Callback callback;
00320 DV->Event_Loop( &callback );
00321
00322 DV = NULL;
00323 Func_wn = NULL;
00324
00325 if ( local_trace ) {
00326 (void)fclose( trace_fp );
00327 }
00328 }