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 "defs.h"
00052 #include "tn.h"
00053 #include "op.h"
00054 #include "bb.h"
00055 #include "wn.h"
00056 #include "symtab.h"
00057 #include "errors.h"
00058 #include "targ_sim.h"
00059 #include "ttype.h"
00060 #include "topcode.h"
00061 #include "register.h"
00062 #include "entry_exit_targ.h"
00063 #include "calls.h"
00064 #include "be_util.h"
00065 #include "data_layout.h"
00066 #include "stblock.h"
00067 #include "cgtarget.h"
00068 #include "whirl2ops.h"
00069 #include "cgexp.h"
00070 #include "cxx_template.h"
00071 #include "cg_spill.h"
00072 #include "cg.h"
00073
00074 static ST* save_ebx_loc = NULL;
00075 static INT32 last_pu_count = -1;
00076
00077 static BOOL need_ip = FALSE;
00078
00079 const char * ip_calc_funcname = "getip.pathscale";
00080
00081 void EETARG_Generate_PIC_Exit_Code( BB* bb, OPS* ops )
00082 {
00083 if( save_ebx_loc == NULL )
00084 return;
00085
00086 CGSPILL_Load_From_Memory( Ebx_TN(), save_ebx_loc, ops, CGSPILL_LCL, bb );
00087 Set_OP_computes_got( OPS_last(ops) );
00088 }
00089
00090
00091 void EETARG_Generate_PIC_Entry_Code( BB* bb, OPS* ops )
00092 {
00093 FmtAssert( BB_entry(bb), ("BB is not entry") );
00094 FmtAssert( Is_Target_32bit(), ("PIC entry for -m32 only") );
00095
00096 if( BB_handler( bb ) )
00097 return;
00098
00099 TN* ebx_tn = Ebx_TN();
00100
00101 if( REGISTER_allocatable( TN_register_class(ebx_tn),
00102 TN_register(ebx_tn) ) ){
00103 save_ebx_loc = NULL;
00104 return;
00105 }
00106
00107 if( last_pu_count != Current_PU_Count() ){
00108 save_ebx_loc = CGSPILL_Get_TN_Spill_Location( ebx_tn, CGSPILL_LCL );
00109 last_pu_count = Current_PU_Count();
00110 }
00111
00112
00113
00114
00115 {
00116 SAVE_REG_LOC sr;
00117 extern STACK<SAVE_REG_LOC> Saved_Callee_Saved_Regs;
00118
00119 sr.user_allocated = FALSE;
00120 sr.ded_tn = ebx_tn;
00121 sr.temp = save_ebx_loc;
00122 Saved_Callee_Saved_Regs.Push(sr);
00123 }
00124
00125 CGSPILL_Store_To_Memory( ebx_tn, save_ebx_loc, ops, CGSPILL_LCL, bb );
00126
00127
00128
00129 BB* call_bb = Gen_And_Insert_BB_Before(bb);
00130 BB_Transfer_Entryinfo( bb, call_bb );
00131 REGION_First_BB = call_bb;
00132 Entry_BB_Head = BB_LIST_Delete( bb, Entry_BB_Head );
00133 Entry_BB_Head = BB_LIST_Push( call_bb, Entry_BB_Head, &MEM_pu_pool );
00134 Chain_BBs( call_bb, bb );
00135 Link_Pred_Succ_with_Prob( call_bb, bb, 1.0 );
00136 BB_rid( call_bb ) = BB_rid( bb );
00137 BB_freq( call_bb ) = BB_freq( bb );
00138 if( BB_freq_fb_based( bb ) )
00139 Set_BB_freq_fb_based( call_bb );
00140
00141
00142 BB* bb2 = Gen_And_Insert_BB_Before(bb);
00143 Chain_BBs(bb2, bb);
00144 Link_Pred_Succ_with_Prob(bb2, bb, 1.0);
00145 BB_rid(bb2) = BB_rid(bb);
00146 BB_freq(bb2) = BB_freq(bb);
00147 if (BB_freq_fb_based(bb))
00148 Set_BB_freq_fb_based(bb2);
00149 Change_Succ(call_bb, bb, bb2);
00150
00151 PU_IDX pu_idx;
00152 PU& pu = New_PU (pu_idx);
00153 ST* st = New_ST( GLOBAL_SYMTAB );
00154 TY_IDX func_ty_idx;
00155 TY &func_ty = New_TY(func_ty_idx);
00156 TY_Init( func_ty, 0, KIND_FUNCTION, MTYPE_UNKNOWN, STR_IDX_ZERO );
00157 Set_TY_align( func_ty_idx, 1 );
00158
00159 TYLIST tylist_idx;
00160 Set_TYLIST_type( New_TYLIST(tylist_idx), MTYPE_To_TY(Pointer_Mtype) );
00161 Set_TY_tylist( func_ty, tylist_idx );
00162 Set_TYLIST_type( New_TYLIST (tylist_idx), 0 );
00163
00164 Set_TY_has_prototype(func_ty_idx);
00165
00166 PU_Init( pu, func_ty_idx, CURRENT_SYMTAB );
00167
00168 if (Is_Target_EM64T() ||
00169 Is_Target_Wolfdale() ||
00170 Is_Target_Core())
00171 {
00172 const LABEL_IDX bb_label = Gen_Label_For_BB(bb2);
00173
00174 ST_Init( st, Save_Str(LABEL_name(bb_label)),
00175 CLASS_FUNC, SCLASS_EXTERN,
00176 EXPORT_PREEMPTIBLE,
00177 TY_IDX(pu_idx) );
00178
00179 CALLINFO* call_info = TYPE_PU_ALLOC(CALLINFO);
00180 CALLINFO_call_st(call_info) = st;
00181 CALLINFO_call_wn(call_info) = WN_Call(MTYPE_V, MTYPE_V, 0, st);
00182 BB_Add_Annotation( call_bb, ANNOT_CALLINFO, call_info );
00183 Set_BB_call( call_bb );
00184
00185 TN* label_tn = Gen_Label_TN( bb_label, 0 );
00186 Exp_Call( OPR_CALL, NULL, label_tn, ops );
00187 BB_Append_Ops( call_bb, ops );
00188
00189 OPS_Remove_All( ops );
00190
00191 Build_OP( TOP_popl, ebx_tn, SP_TN, SP_TN, ops );
00192 Set_OP_computes_got( OPS_last(ops) );
00193 Exp_ADD( Pointer_Mtype,
00194 ebx_tn, ebx_tn,
00195 Gen_Symbol_TN(st, 0, TN_RELOC_IA32_GLOBAL_OFFSET_TABLE), ops );
00196 Set_OP_computes_got( OPS_last(ops) );
00197 BB_Append_Ops(bb2, ops);
00198 }
00199 else
00200 {
00201
00202 BB *bb3 = Gen_And_Insert_BB_Before(bb);
00203 Chain_BBs(bb3, bb);
00204 Link_Pred_Succ_with_Prob(bb3, bb, 1.0 );
00205 BB_rid(bb3) = BB_rid(bb);
00206 BB_freq(bb3) = BB_freq(bb);
00207 if (BB_freq_fb_based(bb))
00208 Set_BB_freq_fb_based(bb3);
00209 Change_Succ(bb2, bb, bb3);
00210
00211
00212 ST_Init( st, Save_Str(ip_calc_funcname),
00213 CLASS_FUNC, SCLASS_TEXT,
00214 EXPORT_LOCAL,
00215 TY_IDX(pu_idx) );
00216
00217 Allocate_Object (st);
00218 CALLINFO* call_info = TYPE_PU_ALLOC(CALLINFO);
00219 CALLINFO_call_st(call_info) = st;
00220 CALLINFO_call_wn(call_info) = WN_Call(MTYPE_V, MTYPE_V, 0, st);
00221 BB_Add_Annotation( call_bb, ANNOT_CALLINFO, call_info );
00222 Set_BB_call( call_bb );
00223
00224 TN* tgt_tn = Gen_Symbol_TN(st, 0, 0);
00225 Exp_Call( OPR_CALL, RA_TN, tgt_tn, ops );
00226 BB_Append_Ops( call_bb, ops );
00227
00228 OPS_Remove_All( ops );
00229
00230
00231
00232 Exp_ADD(Pointer_Mtype,
00233 ebx_tn, ebx_tn,
00234 Gen_Symbol_TN(st, 0, TN_RELOC_IA32_GLOBAL_OFFSET_TABLE), ops);
00235 Set_OP_computes_got(OPS_last(ops));
00236 BB_Append_Ops(bb2, ops);
00237 need_ip = TRUE;
00238 }
00239
00240 OPS_Remove_All(ops);
00241
00242 return;
00243 }
00244
00245
00246 void
00247 EETARG_Save_Pfs (TN *saved_pfs, OPS *ops)
00248 {
00249 }
00250
00251
00252 void
00253 EETARG_Restore_Pfs (TN *saved_pfs, OPS *ops)
00254 {
00255 }
00256
00257
00258 void
00259 EETARG_Adjust_SP_For_Entry( TN *incr, OPS *ops )
00260 {
00261 FmtAssert(FALSE, ("NYI: EETARG_Adjust_SP_For_Entry"));
00262 }
00263
00264 void
00265 EETARG_Adjust_SP_For_Exit( TN *incr, OPS *ops )
00266 {
00267 FmtAssert(FALSE, ("NYI: EETARG_Adjust_SP_For_Exit"));
00268 }
00269
00270 void
00271 EETARG_Fixup_Entry_Code (BB *bb)
00272 {
00273 }
00274
00275 void
00276 EETARG_Init_Entry_Exit_Code (WN *pu_wn, BOOL need_frame_pointer)
00277 {
00278 }
00279
00280 void EETARG_Save_Extra_Callee_Tns (OPS *ops)
00281 {
00282 }
00283
00284 void EETARG_Restore_Extra_Callee_Tns (OPS *ops)
00285 {
00286 }
00287
00288
00289 OP *
00290 EETARG_Build_Jump_Instead_Of_Call (OP *call_op)
00291 {
00292 const TOP jump_top = OP_ijump(call_op) ? TOP_ijmp : TOP_jmp;
00293 OP* jump_op = Mk_OP(jump_top, OP_opnd(call_op, 0));
00294
00295 Is_True(OP_opnds(call_op) == 1, ("unexpected number of call opnds"));
00296 Is_True(OP_opnds(jump_op) == 1, ("unexpected number of jump opnds"));
00297
00298 return jump_op;
00299 }
00300
00301 OP* EETARG_High_Level_Procedure_Exit()
00302 {
00303
00304 TN *result = Build_Dedicated_TN( ISA_REGISTER_CLASS_integer, RSP, 0 );
00305 TN *src = Build_Dedicated_TN( ISA_REGISTER_CLASS_integer, RBP, 0 );
00306 return Mk_OP(TOP_leave, result, src);
00307 }
00308
00309
00310 extern void CGEMIT_Setup_IP_Calc(void);
00311
00312 void EETARG_Emit_IP_Calc_Func (void)
00313 {
00314 if (need_ip)
00315 CGEMIT_Setup_IP_Calc();
00316 }