From fc0b5db0a77a6b64d1196aed2ad6670aed28a9cd Mon Sep 17 00:00:00 2001 From: Marco Maccaferri Date: Tue, 5 Feb 2019 10:01:59 +0100 Subject: [PATCH] Refactored debugger source map builder --- src/com/maccasoft/tools/Application.java | 63 +++------- src/com/maccasoft/tools/CodeRuler.java | 23 ++-- src/com/maccasoft/tools/SourceMap.java | 137 ++++++++++++++++++++++ src/com/maccasoft/tools/SourceViewer.java | 20 ++-- 4 files changed, 175 insertions(+), 68 deletions(-) create mode 100644 src/com/maccasoft/tools/SourceMap.java diff --git a/src/com/maccasoft/tools/Application.java b/src/com/maccasoft/tools/Application.java index 31d44df..c2c2188 100644 --- a/src/com/maccasoft/tools/Application.java +++ b/src/com/maccasoft/tools/Application.java @@ -27,10 +27,8 @@ import java.io.Writer; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; -import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicReference; import org.eclipse.core.databinding.observable.Realm; @@ -89,6 +87,7 @@ import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; +import com.maccasoft.tools.SourceMap.LineEntry; import com.maccasoft.tools.editor.Z80TokenMarker; import com.maccasoft.tools.internal.BusyIndicator; import com.maccasoft.tools.internal.ImageRegistry; @@ -134,19 +133,7 @@ public class Application { Z80 proc; MemIoOps memIoOps; - int entryAddress; - - class LineEntry { - int lineNumber; - Line line; - - LineEntry(int lineNumber, Line line) { - this.lineNumber = lineNumber; - this.line = line; - } - } - - Map list; + SourceMap sourceMap; int stepOverPC1; int stepOverPC2; @@ -2518,27 +2505,15 @@ public class Application { }); proc.setBreakpoint(0x0005, true); - list = new HashMap(); - - entryAddress = -1; - - int lineNumber = 0; - for (Line line : source.getLines()) { - int address = line.getScope().getAddress(); - byte[] code = line.getBytes(); - if (code.length != 0 && entryAddress == -1) { - entryAddress = address; - } - System.arraycopy(code, 0, memIoOps.getRam(), address, code.length); - list.put(address, new LineEntry(lineNumber++, line)); - } + sourceMap = new SourceMap(source, memIoOps); + sourceMap.build(); display.syncExec(new Runnable() { @Override public void run() { memory.setData(memIoOps.getRam()); - viewer.setSource(source); + viewer.setSourceMap(sourceMap); handleReset(); reparentControls(); @@ -2613,9 +2588,9 @@ public class Application { proc.setPinReset(); proc.reset(); - proc.setRegPC(entryAddress); + proc.setRegPC(sourceMap.getEntryAddress()); - memory.setSelection(entryAddress); + memory.setSelection(sourceMap.getEntryAddress()); updateDebuggerState(); } @@ -2625,16 +2600,16 @@ public class Application { memory.clearUpdates(); viewer.getControl().setFocus(); - LineEntry lineEntry = list.get(proc.getRegPC()); + LineEntry lineEntry = sourceMap.getLineAtAddress(proc.getRegPC()); if (lineEntry != null) { - stepOverPC1 = proc.getRegPC() + lineEntry.line.getSize(); + stepOverPC1 = proc.getRegPC() + lineEntry.code.length; stepOverPC2 = memIoOps.peek16(proc.getRegSP()); stepOverSP = proc.getRegSP(); boolean repeat = isRepeatInstruction(); proc.execute(); - if (repeat || list.get(proc.getRegPC()) == null) { + if (repeat || sourceMap.getLineAtAddress(proc.getRegPC()) == null) { display.asyncExec(stepOverRunnable); return; } @@ -2670,9 +2645,9 @@ public class Application { memory.clearUpdates(); viewer.getControl().setFocus(); - LineEntry lineEntry = list.get(proc.getRegPC()); + LineEntry lineEntry = sourceMap.getLineAtAddress(proc.getRegPC()); if (lineEntry != null) { - stepOverPC1 = proc.getRegPC() + lineEntry.line.getSize(); + stepOverPC1 = proc.getRegPC() + lineEntry.code.length; stepOverPC2 = memIoOps.peek16(proc.getRegSP()); stepOverSP = proc.getRegSP(); display.asyncExec(stepOverRunnable); @@ -2691,10 +2666,10 @@ public class Application { int caretOffset = viewer.getStyledText().getCaretOffset(); int lineAtOffset = viewer.getStyledText().getLineAtOffset(caretOffset); - Line line = viewer.getSource().getLines().get(lineAtOffset); + LineEntry lineEntry = viewer.getSourceMap().getLines().get(lineAtOffset); - if (line.getScope().getAddress() != proc.getRegPC()) { - stepOverPC1 = line.getScope().getAddress(); + if (lineEntry.address != proc.getRegPC()) { + stepOverPC1 = lineEntry.address; display.asyncExec(runToLineRunnable); } } @@ -2709,9 +2684,9 @@ public class Application { int caretOffset = viewer.getStyledText().getCaretOffset(); int lineAtOffset = viewer.getStyledText().getLineAtOffset(caretOffset); - Line line = viewer.getSource().getLines().get(lineAtOffset); - if (line != null) { - int address = line.getScope().getAddress(); + LineEntry lineEntry = viewer.getSourceMap().getLines().get(lineAtOffset); + if (lineEntry != null) { + int address = lineEntry.address; viewer.toggleBreakpoint(address); proc.setBreakpoint(address, viewer.isBreakpoint(address)); } @@ -2735,7 +2710,7 @@ public class Application { memory.update(); registers.updateRegisters(proc); - LineEntry lineEntry = list.get(proc.getRegPC()); + LineEntry lineEntry = sourceMap.getLineAtAddress(proc.getRegPC()); if (lineEntry != null) { viewer.gotToLineColumn(lineEntry.lineNumber, 0); } diff --git a/src/com/maccasoft/tools/CodeRuler.java b/src/com/maccasoft/tools/CodeRuler.java index 4aa01f6..15f3870 100644 --- a/src/com/maccasoft/tools/CodeRuler.java +++ b/src/com/maccasoft/tools/CodeRuler.java @@ -30,8 +30,7 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.ScrollBar; -import nl.grauw.glass.Line; -import nl.grauw.glass.Source; +import com.maccasoft.tools.SourceMap.LineEntry; public class CodeRuler { @@ -40,7 +39,7 @@ public class CodeRuler { FontMetrics fontMetrics; StyledText text; - Source source; + SourceMap sourceMap; boolean[] breakpoint; int leftMargin; @@ -119,8 +118,8 @@ public class CodeRuler { this.text.addCaretListener(caretListener); } - public void setSource(Source source) { - this.source = source; + public void setSourceMap(SourceMap sourceMap) { + this.sourceMap = sourceMap; } void onPaintControl(GC gc) { @@ -136,18 +135,16 @@ public class CodeRuler { break; } - if (source != null && lineNumber >= 0 && lineNumber < source.getLines().size()) { - Line line = source.getLines().get(lineNumber); - int address = line.getScope().getAddress(); - byte[] code = line.getBytes(); + if (sourceMap != null && lineNumber >= 0 && lineNumber < sourceMap.getLines().size()) { + LineEntry line = sourceMap.getLine(lineNumber); StringBuilder sb = new StringBuilder(); - sb.append(String.format("%04X ", line.getScope().getAddress())); - for (int i = 0; i < code.length; i++) { + sb.append(String.format("%04X ", line.address)); + for (int i = 0; i < line.code.length; i++) { if (i != 0) { sb.append(' '); } - sb.append(String.format("%02X", code[i])); + sb.append(String.format("%02X", line.code[i])); } if (lineNumber == currentLine) { gc.setBackground(currentLineBackground); @@ -156,7 +153,7 @@ public class CodeRuler { else { gc.setBackground(canvas.getBackground()); } - gc.setFont((breakpoint[address] && code.length != 0) ? fontBold : font); + gc.setFont((breakpoint[line.address] && line.code.length != 0) ? fontBold : font); gc.drawString(sb.toString(), leftMargin, y, true); } diff --git a/src/com/maccasoft/tools/SourceMap.java b/src/com/maccasoft/tools/SourceMap.java new file mode 100644 index 0000000..3e4430f --- /dev/null +++ b/src/com/maccasoft/tools/SourceMap.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2018-19 Marco Maccaferri 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 + */ + +package com.maccasoft.tools; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import nl.grauw.glass.AssemblyException; +import nl.grauw.glass.Line; +import nl.grauw.glass.Scope; +import nl.grauw.glass.Source; +import nl.grauw.glass.directives.If; +import z80core.MemIoOps; + +public class SourceMap { + + Source source; + MemIoOps memIoOps; + + int address; + int entryAddress; + + public static class LineEntry { + public final Line line; + public final int lineNumber; + + public final int address; + public final byte[] code; + + public LineEntry(int lineNumber, int address, Line line) { + this.line = line; + this.address = address; + this.lineNumber = lineNumber; + + Scope scope = line.getScope(); + + if (line.getDirective() instanceof If) { + this.code = new byte[0]; + } + else if (scope.isAddressSet()) { + this.code = line.getBytes(); + } + else { + this.code = new byte[0]; + } + } + + } + + Map map; + List list; + + public SourceMap(Source source, MemIoOps memIoOps) { + this.source = source; + this.memIoOps = memIoOps; + } + + public void build() { + address = 0; + entryAddress = -1; + + list = new ArrayList(); + map = new HashMap(); + + build(source, 0); + } + + int build(Source source, int lineNumber) { + for (Line line : source.getLines()) { + try { + if (line.getScope().isAddressSet()) { + address = line.getScope().getAddress(); + } + LineEntry lineEntry = new LineEntry(lineNumber++, address, line); + if (lineEntry.code.length != 0) { + if (entryAddress == -1) { + entryAddress = address; + } + System.arraycopy(lineEntry.code, 0, memIoOps.getRam(), lineEntry.address, lineEntry.code.length); + map.put(lineEntry.address, lineEntry); + } + list.add(lineEntry); + + if (line.getDirective() instanceof If) { + if (line.getInstructionObject() != null) { + nl.grauw.glass.instructions.If ins = (nl.grauw.glass.instructions.If) line.getInstruction(); + lineNumber = build(ins.getThenSource(), lineNumber); + if (ins.getElseSource() != null) { + lineNumber = build(ins.getElseSource(), lineNumber); + } + } + else { + If ins = (If) line.getDirective(); + lineNumber = build(ins.getThenSource(), lineNumber); + if (ins.getElseSource() != null) { + lineNumber = build(ins.getElseSource(), lineNumber); + } + } + } + } catch (AssemblyException e) { + e.addContext(line); + throw e; + } catch (Exception e) { + e.printStackTrace(); + } + } + + return lineNumber; + } + + public int getEntryAddress() { + return entryAddress; + } + + public LineEntry getLineAtAddress(int address) { + return map.get(address); + } + + public List getLines() { + return list; + } + + public LineEntry getLine(int lineNumber) { + return list.get(lineNumber); + } + +} diff --git a/src/com/maccasoft/tools/SourceViewer.java b/src/com/maccasoft/tools/SourceViewer.java index 7cba6ef..c54bb9d 100644 --- a/src/com/maccasoft/tools/SourceViewer.java +++ b/src/com/maccasoft/tools/SourceViewer.java @@ -38,15 +38,13 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; +import com.maccasoft.tools.SourceMap.LineEntry; import com.maccasoft.tools.editor.EditorUtil; import com.maccasoft.tools.editor.LineNumbersRuler; import com.maccasoft.tools.editor.Token; import com.maccasoft.tools.editor.TokenId; import com.maccasoft.tools.editor.TokenMarker; -import nl.grauw.glass.Line; -import nl.grauw.glass.Source; - public class SourceViewer { Composite container; @@ -62,7 +60,7 @@ public class SourceViewer { private Font fontBold; private Map styleMap = new HashMap(); - Source source; + SourceMap sourceMap; boolean showLineNumbers = true; @@ -183,21 +181,21 @@ public class SourceViewer { return text; } - public Source getSource() { - return source; + public SourceMap getSourceMap() { + return sourceMap; } - public void setSource(Source source) { - this.source = source; + public void setSourceMap(SourceMap sourceMap) { + this.sourceMap = sourceMap; StringBuilder sb = new StringBuilder(); - for (Line line : source.getLines()) { - sb.append(line.getSourceText()); + for (LineEntry lineEntry : sourceMap.getLines()) { + sb.append(lineEntry.line.getSourceText()); sb.append("\r\n"); } String text = sb.toString(); - codeRuler.setSource(source); + codeRuler.setSourceMap(sourceMap); currentLine = 0; this.text.setText(text);