mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-09 05:37:16 +00:00
Added command line switches for adding comments containing source file information to the ASM. Closes #215
This commit is contained in:
parent
5061a02a17
commit
f2f144c3ee
src
main/java/dk/camelot64/kickc
test/java/dk/camelot64/kickc/test
@ -1,5 +1,6 @@
|
||||
package dk.camelot64.kickc;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.model.Comment;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
@ -482,7 +483,7 @@ public class Compiler {
|
||||
new Pass4CodeGeneration(program, false).generate();
|
||||
new Pass4AssertNoCpuClobber(program).check();
|
||||
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
|
||||
getLog().append("REGISTER UPLIFT POTENTIAL REGISTERS");
|
||||
@ -530,7 +531,7 @@ public class Compiler {
|
||||
new Pass4InterruptClobberFix(program).fix();
|
||||
|
||||
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");
|
||||
List<Pass5AsmOptimization> pass5Optimizations = new ArrayList<>();
|
||||
@ -568,7 +569,7 @@ public class Compiler {
|
||||
|
||||
getLog().append("\nFINAL ASSEMBLER");
|
||||
getLog().append("Score: " + Pass4RegisterUpliftCombinations.getAsmScore(program) + "\n");
|
||||
getLog().append(program.getAsm().toString());
|
||||
getLog().append(program.getAsm().toString(new AsmProgram.AsmPrintState(true, false), program));
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package dk.camelot64.kickc;
|
||||
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
|
||||
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.")
|
||||
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. */
|
||||
public static final int COMPILE_ERROR = 1;
|
||||
|
||||
@ -180,7 +191,7 @@ public class KickC implements Callable<Void> {
|
||||
System.out.println("Writing asm file " + asmPath);
|
||||
FileOutputStream asmOutputStream = new FileOutputStream(asmPath.toFile());
|
||||
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.close();
|
||||
asmOutputStream.close();
|
||||
|
@ -1,6 +1,7 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
import dk.camelot64.kickc.fragment.AsmFormat;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.values.ScopeRef;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -196,26 +197,17 @@ public class AsmProgram {
|
||||
return clobber;
|
||||
}
|
||||
|
||||
public String toString(boolean comments) {
|
||||
return toString(new AsmPrintState(comments, false));
|
||||
}
|
||||
|
||||
public String toString(boolean comments, boolean lineIdx) {
|
||||
return toString(new AsmPrintState(comments, lineIdx));
|
||||
}
|
||||
|
||||
|
||||
public String toString(AsmPrintState printState) {
|
||||
public String toString(AsmPrintState printState, Program program) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
for(AsmSegment segment : segments) {
|
||||
out.append(segment.toString(printState));
|
||||
out.append(segment.toString(printState, program));
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(true);
|
||||
return toString(new AsmPrintState(false, false), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,19 +234,61 @@ public class AsmProgram {
|
||||
return null;
|
||||
}
|
||||
|
||||
static class AsmPrintState {
|
||||
boolean comments;
|
||||
boolean lineIdx;
|
||||
String indent;
|
||||
public static class AsmPrintState {
|
||||
// Output comments with information about the file/line number in the source file
|
||||
private boolean sourceFileInfo;
|
||||
// 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) {
|
||||
this.comments = comments;
|
||||
public AsmPrintState(boolean sourceFileInfo, boolean sourceCodeInfo, boolean sourceIclInfo, boolean lineIdx) {
|
||||
this.sourceFileInfo = sourceFileInfo;
|
||||
this.sourceCodeInfo = sourceCodeInfo;
|
||||
this.sourceIclInfo = sourceIclInfo;
|
||||
this.lineIdx = lineIdx;
|
||||
this.indent = "";
|
||||
}
|
||||
|
||||
public boolean isComments() {
|
||||
return comments;
|
||||
public AsmPrintState(boolean sourceIclInfo, boolean lineIdx) {
|
||||
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() {
|
||||
|
@ -1,6 +1,9 @@
|
||||
package dk.camelot64.kickc.asm;
|
||||
|
||||
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 java.util.ArrayList;
|
||||
@ -77,6 +80,7 @@ public class AsmSegment {
|
||||
|
||||
/**
|
||||
* 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 add The line to add
|
||||
*/
|
||||
@ -89,7 +93,7 @@ public class AsmSegment {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new NoSuchElementException("Item not found "+line);
|
||||
throw new NoSuchElementException("Item not found " + line);
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
@ -163,7 +167,7 @@ public class AsmSegment {
|
||||
* @return The registers clobbered
|
||||
*/
|
||||
public AsmClobber getClobber() {
|
||||
if(clobberOverwrite!=null) {
|
||||
if(clobberOverwrite != null) {
|
||||
return clobberOverwrite;
|
||||
}
|
||||
AsmClobber clobber = new AsmClobber();
|
||||
@ -180,6 +184,7 @@ public class AsmSegment {
|
||||
|
||||
/**
|
||||
* Get ASM line by index
|
||||
*
|
||||
* @param idx The index of the line to get
|
||||
* @return The line with the passed index. Null if not found inside the segment.
|
||||
*/
|
||||
@ -192,11 +197,48 @@ public class AsmSegment {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public String toString(AsmProgram.AsmPrintState printState) {
|
||||
public String toString(AsmProgram.AsmPrintState printState, Program program) {
|
||||
StringBuffer out = new StringBuffer();
|
||||
if(printState.isComments()) {
|
||||
out.append(printState.getIndent()).append("//SEG").append(getIndex());
|
||||
if(printState.isSourceFileInfo()) {
|
||||
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) {
|
||||
out.append(" ").append(source.replace('\r', ' ').replace('\n', ' '));
|
||||
}
|
||||
@ -219,7 +261,7 @@ public class AsmSegment {
|
||||
printState.decIndent();
|
||||
}
|
||||
if(printState.getLineIdx()) {
|
||||
out.append("["+line.getIndex()+"]");
|
||||
out.append("[" + line.getIndex() + "]");
|
||||
}
|
||||
out.append(printState.getIndent());
|
||||
if(shouldIndentAsm(line)) {
|
||||
@ -227,7 +269,7 @@ public class AsmSegment {
|
||||
}
|
||||
if(line instanceof AsmComment) {
|
||||
// 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);
|
||||
if(peek instanceof AsmScopeBegin) {
|
||||
break;
|
||||
@ -248,6 +290,7 @@ public class AsmSegment {
|
||||
/**
|
||||
* Should this ASM line be indented a few spaces.
|
||||
* Instructions, variables and similar ASM is indented slightly more than other ASM.
|
||||
*
|
||||
* @param line The line to examine
|
||||
* @return true if the line is an instruction or similar.
|
||||
*/
|
||||
@ -257,7 +300,7 @@ public class AsmSegment {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toString(new AsmProgram.AsmPrintState(true, false));
|
||||
return toString(new AsmProgram.AsmPrintState(true, false), null);
|
||||
}
|
||||
|
||||
public void setSource(String source) {
|
||||
|
@ -14,6 +14,33 @@ public class StatementSource {
|
||||
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
|
||||
public String toString() {
|
||||
Token contextStart = context.getStart();
|
||||
|
@ -63,7 +63,7 @@ public class Pass5FixLongBranches extends Pass5AsmOptimization {
|
||||
//getLog().append("ASM");
|
||||
//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
|
||||
for(Path asmResourceFile : getProgram().getAsmResourceFiles()) {
|
||||
|
@ -2,6 +2,7 @@ package dk.camelot64.kickc.test;
|
||||
|
||||
import dk.camelot64.kickc.CompileLog;
|
||||
import dk.camelot64.kickc.Compiler;
|
||||
import dk.camelot64.kickc.asm.AsmProgram;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateSynthesizer;
|
||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
@ -2584,7 +2585,7 @@ public class TestPrograms {
|
||||
|
||||
boolean success = true;
|
||||
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, ".cfg", program.getGraph().toString(program));
|
||||
success &= helper.testOutput(fileName, ".log", program.getLog().toString());
|
||||
@ -2596,7 +2597,7 @@ public class TestPrograms {
|
||||
}
|
||||
|
||||
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()) {
|
||||
File asmFile = getBinFile(fileName, ".asm");
|
||||
String asmFolder = asmFile.getParent();
|
||||
|
Loading…
x
Reference in New Issue
Block a user