mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-12-22 21:29:50 +00:00
Optimized fragment generation by caching loaded fragment files.
This commit is contained in:
parent
439a70e52a
commit
0da6c7af6a
@ -10,6 +10,7 @@ import org.antlr.v4.runtime.*;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -344,6 +345,9 @@ public class AsmFragment {
|
|||||||
return bound;
|
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.
|
* Generate assembler code for the assembler fragment.
|
||||||
*
|
*
|
||||||
@ -351,48 +355,50 @@ public class AsmFragment {
|
|||||||
*/
|
*/
|
||||||
public void generate(AsmProgram asm) {
|
public void generate(AsmProgram asm) {
|
||||||
String signature = this.getSignature();
|
String signature = this.getSignature();
|
||||||
ClassLoader classLoader = this.getClass().getClassLoader();
|
Asm6502Parser.FileContext fragmentFile = fragmentFileCache.get(signature);
|
||||||
final URL fragmentResource = classLoader.getResource("dk/camelot64/kickc/asm/fragment/" + signature + ".asm");
|
if(fragmentFile==null) {
|
||||||
if (fragmentResource == null) {
|
ClassLoader classLoader = this.getClass().getClassLoader();
|
||||||
throw new UnknownFragmentException(signature);
|
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 {
|
AsmSequenceGenerator asmSequenceGenerator = new AsmSequenceGenerator(signature, this, asm);
|
||||||
InputStream fragmentStream = fragmentResource.openStream();
|
asmSequenceGenerator.generate(fragmentFile);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AsmSequenceGenerator extends Asm6502BaseVisitor {
|
private static class AsmSequenceGenerator extends Asm6502BaseVisitor {
|
||||||
|
|
||||||
private URL fragmentResource;
|
private String signature;
|
||||||
private AsmProgram program;
|
private AsmProgram program;
|
||||||
|
private AsmFragment bindings;
|
||||||
|
|
||||||
public AsmSequenceGenerator(URL fragmentResource, AsmProgram program) {
|
public AsmSequenceGenerator(String signature, AsmFragment bindings, AsmProgram program) {
|
||||||
this.fragmentResource = fragmentResource;
|
this.signature = signature;
|
||||||
|
this.bindings = bindings;
|
||||||
this.program = program;
|
this.program = program;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsmSequenceGenerator(URL fragmentResource) {
|
|
||||||
this.fragmentResource = fragmentResource;
|
|
||||||
this.program = new AsmProgram();
|
|
||||||
}
|
|
||||||
|
|
||||||
public AsmProgram getProgram() {
|
public AsmProgram getProgram() {
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
@ -427,7 +433,7 @@ public class AsmFragment {
|
|||||||
if (instruction != null) {
|
if (instruction != null) {
|
||||||
program.addLine(instruction);
|
program.addLine(instruction);
|
||||||
} else {
|
} 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;
|
return null;
|
||||||
}
|
}
|
||||||
@ -505,7 +511,7 @@ public class AsmFragment {
|
|||||||
@Override
|
@Override
|
||||||
public Object visitExprReplace(Asm6502Parser.ExprReplaceContext ctx) {
|
public Object visitExprReplace(Asm6502Parser.ExprReplaceContext ctx) {
|
||||||
String replaceName = ctx.NAME().getSymbol().getText();
|
String replaceName = ctx.NAME().getSymbol().getText();
|
||||||
return AsmFragment.this.getBoundValue(replaceName);
|
return bindings.getBoundValue(replaceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
* @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) {
|
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.getRegisterA());
|
||||||
alwaysClobbered.add(RegisterAllocation.getRegisterX());
|
alwaysClobbered.add(RegisterAllocation.getRegisterX());
|
||||||
alwaysClobbered.add(RegisterAllocation.getRegisterY());
|
alwaysClobbered.add(RegisterAllocation.getRegisterY());
|
||||||
|
@ -1171,13 +1171,13 @@ B3_from_B2:
|
|||||||
//SEG31 [6] phi (byte*) cursor#5 = (byte*) cursor#2 -- register_copy
|
//SEG31 [6] phi (byte*) cursor#5 = (byte*) cursor#2 -- register_copy
|
||||||
jmp B3
|
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
|
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 y as potential for zp byte:4 [ x#2 x#1 ]
|
|
||||||
Removing always clobbered register reg byte a as potential for zp byte:4 [ x#2 x#1 ]
|
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 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 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 [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 [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
|
Statement [10] (byte) e#2 ← (byte) e#1 - (byte) 39 [ x#1 cursor#2 e#2 y#1 ] always clobbers reg byte a
|
||||||
|
@ -2066,9 +2066,9 @@ lvalue__B1_from_B2:
|
|||||||
//SEG70 [27] phi (byte) lvalue::i#2 = (byte) lvalue::i#1 -- register_copy
|
//SEG70 [27] phi (byte) lvalue::i#2 = (byte) lvalue::i#1 -- register_copy
|
||||||
jmp lvalue__B1
|
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
|
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 y as potential for zp byte:2 [ lvaluevar::i#2 lvaluevar::i#1 ]
|
|
||||||
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 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
|
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 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 ]
|
Removing always clobbered register reg byte y as potential for zp byte:5 [ rvaluevar::i#2 rvaluevar::i#1 ]
|
||||||
|
Loading…
Reference in New Issue
Block a user