diff options
author | njn <njn@a5019735-40e9-0310-863c-91ae7b9d1cf9> | 2005-10-16 00:17:37 +0000 |
---|---|---|
committer | njn <njn@a5019735-40e9-0310-863c-91ae7b9d1cf9> | 2005-10-16 00:17:37 +0000 |
commit | fd9f622c84fba391215e415e942772862d0fe2af (patch) | |
tree | b15ac1f41d5aacd0f5e4ee265495d84201822644 /cachegrind | |
parent | c285dcafa07466ab307726181cae2e9478b632c0 (diff) |
A small Cachegrind cleanup: previously it was copying some things (eg.
instr_size and instr_addr) into Ir events, then later copying those into
instrInfo nodes. Now it just allocates the instrInfo nodes earlier and
copies them in directly. This is a bit more concise and easier to
understand.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4937 a5019735-40e9-0310-863c-91ae7b9d1cf9
Diffstat (limited to 'cachegrind')
-rw-r--r-- | cachegrind/cg_main.c | 228 |
1 files changed, 90 insertions, 138 deletions
diff --git a/cachegrind/cg_main.c b/cachegrind/cg_main.c index d8460336..d750953b 100644 --- a/cachegrind/cg_main.c +++ b/cachegrind/cg_main.c @@ -414,10 +414,10 @@ typedef typedef struct { - EventKind ekind; - Int size; /* ALL */ - Addr64 iaddr; /* ALL. For Dr/Dw/Dm is & of parent insn. */ - IRAtom* dataEA; /* Dr/Dw/Dm only */ /* IR ATOM ONLY */ + EventKind ekind; // All + InstrInfo* inode; // All; inode for this event's instruction + Int datasize; // Dr/Dw/Dm only + IRAtom* dataEA; // Dr/Dw/Dm only; IR ATOM ONLY } Event; @@ -486,32 +486,24 @@ BB_info* get_BB_info(IRBB* bbIn, Addr origAddr) } -static -void init_InstrInfo( InstrInfo* n, Addr instr_addr, Int instr_len ) -{ - n->instr_addr = instr_addr; - n->instr_len = instr_len; - n->parent = get_lineCC(instr_addr); -} - static void showEvent ( Event* ev ) { switch (ev->ekind) { case Event_Ir: - VG_(printf)("Ir %d 0x%llx\n", ev->size, ev->iaddr); + VG_(printf)("Ir %p\n", ev->inode); break; case Event_Dr: - VG_(printf)("Dr %d 0x%llx EA=", ev->size, ev->iaddr); + VG_(printf)("Dr %p %d EA=", ev->inode, ev->datasize); ppIRExpr(ev->dataEA); VG_(printf)("\n"); break; case Event_Dw: - VG_(printf)("Dw %d 0x%llx EA=", ev->size, ev->iaddr); + VG_(printf)("Dw %p %d EA=", ev->inode, ev->datasize); ppIRExpr(ev->dataEA); VG_(printf)("\n"); break; case Event_Dm: - VG_(printf)("Dm %d 0x%llx EA=", ev->size, ev->iaddr); + VG_(printf)("Dm %p %d EA=", ev->inode, ev->datasize); ppIRExpr(ev->dataEA); VG_(printf)("\n"); break; @@ -521,29 +513,22 @@ static void showEvent ( Event* ev ) } } -/* Reserve InstrInfo for the first mention of a new insn. */ - -static InstrInfo* reserve_InstrInfo ( CgState* cgs ) +// Reserve and initialise an InstrInfo for the first mention of a new insn. +static +InstrInfo* setup_InstrInfo ( CgState* cgs, Addr instr_addr, UInt instr_len ) { InstrInfo* i_node; tl_assert(cgs->bbInfo_i >= 0); tl_assert(cgs->bbInfo_i < cgs->bbInfo->n_instrs); i_node = &cgs->bbInfo->instrs[ cgs->bbInfo_i ]; + i_node->instr_addr = instr_addr; + i_node->instr_len = instr_len; + i_node->parent = get_lineCC(instr_addr); cgs->bbInfo_i++; return i_node; } -/* Find the most recently allocated InstrInfo. */ - -static InstrInfo* find_most_recent_InstrInfo ( CgState* cgs ) -{ - tl_assert(cgs->bbInfo_i >= 0); - tl_assert(cgs->bbInfo_i <= cgs->bbInfo->n_instrs); - return &cgs->bbInfo->instrs[ cgs->bbInfo_i - 1 ]; -} - - /* Generate code for all outstanding memory events, and mark the queue empty. Code is generated into cgs->bbOut, and this activity 'consumes' slots in cgs->bbInfo. */ @@ -555,12 +540,7 @@ static void flushEvents ( CgState* cgs ) void* helperAddr; IRExpr** argv; IRExpr* i_node_expr; - IRExpr* i_node2_expr; - IRExpr* i_node3_expr; IRDirty* di; - InstrInfo* i_node; - InstrInfo* i_node2; - InstrInfo* i_node3; Event* ev; Event* ev2; Event* ev3; @@ -586,28 +566,7 @@ static void flushEvents ( CgState* cgs ) showEvent( ev ); } - /* For any event we find the relevant InstrInfo. The following - assumes that Event_Ir is the first event to refer to any - specific insn, and so a new entry in the cgs->bbInfo->instrs - is allocated. All other events (Dr,Dw,Dm) must refer to the - most recently encountered IMark and so we use the - most-recently allocated instrs[] entry, which must exist. */ - - if (ev->ekind == Event_Ir) { - /* allocate an InstrInfo and fill in its addr/size. */ - i_node = reserve_InstrInfo( cgs ); - init_InstrInfo( i_node, - (Addr)ev->iaddr, /* i addr */ - ev->size /* i size */); - } else { - /* use the most-recently allocated i_node but don't mess with - its internals */ - i_node = find_most_recent_InstrInfo( cgs ); - /* it must match the declared parent instruction of this event. */ - tl_assert(i_node->instr_addr == ev->iaddr); - } - - i_node_expr = mkIRExpr_HWord( (HWord)i_node ); + i_node_expr = mkIRExpr_HWord( (HWord)ev->inode ); /* Decide on helper fn to call and args to pass it, and advance i appropriately. */ @@ -615,24 +574,24 @@ static void flushEvents ( CgState* cgs ) case Event_Ir: /* Merge with a following Dr/Dm if it is from this insn. */ if (ev2 && (ev2->ekind == Event_Dr || ev2->ekind == Event_Dm)) { - tl_assert(ev2->iaddr == ev->iaddr); + tl_assert(ev2->inode == ev->inode); helperName = "log_1I_1Dr_cache_access"; helperAddr = &log_1I_1Dr_cache_access; argv = mkIRExprVec_3( i_node_expr, ev2->dataEA, - mkIRExpr_HWord( ev2->size ) ); + mkIRExpr_HWord( ev2->datasize ) ); regparms = 3; i += 2; } /* Merge with a following Dw if it is from this insn. */ else if (ev2 && ev2->ekind == Event_Dw) { - tl_assert(ev2->iaddr == ev->iaddr); + tl_assert(ev2->inode == ev->inode); helperName = "log_1I_1Dw_cache_access"; helperAddr = &log_1I_1Dw_cache_access; argv = mkIRExprVec_3( i_node_expr, ev2->dataEA, - mkIRExpr_HWord( ev2->size ) ); + mkIRExpr_HWord( ev2->datasize ) ); regparms = 3; i += 2; } @@ -642,20 +601,9 @@ static void flushEvents ( CgState* cgs ) { helperName = "log_3I_0D_cache_access"; helperAddr = &log_3I_0D_cache_access; - - i_node2 = reserve_InstrInfo( cgs ); - init_InstrInfo( i_node2, - (Addr)ev2->iaddr, /* i addr */ - ev2->size /* i size */); - i_node2_expr = mkIRExpr_HWord( (HWord)i_node2 ); - - i_node3 = reserve_InstrInfo( cgs ); - init_InstrInfo( i_node3, - (Addr)ev3->iaddr, /* i addr */ - ev3->size /* i size */); - i_node3_expr = mkIRExpr_HWord( (HWord)i_node3 ); - - argv = mkIRExprVec_3( i_node_expr, i_node2_expr, i_node3_expr ); + argv = mkIRExprVec_3( i_node_expr, + mkIRExpr_HWord( (HWord)ev2->inode ), + mkIRExpr_HWord( (HWord)ev3->inode ) ); regparms = 3; i += 3; } @@ -664,14 +612,8 @@ static void flushEvents ( CgState* cgs ) if (ev2 && ev2->ekind == Event_Ir) { helperName = "log_2I_0D_cache_access"; helperAddr = &log_2I_0D_cache_access; - - i_node2 = reserve_InstrInfo( cgs ); - init_InstrInfo( i_node2, - (Addr)ev2->iaddr, /* i addr */ - ev2->size /* i size */); - - i_node2_expr = mkIRExpr_HWord( (HWord)i_node2 ); - argv = mkIRExprVec_2( i_node_expr, i_node2_expr ); + argv = mkIRExprVec_2( i_node_expr, + mkIRExpr_HWord( (HWord)ev2->inode ) ); regparms = 2; i += 2; } @@ -694,7 +636,7 @@ static void flushEvents ( CgState* cgs ) helperAddr = &log_0I_1Dr_cache_access; argv = mkIRExprVec_3( i_node_expr, ev->dataEA, - mkIRExpr_HWord( ev->size ) ); + mkIRExpr_HWord( ev->datasize ) ); regparms = 3; i++; break; @@ -703,7 +645,7 @@ static void flushEvents ( CgState* cgs ) helperAddr = &log_0I_1Dw_cache_access; argv = mkIRExprVec_3( i_node_expr, ev->dataEA, - mkIRExpr_HWord( ev->size ) ); + mkIRExpr_HWord( ev->datasize ) ); regparms = 3; i++; break; @@ -722,56 +664,55 @@ static void flushEvents ( CgState* cgs ) cgs->events_used = 0; } - -static void addEvent_Ir ( CgState* cgs, Int size, Addr64 iaddr ) +static void addEvent_Ir ( CgState* cgs, InstrInfo* inode ) { Event* evt; - tl_assert(size >= 0 && size <= MIN_LINE_SIZE); if (cgs->events_used == N_EVENTS) flushEvents(cgs); tl_assert(cgs->events_used >= 0 && cgs->events_used < N_EVENTS); - /* If vex fails to decode an insn, the size will be zero, but that - can't really be true -- the cpu couldn't have determined the - insn was undecodable without looking at it. Hence: */ - if (size == 0) - size = 1; evt = &cgs->events[cgs->events_used]; - evt->ekind = Event_Ir; - evt->size = size; - evt->iaddr = iaddr; - evt->dataEA = NULL; /*paranoia*/ + evt->ekind = Event_Ir; + evt->inode = inode; + evt->datasize = 0; + evt->dataEA = NULL; /*paranoia*/ cgs->events_used++; } -static void addEvent_Dr ( CgState* cgs, Int size, Addr64 iaddr, IRAtom* ea ) +static +void addEvent_Dr ( CgState* cgs, InstrInfo* inode, Int datasize, IRAtom* ea ) { Event* evt; tl_assert(isIRAtom(ea)); - tl_assert(size >= 1 && size <= MIN_LINE_SIZE); + tl_assert(datasize >= 1 && datasize <= MIN_LINE_SIZE); if (cgs->events_used == N_EVENTS) flushEvents(cgs); tl_assert(cgs->events_used >= 0 && cgs->events_used < N_EVENTS); evt = &cgs->events[cgs->events_used]; - evt->ekind = Event_Dr; - evt->size = size; - evt->iaddr = iaddr; - evt->dataEA = ea; + evt->ekind = Event_Dr; + evt->inode = inode; + evt->datasize = datasize; + evt->dataEA = ea; cgs->events_used++; } -static void addEvent_Dw ( CgState* cgs, Int size, Addr64 iaddr, IRAtom* ea ) +static +void addEvent_Dw ( CgState* cgs, InstrInfo* inode, Int datasize, IRAtom* ea ) { + Event* lastEvt; + Event* evt; + tl_assert(isIRAtom(ea)); - tl_assert(size >= 1 && size <= MIN_LINE_SIZE); + tl_assert(datasize >= 1 && datasize <= MIN_LINE_SIZE); - /* Is it possible to merge this write into an immediately preceding - read? */ + /* Is it possible to merge this write with the preceding read? */ + lastEvt = &cgs->events[cgs->events_used-1]; if (cgs->events_used > 0 - && cgs->events[cgs->events_used-1].ekind == Event_Dr - && cgs->events[cgs->events_used-1].size == size - && cgs->events[cgs->events_used-1].iaddr == iaddr - && eqIRAtom(cgs->events[cgs->events_used-1].dataEA, ea)) { - cgs->events[cgs->events_used-1].ekind = Event_Dm; + && lastEvt->ekind == Event_Dr + && lastEvt->datasize == datasize + && lastEvt->inode == inode + && eqIRAtom(lastEvt->dataEA, ea)) + { + lastEvt->ekind = Event_Dm; return; } @@ -779,10 +720,11 @@ static void addEvent_Dw ( CgState* cgs, Int size, Addr64 iaddr, IRAtom* ea ) if (cgs->events_used == N_EVENTS) flushEvents(cgs); tl_assert(cgs->events_used >= 0 && cgs->events_used < N_EVENTS); - cgs->events[cgs->events_used].ekind = Event_Dw; - cgs->events[cgs->events_used].size = size; - cgs->events[cgs->events_used].iaddr = iaddr; - cgs->events[cgs->events_used].dataEA = ea; + evt = &cgs->events[cgs->events_used]; + evt->ekind = Event_Dw; + evt->inode = inode; + evt->datasize = datasize; + evt->dataEA = ea; cgs->events_used++; } @@ -792,11 +734,12 @@ static void addEvent_Dw ( CgState* cgs, Int size, Addr64 iaddr, IRAtom* ea ) static IRBB* cg_instrument ( IRBB* bbIn, VexGuestLayout* layout, IRType gWordTy, IRType hWordTy ) { - Int i; + Int i, isize; IRStmt* st; Addr64 cia; /* address of current insn */ CgState cgs; IRTypeEnv* tyenv = bbIn->tyenv; + InstrInfo* curr_inode = NULL; if (gWordTy != hWordTy) { @@ -804,9 +747,12 @@ static IRBB* cg_instrument ( IRBB* bbIn, VexGuestLayout* layout, VG_(tool_panic)("host/guest word size mismatch"); } - /* Set up BB */ - cgs.bbOut = emptyIRBB(); - cgs.bbOut->tyenv = dopyIRTypeEnv(tyenv); + /* Set up BB, including copying of the where-next stuff. */ + cgs.bbOut = emptyIRBB(); + cgs.bbOut->tyenv = dopyIRTypeEnv(tyenv); + tl_assert( isIRAtom(bbIn->next) ); + cgs.bbOut->next = dopyIRExpr(bbIn->next); + cgs.bbOut->jumpkind = bbIn->jumpkind; // Get the first statement, and initial cia from it i = 0; @@ -823,7 +769,8 @@ static IRBB* cg_instrument ( IRBB* bbIn, VexGuestLayout* layout, if (DEBUG_CG) VG_(printf)("\n\n---------- cg_instrument ----------\n"); - // Traverse the block, adding events and flushing as necessary. + // Traverse the block, initialising inodes, adding events and flushing as + // necessary. for (i = 0; i < bbIn->stmts_used; i++) { st = bbIn->stmts[i]; @@ -838,19 +785,32 @@ static IRBB* cg_instrument ( IRBB* bbIn, VexGuestLayout* layout, break; case Ist_IMark: - cia = st->Ist.IMark.addr; - addEvent_Ir( &cgs, st->Ist.IMark.len, cia ); + cia = st->Ist.IMark.addr; + isize = st->Ist.IMark.len; + + // If Vex fails to decode an instruction, the size will be zero. + // Pretend otherwise. + if (isize == 0) isize = VG_MIN_INSTR_SZB; + + // Check size. XXX: broken for client requests! + tl_assert(VG_MIN_INSTR_SZB <= isize && isize <= VG_MAX_INSTR_SZB); + + // Get space for and init the inode, record it as the current one. + // Subsequent Dr/Dw/Dm events from the same instruction will + // also use it. + curr_inode = setup_InstrInfo(&cgs, cia, isize); + + addEvent_Ir( &cgs, curr_inode ); break; case Ist_Tmp: { IRExpr* data = st->Ist.Tmp.data; if (data->tag == Iex_Load) { IRExpr* aexpr = data->Iex.Load.addr; - tl_assert( isIRAtom(aexpr) ); // Note also, endianness info is ignored. I guess // that's not interesting. - addEvent_Dr( &cgs, sizeofIRType(data->Iex.Load.ty), - cia, aexpr ); + addEvent_Dr( &cgs, curr_inode, sizeofIRType(data->Iex.Load.ty), + aexpr ); } break; } @@ -858,10 +818,8 @@ static IRBB* cg_instrument ( IRBB* bbIn, VexGuestLayout* layout, case Ist_Store: { IRExpr* data = st->Ist.Store.data; IRExpr* aexpr = st->Ist.Store.addr; - tl_assert( isIRAtom(aexpr) ); - addEvent_Dw( &cgs, - sizeofIRType(typeOfIRExpr(tyenv, data)), - cia, aexpr ); + addEvent_Dw( &cgs, curr_inode, + sizeofIRType(typeOfIRExpr(tyenv, data)), aexpr ); break; } @@ -869,8 +827,7 @@ static IRBB* cg_instrument ( IRBB* bbIn, VexGuestLayout* layout, Int dataSize; IRDirty* d = st->Ist.Dirty.details; if (d->mFx != Ifx_None) { - /* This dirty helper accesses memory. Collect the - details. */ + /* This dirty helper accesses memory. Collect the details. */ tl_assert(d->mAddr != NULL); tl_assert(d->mSize != 0); dataSize = d->mSize; @@ -881,9 +838,9 @@ static IRBB* cg_instrument ( IRBB* bbIn, VexGuestLayout* layout, if (dataSize > MIN_LINE_SIZE) dataSize = MIN_LINE_SIZE; if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) - addEvent_Dr( &cgs, dataSize, cia, d->mAddr ); + addEvent_Dr( &cgs, curr_inode, dataSize, d->mAddr ); if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) - addEvent_Dw( &cgs, dataSize, cia, d->mAddr ); + addEvent_Dw( &cgs, curr_inode, dataSize, d->mAddr ); } else { tl_assert(d->mAddr == NULL); tl_assert(d->mSize == 0); @@ -912,13 +869,8 @@ static IRBB* cg_instrument ( IRBB* bbIn, VexGuestLayout* layout, } /* At the end of the bb. Flush outstandings. */ - tl_assert(isIRAtom(bbIn->next)); flushEvents( &cgs ); - /* copy where-next stuff. */ - cgs.bbOut->next = dopyIRExpr(bbIn->next); - cgs.bbOut->jumpkind = bbIn->jumpkind; - /* done. stay sane ... */ tl_assert(cgs.bbInfo_i == cgs.bbInfo->n_instrs); |