1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Optimized fragment generation by caching loaded fragment files.

This commit is contained in:
jespergravgaard 2017-08-06 14:14:58 +02:00
parent 439a70e52a
commit 0da6c7af6a
4 changed files with 46 additions and 40 deletions

View File

@ -10,6 +10,7 @@ import org.antlr.v4.runtime.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@ -344,6 +345,9 @@ public class AsmFragment {
return bound;
}
/** Cache for fragment files. Maps signature to the parsed file. */
private static Map<String, Asm6502Parser.FileContext> fragmentFileCache = new HashMap<>();
/**
* Generate assembler code for the assembler fragment.
*
@ -351,48 +355,50 @@ public class AsmFragment {
*/
public void generate(AsmProgram asm) {
String signature = this.getSignature();
ClassLoader classLoader = this.getClass().getClassLoader();
final URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/asm/fragment/" + signature + ".asm");
if (fragmentResource == null) {
throw new UnknownFragmentException(signature);
Asm6502Parser.FileContext fragmentFile = fragmentFileCache.get(signature);
if(fragmentFile==null) {
ClassLoader classLoader = this.getClass().getClassLoader();
final URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/asm/fragment/" + signature + ".asm");
if (fragmentResource == null) {
throw new UnknownFragmentException(signature);
}
try {
InputStream fragmentStream = fragmentResource.openStream();
Asm6502Lexer lexer = new Asm6502Lexer(CharStreams.fromStream(fragmentStream));
Asm6502Parser parser = new Asm6502Parser(new CommonTokenStream(lexer));
parser.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
throw new RuntimeException("Error parsing fragment fragmentFile " + fragmentResource + "\n - Line: " + line + "\n - Message: " + msg);
}
});
parser.setBuildParseTree(true);
fragmentFile = parser.file();
fragmentStream.close();
fragmentFileCache.put(signature, fragmentFile);
} catch (IOException e) {
throw new RuntimeException("Error reading code fragment " + fragmentResource);
}
}
try {
InputStream fragmentStream = fragmentResource.openStream();
Asm6502Lexer lexer = new Asm6502Lexer(CharStreams.fromStream(fragmentStream));
Asm6502Parser parser = new Asm6502Parser(new CommonTokenStream(lexer));
parser.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
throw new RuntimeException("Error parsing fragment file " + fragmentResource + "\n - Line: " + line + "\n - Message: " + msg);
}
});
parser.setBuildParseTree(true);
Asm6502Parser.FileContext file = parser.file();
AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(fragmentResource, asm);
asmSequenceGenerator.generate(file);
fragmentStream.close();
} catch (IOException e) {
throw new RuntimeException("Error reading code fragment " + fragmentResource);
}
AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(signature, this, asm);
asmSequenceGenerator.generate(fragmentFile);
}
private class AsmSequenceGenerator extends Asm6502BaseVisitor {
private static class AsmSequenceGenerator extends Asm6502BaseVisitor {
private URL fragmentResource;
private String signature;
private AsmProgram program;
private AsmFragment bindings;
public AsmSequenceGenerator(URL fragmentResource, AsmProgram program) {
this.fragmentResource = fragmentResource;
public AsmSequenceGenerator(String signature, AsmFragment bindings, AsmProgram program) {
this.signature = signature;
this.bindings = bindings;
this.program = program;
}
public AsmSequenceGenerator(URL fragmentResource) {
this.fragmentResource = fragmentResource;
this.program = new AsmProgram();
}
public AsmProgram getProgram() {
return program;
}
@ -427,7 +433,7 @@ public class AsmFragment {
if (instruction != null) {
program.addLine(instruction);
} else {
throw new RuntimeException("Error parsing ASM fragment line in " + fragmentResource.toString() + "\n - Line: " + ctx.getText());
throw new RuntimeException("Error parsing ASM fragment line in dk/camelot64/kickc/asm/fragment/" + signature + ".asm\n - Line: " + ctx.getText());
}
return null;
}
@ -505,7 +511,7 @@ public class AsmFragment {
@Override
public Object visitExprReplace(Asm6502Parser.ExprReplaceContext ctx) {
String replaceName = ctx.NAME().getSymbol().getText();
return AsmFragment.this.getBoundValue(replaceName);
return bindings.getBoundValue(replaceName);
}
}

View File

@ -116,7 +116,7 @@ public class Pass3RegisterUpliftPotentialRegisterAnalysis extends Pass2Base {
* @return A set with registers that are clobbered by all different register assignments in the combination
*/
private Set<RegisterAllocation.Register> findAlwaysClobberedRegisters(ControlFlowBlock block, Statement statement, RegisterCombinationIterator combinations) {
Set<RegisterAllocation.Register> alwaysClobbered = new HashSet<>();
Set<RegisterAllocation.Register> alwaysClobbered = new LinkedHashSet<>();
alwaysClobbered.add(RegisterAllocation.getRegisterA());
alwaysClobbered.add(RegisterAllocation.getRegisterX());
alwaysClobbered.add(RegisterAllocation.getRegisterY());

View File

@ -1171,13 +1171,13 @@ B3_from_B2:
//SEG31 [6] phi (byte*) cursor#5 = (byte*) cursor#2 -- register_copy
jmp B3
Statement [1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ] always clobbers reg byte y reg byte a
Removing always clobbered register reg byte y as potential for zp byte:4 [ x#2 x#1 ]
Statement [1] *((byte*) cursor#3) ← (byte) 81 [ cursor#3 x#2 e#3 y#2 ] always clobbers reg byte a reg byte y
Removing always clobbered register reg byte a as potential for zp byte:4 [ x#2 x#1 ]
Removing always clobbered register reg byte y as potential for zp byte:5 [ e#3 e#5 e#1 e#2 ]
Removing always clobbered register reg byte y as potential for zp byte:4 [ x#2 x#1 ]
Removing always clobbered register reg byte a as potential for zp byte:5 [ e#3 e#5 e#1 e#2 ]
Removing always clobbered register reg byte y as potential for zp byte:6 [ y#2 y#4 y#1 ]
Removing always clobbered register reg byte y as potential for zp byte:5 [ e#3 e#5 e#1 e#2 ]
Removing always clobbered register reg byte a as potential for zp byte:6 [ y#2 y#4 y#1 ]
Removing always clobbered register reg byte y as potential for zp byte:6 [ y#2 y#4 y#1 ]
Statement [4] (byte) e#1 ← (byte) e#3 + (byte) 24 [ x#1 e#1 cursor#1 y#2 ] always clobbers reg byte a
Statement [9] (byte*) cursor#2 ← (byte*) cursor#1 + (byte) 40 [ x#1 e#1 cursor#2 y#1 ] always clobbers reg byte a
Statement [10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ] always clobbers reg byte a

View File

@ -2066,9 +2066,9 @@ lvalue__B1_from_B2:
//SEG70 [27] phi (byte) lvalue::i#2 = (byte) lvalue::i#1 -- register_copy
jmp lvalue__B1
Statement [9] *((byte*) lvaluevar::screen#2) ← (byte) 4 [ lvaluevar::i#2 lvaluevar::screen#2 ] always clobbers reg byte y reg byte a
Removing always clobbered register reg byte y as potential for zp byte:2 [ lvaluevar::i#2 lvaluevar::i#1 ]
Statement [9] *((byte*) lvaluevar::screen#2) ← (byte) 4 [ lvaluevar::i#2 lvaluevar::screen#2 ] always clobbers reg byte a reg byte y
Removing always clobbered register reg byte a as potential for zp byte:2 [ lvaluevar::i#2 lvaluevar::i#1 ]
Removing always clobbered register reg byte y as potential for zp byte:2 [ lvaluevar::i#2 lvaluevar::i#1 ]
Statement [15] (byte) rvaluevar::b#0 ← * (byte*) rvaluevar::screen#2 [ rvaluevar::i#2 rvaluevar::screen#2 ] always clobbers reg byte a reg byte y
Removing always clobbered register reg byte a as potential for zp byte:5 [ rvaluevar::i#2 rvaluevar::i#1 ]
Removing always clobbered register reg byte y as potential for zp byte:5 [ rvaluevar::i#2 rvaluevar::i#1 ]