blob: 869e8a17ceacf2556437179b0c4f0264f155e0ea [file] [log] [blame]
/*
* LLBrowseFrame.cpp
*/
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/IRReader.h"
#include "llvm/Support/raw_ostream.h"
#include "llbrowse/BrowserFrame.h"
#include "llbrowse/BrowserApp.h"
#include "llbrowse/TreeView.h"
#include "llbrowse/DetailsView.h"
#include "llbrowse/Resources.h"
#include "wx/wfstream.h"
#include "wx/imaglist.h"
using namespace llvm;
BrowserFrame::BrowserFrame(
const wxString& title, const wxPoint& pos, const wxSize& size)
: wxFrame(NULL, -1, title, pos, size)
, context_(getGlobalContext())
{
CreateMenus();
CreateStatusBar();
CreatePanels();
SetStatusText(_("No module loaded"));
fileDialog_ = new wxFileDialog(this, _("Open LLVM module"),
wxString(), wxString(),
wxString::FromAscii("LLVM IR files (*.bc;*.ll)|*.bc;*.ll"),
wxFD_OPEN | wxFD_FILE_MUST_EXIST);
Show(true);
}
BrowserFrame::~BrowserFrame() {
delete fileDialog_;
}
void BrowserFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) {
Close(true);
}
void BrowserFrame::OnOpen(wxCommandEvent& WXUNUSED(event)) {
if (fileDialog_->ShowModal() == wxID_OK) {
// Load the module.
LoadModule(fileDialog_->GetPath());
}
}
void BrowserFrame::CreateMenus() {
// File menu
wxMenu* menuFile = new wxMenu();
menuFile->Append(wxID_OPEN, _("&Open..."));
menuFile->AppendSeparator();
menuFile->Append(wxID_ABOUT, _("&About..."));
menuFile->AppendSeparator();
menuFile->Append(wxID_EXIT, _("E&xit"));
Connect(wxID_OPEN, wxEVT_COMMAND_MENU_SELECTED,
(wxObjectEventFunction) (&BrowserFrame::OnOpen));
Connect(wxID_ABOUT, wxEVT_COMMAND_MENU_SELECTED,
(wxObjectEventFunction) (&BrowserFrame::OnAbout));
Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
(wxObjectEventFunction) (&BrowserFrame::OnQuit));
// View menu
// wxMenu* menuView = new wxMenu();
// menuFile->Append(ID_SORT_FUNCTION_NAMES, _("Sort &Functions by name"));
// menuFile->Append(ID_SORT_VARIABLE_NAMES, _("Sort &Variables by name"));
// Menu bar
wxMenuBar* menuBar = new wxMenuBar();
menuBar->Append(menuFile, _("&File"));
// menuBar->Append(menuView, _("&View"));
SetMenuBar(menuBar);
}
void BrowserFrame::CreatePanels() {
splitter_ = new wxSplitterWindow(this);
tree_ = new TreeView(splitter_);
tree_->SetWindowStyleFlag(wxTR_HAS_BUTTONS);
tree_->SetButtonsImageList(Resources::GetTreeListButtonList());
tree_->SetImageList(Resources::GetTreeListIconList());
details_ = new DetailsView(splitter_);
splitter_->Initialize(tree_);
splitter_->SplitVertically(tree_, details_);
Connect(tree_->GetId(), wxEVT_COMMAND_TREE_ITEM_EXPANDING,
(wxObjectEventFunction) &BrowserFrame::OnTreeItemExpanding);
Connect(tree_->GetId(), wxEVT_COMMAND_TREE_SEL_CHANGED,
(wxObjectEventFunction) &BrowserFrame::OnTreeSelChanged);
}
void BrowserFrame::LoadModule(const wxString & path) {
wxFileInputStream inStream(path);
if (!inStream.IsOk()) {
// TODO: Report error
return;
}
SMDiagnostic err;
std::auto_ptr<Module> mod;
OwningPtr<MemoryBuffer> buffer;
buffer.reset(MemoryBuffer::getNewUninitMemBuffer(inStream.GetSize(), ""));
inStream.Read((void *) buffer->getBufferStart(), buffer->getBufferSize());
if (!inStream.IsOk()) {
// TODO: Report error
return;
}
mod.reset(ParseIR(buffer.take(), err, context_));
if (mod.get() == 0) {
std::string errs;
raw_string_ostream errStrm(errs);
err.Print("llbrowse", errStrm);
wxString errString = wxString::From8BitData(&*errs.begin(), errs.size());
// Show error dialog.
//return 1;
}
module_.reset(mod.release());
lastLoadDir_ = fileDialog_->GetDirectory();
BuildTree();
}
void BrowserFrame::BuildTree() {
wxString rootName(_("Module - "));
const std::string & moduleName = module_->getModuleIdentifier();
if (!moduleName.empty()) {
rootName.Append(
wxString::From8BitData(&*moduleName.begin(), moduleName.size()));
}
tree_->SetModule(module_.get(), rootName);
TreeItemBase* treeItem =
static_cast<TreeItemBase*>(tree_->GetItemData(tree_->GetRootItem()));
ShowItemDetails(treeItem);
}
void BrowserFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) {
wxMessageBox(_("Visual browser for LLVM .bc files"),
_("About LLBrowse"),
wxOK | wxICON_INFORMATION, this);
}
void BrowserFrame::OnTreeItemExpanding(wxTreeEvent& event) {
const wxTreeItemId item = event.GetItem();
// Don't add items if folder already expanded.
if (tree_->GetChildrenCount(item) > 0) {
return;
}
TreeItemBase* treeItem =
static_cast<TreeItemBase*>(tree_->GetItemData(item));
treeItem->CreateChildren(tree_, item);
}
void BrowserFrame::OnTreeSelChanged(wxTreeEvent& event) {
const wxTreeItemId item = event.GetItem();
TreeItemBase* treeItem =
static_cast<TreeItemBase*>(tree_->GetItemData(item));
ShowItemDetails(treeItem);
}
void BrowserFrame::ShowItemDetails(TreeItemBase* treeItem) {
details_->DeleteAllItems();
treeItem->ShowDetails(details_);
details_->SetColumnWidth(0, wxLIST_AUTOSIZE);
details_->SetColumnWidth(1, wxLIST_AUTOSIZE);
}
bool BrowserFrame::Destroy() {
wxGetApp().SavePrefs();
return wxFrame::Destroy();
}
void BrowserFrame::SetCurrentDir(wxString & dir) {
lastLoadDir_ = dir;
fileDialog_->SetDirectory(dir);
}
wxString BrowserFrame::GetCurrentDir() {
return lastLoadDir_;
}