1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-10-21 17:24:39 +00:00

Added command line switches for adding comments containing source file information to the ASM. Closes #215

This commit is contained in:
jespergravgaard 2019-07-08 11:32:07 +02:00
parent 5061a02a17
commit f2f144c3ee
7 changed files with 153 additions and 36 deletions

View File

@ -1,5 +1,6 @@
package dk.camelot64.kickc; package dk.camelot64.kickc;
import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.model.Comment; import dk.camelot64.kickc.model.Comment;
import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.Program; import dk.camelot64.kickc.model.Program;
@ -482,7 +483,7 @@ public class Compiler {
new Pass4CodeGeneration(program, false).generate(); new Pass4CodeGeneration(program, false).generate();
new Pass4AssertNoCpuClobber(program).check(); new Pass4AssertNoCpuClobber(program).check();
getLog().append("\nINITIAL ASM"); getLog().append("\nINITIAL ASM");
getLog().append(program.getAsm().toString()); getLog().append(program.getAsm().toString(new AsmProgram.AsmPrintState(true, false), program));
// Find potential registers for each live range equivalence class - based on clobbering of fragments // Find potential registers for each live range equivalence class - based on clobbering of fragments
getLog().append("REGISTER UPLIFT POTENTIAL REGISTERS"); getLog().append("REGISTER UPLIFT POTENTIAL REGISTERS");
@ -530,7 +531,7 @@ public class Compiler {
new Pass4InterruptClobberFix(program).fix(); new Pass4InterruptClobberFix(program).fix();
getLog().append("\nASSEMBLER BEFORE OPTIMIZATION"); getLog().append("\nASSEMBLER BEFORE OPTIMIZATION");
getLog().append(program.getAsm().toString()); getLog().append(program.getAsm().toString(new AsmProgram.AsmPrintState(true, false), program));
getLog().append("ASSEMBLER OPTIMIZATIONS"); getLog().append("ASSEMBLER OPTIMIZATIONS");
List<Pass5AsmOptimization> pass5Optimizations = new ArrayList<>(); List<Pass5AsmOptimization> pass5Optimizations = new ArrayList<>();
@ -568,7 +569,7 @@ public class Compiler {
getLog().append("\nFINAL ASSEMBLER"); getLog().append("\nFINAL ASSEMBLER");
getLog().append("Score: " + Pass4RegisterUpliftCombinations.getAsmScore(program) + "\n"); getLog().append("Score: " + Pass4RegisterUpliftCombinations.getAsmScore(program) + "\n");
getLog().append(program.getAsm().toString()); getLog().append(program.getAsm().toString(new AsmProgram.AsmPrintState(true, false), program));
} }

View File

@ -1,5 +1,6 @@
package dk.camelot64.kickc; package dk.camelot64.kickc;
import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.fragment.AsmFragmentTemplate; import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer; import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages; import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
@ -96,6 +97,16 @@ public class KickC implements Callable<Void> {
@CommandLine.Option(names = {"-fragment" }, description = "Print the ASM code for a named fragment. The fragment is loaded/synthesized and the ASM variations are written to the output.") @CommandLine.Option(names = {"-fragment" }, description = "Print the ASM code for a named fragment. The fragment is loaded/synthesized and the ASM variations are written to the output.")
private String fragment = null; private String fragment = null;
@CommandLine.Option(names = {"-S", "-Sc" }, description = "Interleave comments with C source code in the generated ASM.")
private boolean interleaveSourceCode = false;
@CommandLine.Option(names = {"-Sl" }, description = "Interleave comments with C source file name and line number in the generated ASM.")
private boolean interleaveSourceFile = false;
@CommandLine.Option(names = {"-Si" }, description = "Interleave comments with intermediate language code and ASM fragment names in the generated ASM.")
private boolean interleaveIclFile = false;
/** Program Exit Code signaling a compile error. */ /** Program Exit Code signaling a compile error. */
public static final int COMPILE_ERROR = 1; public static final int COMPILE_ERROR = 1;
@ -180,7 +191,7 @@ public class KickC implements Callable<Void> {
System.out.println("Writing asm file " + asmPath); System.out.println("Writing asm file " + asmPath);
FileOutputStream asmOutputStream = new FileOutputStream(asmPath.toFile()); FileOutputStream asmOutputStream = new FileOutputStream(asmPath.toFile());
OutputStreamWriter asmWriter = new OutputStreamWriter(asmOutputStream); OutputStreamWriter asmWriter = new OutputStreamWriter(asmOutputStream);
String asmCodeString = program.getAsm().toString(false); String asmCodeString = program.getAsm().toString(new AsmProgram.AsmPrintState(interleaveSourceFile, interleaveSourceCode, interleaveIclFile, false), program);
asmWriter.write(asmCodeString); asmWriter.write(asmCodeString);
asmWriter.close(); asmWriter.close();
asmOutputStream.close(); asmOutputStream.close();

View File

@ -1,6 +1,7 @@
package dk.camelot64.kickc.asm; package dk.camelot64.kickc.asm;
import dk.camelot64.kickc.fragment.AsmFormat; import dk.camelot64.kickc.fragment.AsmFormat;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.values.ScopeRef; import dk.camelot64.kickc.model.values.ScopeRef;
import java.util.ArrayList; import java.util.ArrayList;
@ -196,26 +197,17 @@ public class AsmProgram {
return clobber; return clobber;
} }
public String toString(boolean comments) { public String toString(AsmPrintState printState, Program program) {
return toString(new AsmPrintState(comments, false));
}
public String toString(boolean comments, boolean lineIdx) {
return toString(new AsmPrintState(comments, lineIdx));
}
public String toString(AsmPrintState printState) {
StringBuilder out = new StringBuilder(); StringBuilder out = new StringBuilder();
for(AsmSegment segment : segments) { for(AsmSegment segment : segments) {
out.append(segment.toString(printState)); out.append(segment.toString(printState, program));
} }
return out.toString(); return out.toString();
} }
@Override @Override
public String toString() { public String toString() {
return toString(true); return toString(new AsmPrintState(false, false), null);
} }
/** /**
@ -242,19 +234,61 @@ public class AsmProgram {
return null; return null;
} }
static class AsmPrintState { public static class AsmPrintState {
boolean comments; // Output comments with information about the file/line number in the source file
boolean lineIdx; private boolean sourceFileInfo;
String indent; // Output comments with C-source from the source file
private boolean sourceCodeInfo;
// Output comments with ICL-code and the ASM fragment name
private boolean sourceIclInfo;
// Output segment ID in the ICL-comment
private boolean sourceSegmentIdInfo;
// Output ASM line numbers
private boolean lineIdx;
// Current indent - used during printing
private String indent;
public AsmPrintState(boolean comments, boolean lineIdx) { public AsmPrintState(boolean sourceFileInfo, boolean sourceCodeInfo, boolean sourceIclInfo, boolean lineIdx) {
this.comments = comments; this.sourceFileInfo = sourceFileInfo;
this.sourceCodeInfo = sourceCodeInfo;
this.sourceIclInfo = sourceIclInfo;
this.lineIdx = lineIdx; this.lineIdx = lineIdx;
this.indent = ""; this.indent = "";
} }
public boolean isComments() { public AsmPrintState(boolean sourceIclInfo, boolean lineIdx) {
return comments; this.sourceIclInfo = sourceIclInfo;
this.sourceSegmentIdInfo = sourceIclInfo;
this.lineIdx = lineIdx;
this.indent = "";
}
public boolean isSourceCodeInfo() {
return sourceCodeInfo;
}
public void setSourceCodeInfo(boolean sourceCodeInfo) {
this.sourceCodeInfo = sourceCodeInfo;
}
public boolean isSourceFileInfo() {
return sourceFileInfo;
}
public void setSourceFileInfo(boolean sourceFileInfo) {
this.sourceFileInfo = sourceFileInfo;
}
public boolean isSourceIclInfo() {
return sourceIclInfo;
}
public boolean isSourceSegmentIdInfo() {
return sourceSegmentIdInfo;
}
public void setSourceSegmentIdInfo(boolean sourceSegmentIdInfo) {
this.sourceSegmentIdInfo = sourceSegmentIdInfo;
} }
public void incIndent() { public void incIndent() {

View File

@ -1,6 +1,9 @@
package dk.camelot64.kickc.asm; package dk.camelot64.kickc.asm;
import dk.camelot64.kickc.model.PhiTransitions; import dk.camelot64.kickc.model.PhiTransitions;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementSource;
import dk.camelot64.kickc.model.values.ScopeRef; import dk.camelot64.kickc.model.values.ScopeRef;
import java.util.ArrayList; import java.util.ArrayList;
@ -77,6 +80,7 @@ public class AsmSegment {
/** /**
* Add a new line just after another line * Add a new line just after another line
*
* @param line The line to look for. If it is not found an Exception is thrown * @param line The line to look for. If it is not found an Exception is thrown
* @param add The line to add * @param add The line to add
*/ */
@ -89,7 +93,7 @@ public class AsmSegment {
return; return;
} }
} }
throw new NoSuchElementException("Item not found "+line); throw new NoSuchElementException("Item not found " + line);
} }
public int getIndex() { public int getIndex() {
@ -163,7 +167,7 @@ public class AsmSegment {
* @return The registers clobbered * @return The registers clobbered
*/ */
public AsmClobber getClobber() { public AsmClobber getClobber() {
if(clobberOverwrite!=null) { if(clobberOverwrite != null) {
return clobberOverwrite; return clobberOverwrite;
} }
AsmClobber clobber = new AsmClobber(); AsmClobber clobber = new AsmClobber();
@ -180,6 +184,7 @@ public class AsmSegment {
/** /**
* Get ASM line by index * Get ASM line by index
*
* @param idx The index of the line to get * @param idx The index of the line to get
* @return The line with the passed index. Null if not found inside the segment. * @return The line with the passed index. Null if not found inside the segment.
*/ */
@ -192,11 +197,48 @@ public class AsmSegment {
return null; return null;
} }
public String toString(AsmProgram.AsmPrintState printState, Program program) {
public String toString(AsmProgram.AsmPrintState printState) {
StringBuffer out = new StringBuffer(); StringBuffer out = new StringBuffer();
if(printState.isComments()) { if(printState.isSourceFileInfo()) {
out.append(printState.getIndent()).append("//SEG").append(getIndex()); if(this.statementIdx != null && program != null) {
Statement statement = program.getGraph().getStatementByIndex(this.statementIdx);
if(statement != null) {
StatementSource source = statement.getSource();
if(source != null) {
if(source.getFile() != null || source.getLineNumber() != null) {
out.append(printState.getIndent()).append("// ");
if(source.getFile() != null)
out.append(source.getFile());
out.append(":");
if(source.getLineNumber() != null)
out.append(source.getLineNumber());
out.append("\n");
}
}
}
}
}
if(printState.isSourceCodeInfo()) {
if(this.statementIdx != null && program != null) {
Statement statement = program.getGraph().getStatementByIndex(this.statementIdx);
if(statement != null) {
StatementSource source = statement.getSource();
if(source != null) {
if(source.getCode() != null) {
out.append(printState.getIndent()).append("// ");
if(source.getCode() != null)
out.append(source.getCode().replace("\n", "\n" + printState.getIndent() + "// "));
out.append("\n");
}
}
}
}
}
if(printState.isSourceIclInfo()) {
out.append(printState.getIndent()).append("//");
if(printState.isSourceSegmentIdInfo()) {
out.append("SEG").append(getIndex());
}
if(source != null) { if(source != null) {
out.append(" ").append(source.replace('\r', ' ').replace('\n', ' ')); out.append(" ").append(source.replace('\r', ' ').replace('\n', ' '));
} }
@ -219,7 +261,7 @@ public class AsmSegment {
printState.decIndent(); printState.decIndent();
} }
if(printState.getLineIdx()) { if(printState.getLineIdx()) {
out.append("["+line.getIndex()+"]"); out.append("[" + line.getIndex() + "]");
} }
out.append(printState.getIndent()); out.append(printState.getIndent());
if(shouldIndentAsm(line)) { if(shouldIndentAsm(line)) {
@ -227,7 +269,7 @@ public class AsmSegment {
} }
if(line instanceof AsmComment) { if(line instanceof AsmComment) {
// Peek forward to find the comment indent // Peek forward to find the comment indent
for(int j=i;j<lines.size();j++) { for(int j = i; j < lines.size(); j++) {
AsmLine peek = lines.get(j); AsmLine peek = lines.get(j);
if(peek instanceof AsmScopeBegin) { if(peek instanceof AsmScopeBegin) {
break; break;
@ -248,6 +290,7 @@ public class AsmSegment {
/** /**
* Should this ASM line be indented a few spaces. * Should this ASM line be indented a few spaces.
* Instructions, variables and similar ASM is indented slightly more than other ASM. * Instructions, variables and similar ASM is indented slightly more than other ASM.
*
* @param line The line to examine * @param line The line to examine
* @return true if the line is an instruction or similar. * @return true if the line is an instruction or similar.
*/ */
@ -257,7 +300,7 @@ public class AsmSegment {
@Override @Override
public String toString() { public String toString() {
return toString(new AsmProgram.AsmPrintState(true, false)); return toString(new AsmProgram.AsmPrintState(true, false), null);
} }
public void setSource(String source) { public void setSource(String source) {

View File

@ -14,6 +14,33 @@ public class StatementSource {
this.context = context; this.context = context;
} }
public String getFile() {
Token contextStart = context.getStart();
if(contextStart != null) {
CharStream stream = contextStart.getInputStream();
return stream.getSourceName();
}
return null;
}
public Integer getLineNumber() {
Token contextStart = context.getStart();
if(contextStart != null) {
return contextStart.getLine();
}
return null;
}
public String getCode() {
Token contextStart = context.getStart();
if(contextStart != null) {
CharStream stream = contextStart.getInputStream();
Interval interval = new Interval(contextStart.getStartIndex(), context.getStop().getStopIndex());
return stream.getText(interval);
}
return null;
}
@Override @Override
public String toString() { public String toString() {
Token contextStart = context.getStart(); Token contextStart = context.getStart();

View File

@ -63,7 +63,7 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
//getLog().append("ASM"); //getLog().append("ASM");
//getLog().append(getProgram().getAsm().toString(false, true)); //getLog().append(getProgram().getAsm().toString(false, true));
writeOutputFile(fileName, ".asm", getProgram().getAsm().toString(false)); writeOutputFile(fileName, ".asm", getProgram().getAsm().toString(new AsmProgram.AsmPrintState(false, false), null));
// Copy Resource Files // Copy Resource Files
for(Path asmResourceFile : getProgram().getAsmResourceFiles()) { for(Path asmResourceFile : getProgram().getAsmResourceFiles()) {

View File

@ -2,6 +2,7 @@ package dk.camelot64.kickc.test;
import dk.camelot64.kickc.CompileLog; import dk.camelot64.kickc.CompileLog;
import dk.camelot64.kickc.Compiler; import dk.camelot64.kickc.Compiler;
import dk.camelot64.kickc.asm.AsmProgram;
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer; import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages; import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
import dk.camelot64.kickc.model.CompileError; import dk.camelot64.kickc.model.CompileError;
@ -2584,7 +2585,7 @@ public class TestPrograms {
boolean success = true; boolean success = true;
ReferenceHelper helper = new ReferenceHelperFolder(refPath); ReferenceHelper helper = new ReferenceHelperFolder(refPath);
success &= helper.testOutput(fileName, ".asm", program.getAsm().toString(false)); success &= helper.testOutput(fileName, ".asm", program.getAsm().toString(new AsmProgram.AsmPrintState(false, false),program ));
success &= helper.testOutput(fileName, ".sym", program.getScope().toString(program, null)); success &= helper.testOutput(fileName, ".sym", program.getScope().toString(program, null));
success &= helper.testOutput(fileName, ".cfg", program.getGraph().toString(program)); success &= helper.testOutput(fileName, ".cfg", program.getGraph().toString(program));
success &= helper.testOutput(fileName, ".log", program.getLog().toString()); success &= helper.testOutput(fileName, ".log", program.getLog().toString());
@ -2596,7 +2597,7 @@ public class TestPrograms {
} }
private void compileAsm(String fileName, Program program) throws IOException { private void compileAsm(String fileName, Program program) throws IOException {
writeBinFile(fileName, ".asm", program.getAsm().toString(false)); writeBinFile(fileName, ".asm", program.getAsm().toString(new AsmProgram.AsmPrintState(false, false), program ));
for(Path asmResourceFile : program.getAsmResourceFiles()) { for(Path asmResourceFile : program.getAsmResourceFiles()) {
File asmFile = getBinFile(fileName, ".asm"); File asmFile = getBinFile(fileName, ".asm");
String asmFolder = asmFile.getParent(); String asmFolder = asmFile.getParent();