1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-18 22:30:05 +00:00

Added support for ASM .string directives through string initializer.

This commit is contained in:
jespergravgaard 2017-10-17 22:51:16 +02:00
parent 1a649008b9
commit 6fb5372f1b
14 changed files with 1521 additions and 11 deletions

View File

@ -3,7 +3,7 @@ package dk.camelot64.kickc.asm;
import java.util.List;
/** A labelled numeric data directive. */
public class AsmData implements AsmLine {
public class AsmDataNumeric implements AsmLine {
private String label;
private Type type;
@ -25,7 +25,7 @@ public class AsmData implements AsmLine {
}
public AsmData(String label, Type type, List<String> values) {
public AsmDataNumeric(String label, Type type, List<String> values) {
this.label = label;
this.type = type;
this.values = values;

View File

@ -0,0 +1,44 @@
package dk.camelot64.kickc.asm;
/** A labelled string data directive. */
public class AsmDataString implements AsmLine {
private String label;
private String value;
private int index;
public AsmDataString(String label, String value) {
this.label = label;
this.value = value;
}
@Override
public int getLineBytes() {
return value.length();
}
@Override
public double getLineCycles() {
return 0;
}
@Override
public String getAsm() {
StringBuilder asm = new StringBuilder();
asm.append(label+": ");
asm.append(".text ");
asm.append("\""+value+"\"");
return asm.toString();
}
@Override
public int getIndex() {
return index;
}
@Override
public void setIndex(int index) {
this.index = index;
}
}

View File

@ -91,10 +91,20 @@ public class AsmProgram {
* @param type The type of the data
* @param asmElements The value of the elements
*/
public void addData(String label, AsmData.Type type, List<String> asmElements) {
addLine(new AsmData(label, type, asmElements));
public void addDataNumeric(String label, AsmDataNumeric.Type type, List<String> asmElements) {
addLine(new AsmDataNumeric(label, type, asmElements));
}
/**
* Add a string data declaration tot the ASM
* @param label The label of the data
* @param value The value of the string
*/
public void addDataString(String label, String value) {
addLine(new AsmDataString(label, value));
}
/**
* Get the number of bytes the segment occupies in memory.
* Calculated by adding up the bytes of each ASM segment in the program.

View File

@ -138,7 +138,7 @@ public class AsmSegment {
printState.decIndent();
}
out.append(printState.getIndent());
if (line instanceof AsmComment || line instanceof AsmInstruction || line instanceof AsmLabelDecl || line instanceof AsmConstant || line instanceof AsmData ) {
if (line instanceof AsmComment || line instanceof AsmInstruction || line instanceof AsmLabelDecl || line instanceof AsmConstant || line instanceof AsmDataNumeric|| line instanceof AsmDataString) {
out.append(" ");
}
out.append(line.getAsm() + "\n");

View File

@ -16,6 +16,10 @@ public class ConstantString implements ConstantValue {
return SymbolTypeBasic.STRING;
}
public String getValue() {
return value;
}
@Override
public String toString() {
return toString(null);
@ -24,9 +28,9 @@ public class ConstantString implements ConstantValue {
@Override
public String toString(Program program) {
if (program == null) {
return "\\" + value + "\\";
return "\"" + value + "\"";
} else {
return "(" + SymbolTypeBasic.STRING.getTypeName() + ") " + "\\" + value + "\\";
return "(" + SymbolTypeBasic.STRING.getTypeName() + ") " + "\"" + value + "\"";
}
}

View File

@ -486,7 +486,8 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor<Object> {
@Override
public RValue visitExprString(KickCParser.ExprStringContext ctx) {
return new ConstantString(ctx.getText());
String text = ctx.getText();
return new ConstantString(text.substring(1, text.length()-1));
}
@Override

View File

@ -92,7 +92,7 @@ public class Pass4CodeGeneration {
Collection<ConstantVar> scopeConstants = scope.getAllConstants(false);
Set<String> added = new LinkedHashSet<>();
for (ConstantVar constantVar : scopeConstants) {
if(! (constantVar.getValue() instanceof ConstantArray)) {
if(! (constantVar.getValue() instanceof ConstantArray || constantVar.getValue() instanceof ConstantString)) {
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
if (asmName != null && !added.contains(asmName)) {
asm.addConstant(asmName.replace("#", "_").replace("$", "_"), AsmFragment.getAsmConstant(program, constantVar.getValue(), 99));
@ -117,19 +117,23 @@ public class Pass4CodeGeneration {
ConstantArray constantArray = (ConstantArray) constantVar.getValue();
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
if (asmName != null && !added.contains(asmName)) {
List<String> asmElements = new ArrayList<>();
for (ConstantValue element : constantArray.getElements()) {
String asmElement = AsmFragment.getAsmConstant(program, element, 99);
asmElements.add(asmElement);
}
if(SymbolTypeBasic.BYTE.equals(constantArray.getElementType())) {
asm.addData(asmName.replace("#", "_").replace("$", "_"), AsmData.Type.BYTE, asmElements);
asm.addDataNumeric(asmName.replace("#", "_").replace("$", "_"), AsmDataNumeric.Type.BYTE, asmElements);
added.add(asmName);
} else {
throw new RuntimeException("Unhandled constant array element type "+constantArray.toString(program));
}
}
} else if(constantVar.getValue() instanceof ConstantString) {
ConstantString constantString = (ConstantString) constantVar.getValue();
String asmName = constantVar.getAsmName() == null ? constantVar.getLocalName() : constantVar.getAsmName();
asm.addDataString(asmName.replace("#", "_").replace("$", "_"), constantString.getValue());
added.add(asmName);
}
}
}

View File

@ -35,6 +35,9 @@ public class VariableReplacer {
if(rValue instanceof SymbolRef) {
RValue alias = aliases.get(rValue);
if(alias!=null) {
if(alias.equals(rValue)) {
return alias;
}
RValue replacement = getReplacement(alias);
if(replacement!=null) {
return replacement;

View File

@ -40,6 +40,10 @@ public class TestCompilationOutput extends TestCase {
compileAndCompare("inmemarray");
}
public void testInMemString() throws IOException, URISyntaxException {
compileAndCompare("inmemstring");
}
public void testVoronoi() throws IOException, URISyntaxException {
compileAndCompare("voronoi");
}

View File

@ -0,0 +1,15 @@
byte* SCREEN = $0400;
byte[] TEXT = "camelot ";
main();
void main() {
byte* cursor = SCREEN;
byte i=0;
do {
(*cursor) = TEXT[i];
if(++i>8) {
i = 0;
}
} while(++cursor<SCREEN+1000)
}

View File

@ -0,0 +1,33 @@
.const SCREEN = $400
TEXT: .text "camelot "
jsr main
main: {
.label cursor = 2
lda #<SCREEN
sta cursor
lda #>SCREEN
sta cursor+1
ldx #0
b1:
lda TEXT,x
ldy #0
sta (cursor),y
inx
cpx #8
bcc b2_from_b1
ldx #0
b2_from_b1:
inc cursor
bne !+
inc cursor+1
!:
lda cursor+1
cmp #>SCREEN+$3e8
bcc b1
bne !+
lda cursor
cmp #<SCREEN+$3e8
bcc b1
!:
rts
}

View File

@ -0,0 +1,23 @@
@begin: scope:[] from
[0] call main param-assignment [ ]
to:@end
@end: scope:[] from @begin
main: scope:[main] from @begin
[1] phi() [ ]
to:main::@1
main::@1: scope:[main] from main main::@2
[2] (byte*) main::cursor#2 ← phi( main/(const byte*) SCREEN#0 main::@2/(byte*) main::cursor#1 ) [ main::i#3 main::cursor#2 ]
[2] (byte) main::i#3 ← phi( main/(byte) 0 main::@2/(byte) main::i#4 ) [ main::i#3 main::cursor#2 ]
[3] (byte~) main::$0 ← (const byte[]) TEXT#0 *idx (byte) main::i#3 [ main::i#3 main::cursor#2 main::$0 ]
[4] *((byte*) main::cursor#2) ← (byte~) main::$0 [ main::i#3 main::cursor#2 ]
[5] (byte) main::i#1 ← ++ (byte) main::i#3 [ main::cursor#2 main::i#1 ]
[6] if((byte) main::i#1<=(byte) 8) goto main::@2 [ main::cursor#2 main::i#1 ]
to:main::@2
main::@2: scope:[main] from main::@1 main::@1
[7] (byte) main::i#4 ← phi( main::@1/(byte) main::i#1 main::@1/(byte) 0 ) [ main::cursor#2 main::i#4 ]
[8] (byte*) main::cursor#1 ← ++ (byte*) main::cursor#2 [ main::i#4 main::cursor#1 ]
[9] if((byte*) main::cursor#1<(const byte*) SCREEN#0+(word) 1000) goto main::@1 [ main::i#4 main::cursor#1 ]
to:main::@return
main::@return: scope:[main] from main::@2
[10] return [ ]
to:@return

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
(label) @begin
(label) @end
(byte*) SCREEN
(const byte*) SCREEN#0 SCREEN = (word) 1024
(byte[]) TEXT
(const byte[]) TEXT#0 TEXT = (string) "camelot "
(void()) main()
(byte~) main::$0 reg byte a 22.0
(label) main::@1
(label) main::@2
(label) main::@return
(byte*) main::cursor
(byte*) main::cursor#1 cursor zp ZP_PTR_BYTE:2 16.5
(byte*) main::cursor#2 cursor zp ZP_PTR_BYTE:2 5.5
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#3 reg byte x 11.0
(byte) main::i#4 reg byte x 7.333333333333333
reg byte x [ main::i#3 main::i#4 main::i#1 ]
zp ZP_PTR_BYTE:2 [ main::cursor#2 main::cursor#1 ]
reg byte a [ main::$0 ]