Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2012-07-30 01:11:00 +0000
committerEugene Tarassov2012-07-30 01:11:00 +0000
commit4badf4686d9117b8699cd1e8b6dd257cb4234e38 (patch)
tree853c61ef2dc7ae1aed2167f836acec7d944fc2d4
parent012c7d75e53e3100bc16f61c9cadb5ad82f6d05b (diff)
downloadorg.eclipse.tcf-4badf4686d9117b8699cd1e8b6dd257cb4234e38.tar.gz
org.eclipse.tcf-4badf4686d9117b8699cd1e8b6dd257cb4234e38.tar.xz
org.eclipse.tcf-4badf4686d9117b8699cd1e8b6dd257cb4234e38.zip
Bug 385917 - [PATCH] Improve display of XMM vector registers
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/plugin.properties2
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/plugin.xml13
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RegisterVectorDisplayMenu.java262
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java4
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModelProxy.java4
-rw-r--r--plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeRegister.java81
6 files changed, 359 insertions, 7 deletions
diff --git a/plugins/org.eclipse.tcf.debug.ui/plugin.properties b/plugins/org.eclipse.tcf.debug.ui/plugin.properties
index bbf802572..e10047f90 100644
--- a/plugins/org.eclipse.tcf.debug.ui/plugin.properties
+++ b/plugins/org.eclipse.tcf.debug.ui/plugin.properties
@@ -56,4 +56,6 @@ BackResume.label=Run Backwards
BackResume.tooltip=Run Backwards
BackResume.description=Run backwards
+RegisterVectorDisplay.label = Display Register As Vector Of...
+
propertyPage.name = Debug Element \ No newline at end of file
diff --git a/plugins/org.eclipse.tcf.debug.ui/plugin.xml b/plugins/org.eclipse.tcf.debug.ui/plugin.xml
index d10b17f3f..e0996765d 100644
--- a/plugins/org.eclipse.tcf.debug.ui/plugin.xml
+++ b/plugins/org.eclipse.tcf.debug.ui/plugin.xml
@@ -620,6 +620,19 @@
class="org.eclipse.tcf.internal.debug.ui.commands.UpdatePolicyMenu"/>
</menu>
</menuContribution>
+ <menuContribution
+ locationURI="popup:org.eclipse.debug.ui.RegisterView?after=additions">
+ <menu
+ label="%RegisterVectorDisplay.label">
+ <dynamic
+ class="org.eclipse.tcf.internal.debug.ui.commands.RegisterVectorDisplayMenu"
+ id="org.eclipse.tcf.debug.ui.RegisterVectorDisplayMenu">
+ </dynamic>
+ <visibleWhen
+ checkEnabled="true">
+ </visibleWhen>
+ </menu>
+ </menuContribution>
</extension>
<extension
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RegisterVectorDisplayMenu.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RegisterVectorDisplayMenu.java
new file mode 100644
index 000000000..76bc2dac1
--- /dev/null
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/commands/RegisterVectorDisplayMenu.java
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tcf.internal.debug.ui.commands;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ITreeModelViewer;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.IDebugView;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.tcf.internal.debug.ui.model.TCFChildren;
+import org.eclipse.tcf.internal.debug.ui.model.TCFModelProxy;
+import org.eclipse.tcf.internal.debug.ui.model.TCFNode;
+import org.eclipse.tcf.internal.debug.ui.model.TCFNodeExecContext;
+import org.eclipse.tcf.internal.debug.ui.model.TCFNodeRegister;
+import org.eclipse.tcf.internal.debug.ui.model.TCFNodeStackFrame;
+import org.eclipse.tcf.services.IRegisters;
+import org.eclipse.tcf.util.TCFTask;
+import org.eclipse.ui.IPartService;
+import org.eclipse.ui.ISelectionService;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.actions.CompoundContributionItem;
+import org.eclipse.ui.menus.IWorkbenchContribution;
+import org.eclipse.ui.services.IServiceLocator;
+
+public class RegisterVectorDisplayMenu extends CompoundContributionItem implements IWorkbenchContribution {
+
+ private static final int MAX_REG_REPRESENTATIONS = 100;
+
+ private IServiceLocator service_locator;
+ private ArrayList<String> elements;
+ private Map<String,Map<String,String>> modes;
+
+ @Override
+ public void initialize(IServiceLocator service_locator) {
+ this.service_locator = service_locator;
+ }
+
+ private Object[] getSelectedRegisters() {
+ ISelectionService service = (ISelectionService) service_locator.getService(ISelectionService.class);
+ if (service != null) {
+ ISelection selection = service.getSelection();
+ if (selection instanceof IStructuredSelection) {
+ return ((IStructuredSelection)selection).toArray();
+ }
+ }
+ return new Object[0];
+ }
+
+ @Override
+ protected IContributionItem[] getContributionItems() {
+ final IWorkbenchPart part = getPart();
+ if (part == null) return null;
+
+ final Object[] selection = getSelectedRegisters();
+
+ final TCFNode node = getRootNode(part);
+ if (node == null) return null;
+ if (!(node instanceof TCFNodeExecContext) && !(node instanceof TCFNodeStackFrame)) return null;
+
+ IContributionItem[] items = new TCFTask<IContributionItem[]>(node.getChannel()) {
+ public void run() {
+
+ modes = new LinkedHashMap<String,Map<String,String>>();
+
+ for (Object obj : selection) {
+ if (obj instanceof TCFNodeRegister) {
+ TCFNodeRegister reg = (TCFNodeRegister)obj;
+
+ AtomicBoolean grp = new AtomicBoolean();
+ if (!reg.isRepresentationGroup(grp, this)) return;
+ if (!grp.get()) continue;
+
+ TCFChildren children = reg.getChildren();
+ if (!children.validate(this)) return;
+ for (TCFNode child_node : children.toArray()) {
+ TCFNodeRegister child_reg = (TCFNodeRegister)child_node;
+ if (!child_reg.getContext().validate(this)) return;
+ IRegisters.RegistersContext child_ctx = child_reg.getContext().getData();
+ String reg_name = child_ctx.getName();
+ if (reg_name.matches("w[0-9]+")) {
+ String mode = reg_name.substring(1, reg_name.length()) + "bits";
+ Map<String,String> map = modes.get(mode);
+ if (map == null) modes.put(mode, map = new HashMap<String,String>());
+ map.put(reg.getID(), child_ctx.getID());
+ }
+ }
+ }
+ }
+
+ // if several registers are selected in the register view, we need to show only the common possibilities
+ for (Iterator<Map<String,String>> i = modes.values().iterator(); i.hasNext();) {
+ Map<String,String> map = i.next();
+ for (Object obj : selection) {
+ if (!(obj instanceof TCFNodeRegister)) continue;
+ if (map.containsKey(((TCFNodeRegister)obj).getID())) continue;
+ i.remove();
+ break;
+ }
+ }
+
+ elements = new ArrayList<String>(modes.keySet());
+ elements.add(0, elements.size() == 0 ? "No vector display options available" : "none");
+
+ IContributionItem[] items = new IContributionItem[elements.size()];
+ for (int i = 0; i < items.length; i++) {
+ final int n = i;
+ items[i] = new ContributionItem() {
+ @Override
+ public void fill(final Menu menu, int index) {
+ final MenuItem item = new MenuItem(menu, elements.size() <= 1 ? SWT.NULL : SWT.RADIO);
+ item.setText(elements.get(n));
+ item.setSelection(getRepresentation() == n);
+ item.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ if (item.getSelection()) setRepresentation(n);
+ }
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+ });
+ }
+ };
+ }
+ done(items);
+ }
+ }.getE();
+
+ return (items);
+ }
+
+ private IWorkbenchPart getPart() {
+ IPartService partService = (IPartService)service_locator.getService(IPartService.class);
+ if (partService != null) return partService.getActivePart();
+ return null;
+ }
+
+ private TCFNode getRootNode(IWorkbenchPart part) {
+ IWorkbenchPartSite site = part.getSite();
+ if (site == null || IDebugUIConstants.ID_DEBUG_VIEW.equals(site.getId())) {
+ return null;
+ }
+ if (part instanceof IDebugView) {
+ Object input = ((IDebugView)part).getViewer().getInput();
+ if (input instanceof TCFNode) return (TCFNode)input;
+ }
+ return null;
+ }
+
+ private ITreeModelViewer getViewer() {
+ IWorkbenchPart part = getPart();
+
+ if (part instanceof IDebugView) {
+ return (ITreeModelViewer)((IDebugView)part).getViewer();
+ }
+ return null;
+ }
+
+ private int getRepresentation() {
+ IWorkbenchPart part = getPart();
+ if (part == null) return 0;
+ TCFNodeRegister node = null;
+ for (Object obj : getSelectedRegisters()) {
+ if (obj instanceof TCFNodeRegister) {
+ node = (TCFNodeRegister)obj;
+ break;
+ }
+ }
+ if (node == null) return 0;
+ final String id = node.getID();
+ final IPresentationContext ctx = getViewer().getPresentationContext();
+ return new TCFTask<Integer>(node.getChannel()) {
+ @SuppressWarnings("unchecked")
+ public void run() {
+ Map<String,String> representation = (Map<String,String>)ctx.getProperty(
+ TCFNodeRegister.PROPERTY_REG_REPRESENTATION);
+ if (representation != null) {
+ String rep_id = representation.get(id);
+ if (rep_id != null) {
+ for (Map.Entry<String,Map<String,String>> e : modes.entrySet()) {
+ if (rep_id.equals(e.getValue().get(id))) {
+ done(elements.indexOf(e.getKey()));
+ return;
+ }
+ }
+ }
+ }
+ done(0);
+ }
+ }.getE();
+ }
+
+ private void setRepresentation(final int n) {
+ final IWorkbenchPart part = getPart();
+ if (part == null) return;
+ final TCFNode node = getRootNode(part);
+ if (node == null) return;
+
+ final Object[] selection = getSelectedRegisters();
+ ITreeModelViewer viewer = getViewer();
+ final IPresentationContext ctx = viewer.getPresentationContext();
+ new TCFTask<Object>(node.getChannel()) {
+ @SuppressWarnings({ "unchecked", "serial" })
+ public void run() {
+
+ Map<String,String> representation = (Map<String,String>)ctx.getProperty(
+ TCFNodeRegister.PROPERTY_REG_REPRESENTATION);
+
+ if (representation == null) {
+ representation = new LinkedHashMap<String,String>() {
+ @Override
+ protected boolean removeEldestEntry(Map.Entry<String,String> eldest) {
+ return size() > MAX_REG_REPRESENTATIONS;
+ }
+ };
+ ctx.setProperty(TCFNodeRegister.PROPERTY_REG_REPRESENTATION, representation);
+ }
+
+ Map<String,String> map = modes.get(elements.get(n));
+ TCFModelProxy proxy = node.getModel().getModelProxy(ctx);
+ for (Object obj : selection) {
+ if (obj instanceof TCFNodeRegister) {
+ TCFNodeRegister reg = (TCFNodeRegister)obj;
+ String id = reg.getID();
+ String rep_id = map != null ? map.get(id) : null;
+ if (rep_id == null) representation.remove(id);
+ else representation.put(id, rep_id);
+ if (proxy != null) {
+ proxy.addDelta(reg, IModelDelta.CONTENT);
+ TCFNode n = node.getModel().getNode(rep_id);
+ if (n != null) proxy.expand(n);
+ }
+ }
+ }
+ done(null);
+ }
+ };
+ }
+}
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java
index 07bc265a8..e88c5c58b 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModel.java
@@ -948,6 +948,10 @@ public class TCFModel implements IElementContentProvider, IElementLabelProvider,
}
}
+ public TCFModelProxy getModelProxy(IPresentationContext ctx) {
+ return model_proxies.get(ctx);
+ }
+
Collection<TCFModelProxy> getModelProxies() {
return model_proxies.values();
}
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModelProxy.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModelProxy.java
index 28bd010ca..ee5e27a69 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModelProxy.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFModelProxy.java
@@ -235,7 +235,7 @@ public class TCFModelProxy extends AbstractModelProxy implements IModelProxy, Ru
* @param node - a model node that changed.
* @param flags - flags that describe the change, see IModelDelta
*/
- void addDelta(TCFNode node, int flags) {
+ public void addDelta(TCFNode node, int flags) {
assert Protocol.isDispatchThread();
assert installed && !disposed;
if (flags == 0) return;
@@ -249,7 +249,7 @@ public class TCFModelProxy extends AbstractModelProxy implements IModelProxy, Ru
* Request node to be expanded in the view.
* @param node - a model node that will become expanded.
*/
- void expand(TCFNode node) {
+ public void expand(TCFNode node) {
Object input = getInput();
IPresentationContext ctx = getPresentationContext();
while (node != null && node != input) {
diff --git a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeRegister.java b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeRegister.java
index 86bc55552..015e90761 100644
--- a/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeRegister.java
+++ b/plugins/org.eclipse.tcf.debug.ui/src/org/eclipse/tcf/internal/debug/ui/model/TCFNodeRegister.java
@@ -13,6 +13,10 @@ package org.eclipse.tcf.internal.debug.ui.model;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
@@ -39,6 +43,8 @@ import org.eclipse.tcf.util.TCFTask;
public class TCFNodeRegister extends TCFNode implements IElementEditor, IWatchInExpressions, IDetailsProvider {
+ public static final String PROPERTY_REG_REPRESENTATION = "PROPERTY_REGISTER_REPRESENTATION";
+
private final TCFChildrenRegisters children;
private final TCFData<IRegisters.RegistersContext> context;
private final TCFData<String> expression_text;
@@ -260,23 +266,49 @@ public class TCFNodeRegister extends TCFNode implements IElementEditor, IWatchIn
return true;
}
+ @SuppressWarnings("unchecked")
+ private boolean getChildren(IPresentationContext ctx, List<TCFNode> list, Runnable done) {
+ AtomicBoolean b = new AtomicBoolean();
+ if (!isRepresentationGroup(b, done)) return false;
+ boolean rep_group = b.get();
+ String rep_id = null;
+ if (rep_group) {
+ Map<String,String> map = (Map<String,String>)ctx.getProperty(
+ TCFNodeRegister.PROPERTY_REG_REPRESENTATION);
+ if (map != null) rep_id = map.get(id);
+ }
+ for (TCFNode child : children.toArray()) {
+ if (!rep_group || child.id.equals(rep_id)) list.add(child);
+ }
+ return true;
+ }
+
@Override
protected boolean getData(IHasChildrenUpdate result, Runnable done) {
- if (!children.validate(done)) return false;
- result.setHasChilren(children.size() > 0);
+ List<TCFNode> list = new ArrayList<TCFNode>();
+ if (!getChildren(result.getPresentationContext(), list, done)) return false;
+ result.setHasChilren(list.size() > 0);
return true;
}
@Override
protected boolean getData(IChildrenCountUpdate result, Runnable done) {
- if (!children.validate(done)) return false;
- result.setChildCount(children.size());
+ List<TCFNode> list = new ArrayList<TCFNode>();
+ if (!getChildren(result.getPresentationContext(), list, done)) return false;
+ result.setChildCount(list.size());
return true;
}
@Override
protected boolean getData(IChildrenUpdate result, Runnable done) {
- return children.getData(result, done);
+ List<TCFNode> list = new ArrayList<TCFNode>();
+ if (!getChildren(result.getPresentationContext(), list, done)) return false;
+ int r_offset = result.getOffset();
+ int r_length = result.getLength();
+ for (int n = r_offset; n < r_offset + r_length && n < list.size(); n++) {
+ result.setChild(list.get(n), n);
+ }
+ return true;
}
@Override
@@ -652,4 +684,43 @@ public class TCFNodeRegister extends TCFNode implements IElementEditor, IWatchIn
}
return id.compareTo(n.id);
}
+
+ /**
+ * Check if this register has multiple representations.
+ */
+ public boolean isRepresentationGroup(AtomicBoolean res, Runnable done) {
+ res.set(false);
+ HashSet<Integer> offsets = new HashSet<Integer>();
+ if (!children.validate(done)) return false;
+ for (TCFNode child_node : children.toArray()) {
+ TCFNodeRegister child_reg = (TCFNodeRegister)child_node;
+ if (!child_reg.context.validate(done)) return false;
+ IRegisters.RegistersContext ctx = child_reg.context.getData();
+ if (ctx == null) continue;
+ int offs = ctx.getOffset();
+ if (offs >= 0) {
+ if (!offsets.add(Integer.valueOf(offs))) {
+ res.set(true);
+ return true;
+ }
+ continue;
+ }
+ // TODO: checking grand children should not be needed
+ if (!child_reg.children.validate(done)) return false;
+ for (TCFNode grand_child_node : child_reg.children.toArray()) {
+ TCFNodeRegister grand_child_reg = (TCFNodeRegister)grand_child_node;
+ if (!grand_child_reg.context.validate(done)) return false;
+ ctx = grand_child_reg.context.getData();
+ if (ctx == null) continue;
+ offs = ctx.getOffset();
+ if (offs >= 0) {
+ if (!offsets.add(Integer.valueOf(offs))) {
+ res.set(true);
+ return true;
+ }
+ }
+ }
+ }
+ return true;
+ }
}

Back to the top