diff options
author | Eugene Tarassov | 2012-07-30 01:11:00 +0000 |
---|---|---|
committer | Eugene Tarassov | 2012-07-30 01:11:00 +0000 |
commit | 4badf4686d9117b8699cd1e8b6dd257cb4234e38 (patch) | |
tree | 853c61ef2dc7ae1aed2167f836acec7d944fc2d4 | |
parent | 012c7d75e53e3100bc16f61c9cadb5ad82f6d05b (diff) | |
download | org.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
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; + } } |