1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-08-02 09:29:35 +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;
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));
}

View File

@ -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();

View File

@ -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() {

View File

@ -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) {

View File

@ -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();

View File

@ -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()) {

View File

@ -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();