blob: 390482c8091049d58a2fb457242ded4bacb0e1d4 [file] [log] [blame]
#include "CodeViewer.h"
#include "TVApplication.h"
#include "TVTreeItem.h"
#include "TVFrame.h"
#include "llvm/Function.h"
#include "llvm/Instruction.h"
#include "llvm/Value.h"
#include "llvm/ADT/StringExtras.h"
#include <wx/listctrl.h>
#include <map>
#include <sstream>
using namespace llvm;
void TVCodeItem::SetLabel() {
std::string label;
if (!Val)
label = "<badref>";
else if (BasicBlock *BB = dyn_cast<BasicBlock>(Val))
label = BB->getName() + ":";
else if (Instruction *I = dyn_cast<Instruction>(Val)) {
std::ostringstream out;
I->print(out);
label = out.str();
// Post-processing for more attractive display
for (unsigned i = 0; i != label.length(); ++i)
if (label[i] == '\n') { // \n => space
label[i] = ' ';
} else if (label[i] == '\t') { // \t => 2 spaces
label[i] = ' ';
label.insert(label.begin()+i+1, ' ');
} else if (label[i] == ';') { // Delete comments!
unsigned Idx = label.find('\n', i+1); // Find end of line
label.erase(label.begin()+i, label.begin()+Idx);
--i;
}
} else
label = "<invalid value>";
SetText(label.c_str());
}
//===----------------------------------------------------------------------===//
void TVCodeListCtrl::refreshView() {
// Hide the list while rewriting it from scratch to speed up rendering
Hide();
// Clear out the list and then re-add all the items.
long index = 0;
ClearAll();
for (Items::iterator i = itemList.begin(), e = itemList.end(); i != e; ++i) {
InsertItem(index, (**i).m_text.c_str());
ItemToIndex[*i] = index;
++index;
}
Show();
}
template<class T> void wipe (T x) { delete x; }
void TVCodeListCtrl::SetFunction (Function *F) {
// Empty out the code list.
if (!itemList.empty ())
for_each (itemList.begin (), itemList.end (), wipe<TVCodeItem *>);
itemList.clear ();
ValueToItem.clear ();
// Populate it with BasicBlocks and Instructions from F.
for (Function::iterator BB = F->begin(), BBe = F->end(); BB != BBe; ++BB) {
TVCodeItem *TCBB = new TVCodeItem(BB);
itemList.push_back(TCBB);
ValueToItem[BB] = TCBB;
for (BasicBlock::iterator I = BB->begin(), Ie = BB->end(); I != Ie; ++I) {
TVCodeItem *TCI = new TVCodeItem(I);
itemList.push_back(TCI);
ValueToItem[I] = TCI;
}
}
// Since the function changed, we had better make sure that the list control
// matches what's in the code list.
refreshView ();
}
TVCodeListCtrl::TVCodeListCtrl(wxWindow *_parent, llvm::Function *F)
: wxListCtrl(_parent, LLVM_TV_CODEVIEW_LIST, wxDefaultPosition, wxDefaultSize,
wxLC_LIST) {
SetFunction (F);
}
TVCodeListCtrl::TVCodeListCtrl(wxWindow *_parent)
: wxListCtrl(_parent, LLVM_TV_CODEVIEW_LIST, wxDefaultPosition, wxDefaultSize,
wxLC_LIST) {
}
void TVCodeListCtrl::changeItemTextAttrs (TVCodeItem *item, wxColour *newColor,
int newFontWeight) {
item->m_itemId = ItemToIndex[item];
item->SetTextColour(*newColor);
wxFont Font = item->GetFont();
Font.SetWeight(newFontWeight);
item->SetFont(Font);
SetItem(*item);
}
void TVCodeListCtrl::OnItemSelected(wxListEvent &event) {
Value *V = itemList[event.GetIndex ()]->getValue();
if (!V) return;
// Highlight uses in red
for (User::use_iterator u = V->use_begin(), e = V->use_end(); u != e; ++u)
changeItemTextAttrs (ValueToItem[*u], wxRED, wxBOLD);
// Highlight definitions of operands in green
if (User *U = dyn_cast<User>(V))
for (User::op_iterator op = U->op_begin(), e = U->op_end(); op != e; ++op)
if (TVCodeItem *TCI = ValueToItem[*op])
changeItemTextAttrs (TCI, wxGREEN, wxBOLD);
}
void TVCodeListCtrl::OnItemDeselected(wxListEvent &event) {
Value *V = itemList[event.GetIndex ()]->getValue();
if (!V) return;
// Set uses back to normal
for (User::use_iterator u = V->use_begin(), e = V->use_end(); u != e; ++u)
changeItemTextAttrs (ValueToItem[*u], wxBLACK, wxNORMAL);
// Set definitions of operands back to normal
if (User *U = dyn_cast<User>(V))
for (User::op_iterator op = U->op_begin(), e = U->op_end(); op != e; ++op)
if (TVCodeItem *TCI = ValueToItem[*op])
changeItemTextAttrs (ValueToItem[*op], wxBLACK, wxNORMAL);
}
BEGIN_EVENT_TABLE (TVCodeListCtrl, wxListCtrl)
EVT_LIST_ITEM_SELECTED(LLVM_TV_CODEVIEW_LIST,
TVCodeListCtrl::OnItemSelected)
EVT_LIST_ITEM_DESELECTED(LLVM_TV_CODEVIEW_LIST,
TVCodeListCtrl::OnItemDeselected)
END_EVENT_TABLE ()
//===----------------------------------------------------------------------===//
void TVCodeViewer::displayItem (TVTreeItemData *item) {
item->viewCodeOn (this);
}
void TVCodeViewer::viewFunctionCode (Function *F) {
myListCtrl->SetFunction (F);
}
void TVCodeViewer::viewModuleCode (Module *F) {
myListCtrl->ClearAll();
}