mirror of
https://gitlab.com/camelot/kickc.git
synced 2026-04-20 11:18:16 +00:00
Added initial support for special BYTE0() and BYTE1() unary operators giving access to specific bytes. #221
This commit is contained in:
Generated
+12
-3
@@ -7,9 +7,18 @@
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="java.util" withSubpackages="false" static="false" />
|
||||
<package name="kotlinx.android.synthetic" withSubpackages="true" static="false" />
|
||||
<package name="io.ktor" withSubpackages="true" static="false" />
|
||||
<package name="java.util" alias="false" withSubpackages="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
<package name="io.ktor" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
</JetCodeStyleSettings>
|
||||
|
||||
-19559
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
lda {m1}
|
||||
@@ -0,0 +1 @@
|
||||
txa
|
||||
@@ -0,0 +1 @@
|
||||
tya
|
||||
@@ -0,0 +1 @@
|
||||
txa
|
||||
@@ -0,0 +1 @@
|
||||
tya
|
||||
@@ -0,0 +1 @@
|
||||
lda {m1}
|
||||
@@ -0,0 +1 @@
|
||||
lda {m1}
|
||||
@@ -0,0 +1 @@
|
||||
lda {m1}
|
||||
@@ -0,0 +1 @@
|
||||
lda {m1}
|
||||
@@ -0,0 +1 @@
|
||||
lda {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
lda #0
|
||||
@@ -0,0 +1 @@
|
||||
lda #0
|
||||
@@ -0,0 +1 @@
|
||||
lda #0
|
||||
@@ -0,0 +1 @@
|
||||
lda #0
|
||||
@@ -0,0 +1 @@
|
||||
lda #0
|
||||
@@ -0,0 +1 @@
|
||||
lda #0
|
||||
@@ -0,0 +1 @@
|
||||
lda #0
|
||||
@@ -0,0 +1 @@
|
||||
lda #0
|
||||
@@ -0,0 +1 @@
|
||||
lda {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
lda {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
lda {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
lda {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
ldx {m1}
|
||||
@@ -0,0 +1 @@
|
||||
tax
|
||||
@@ -0,0 +1 @@
|
||||
tax
|
||||
@@ -0,0 +1 @@
|
||||
ldx {m1}
|
||||
@@ -0,0 +1 @@
|
||||
ldx {m1}
|
||||
@@ -0,0 +1 @@
|
||||
ldx {m1}
|
||||
@@ -0,0 +1 @@
|
||||
ldx {m1}
|
||||
@@ -0,0 +1 @@
|
||||
ldx {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
ldx #0
|
||||
@@ -0,0 +1 @@
|
||||
ldx #0
|
||||
@@ -0,0 +1 @@
|
||||
ldx #0
|
||||
@@ -0,0 +1 @@
|
||||
ldx #0
|
||||
@@ -0,0 +1 @@
|
||||
ldx {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
ldx {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
ldx {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
ldx {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
ldy {m1}
|
||||
@@ -0,0 +1 @@
|
||||
tay
|
||||
@@ -0,0 +1 @@
|
||||
tay
|
||||
@@ -0,0 +1 @@
|
||||
ldy {m1}
|
||||
@@ -0,0 +1 @@
|
||||
ldy {m1}
|
||||
@@ -0,0 +1 @@
|
||||
ldy {m1}
|
||||
@@ -0,0 +1 @@
|
||||
ldy {m1}
|
||||
@@ -0,0 +1 @@
|
||||
ldy {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
ldy #0
|
||||
@@ -0,0 +1 @@
|
||||
ldy #0
|
||||
@@ -0,0 +1 @@
|
||||
ldy #0
|
||||
@@ -0,0 +1 @@
|
||||
ldy #0
|
||||
@@ -0,0 +1 @@
|
||||
ldy {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
ldy {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
ldy {m1}+1
|
||||
@@ -0,0 +1 @@
|
||||
ldy {m1}+1
|
||||
@@ -231,6 +231,7 @@ public class Compiler {
|
||||
getLog().append(program.getGraph().toString(program));
|
||||
}
|
||||
new Pass1ResolveForwardReferences(program).execute();
|
||||
new Pass1ByteXIntrinsicRewrite(program).execute();
|
||||
new Pass1AssertProcedureDefined(program).execute();
|
||||
new Pass1AssertVariableDefined(program).execute();
|
||||
new PassNAssertStructMembers(program).execute();
|
||||
|
||||
@@ -212,6 +212,10 @@ public class AsmFormat {
|
||||
} else {
|
||||
throw new CompileError("Operator _hi_ cannot handle " + operand.toString(program));
|
||||
}
|
||||
} else if(Operators.BYTE0.equals(operator)) {
|
||||
return operator.getOperator() + "(" + getAsmConstant(program, operand, operator.getPrecedence(), codeScope) + ")";
|
||||
} else if(Operators.BYTE1.equals(operator)) {
|
||||
return operator.getOperator() + "(" + getAsmConstant(program, operand, operator.getPrecedence(), codeScope) + ")";
|
||||
} else if(Operators.INCREMENT.equals(operator)) {
|
||||
return getAsmConstant(program, new ConstantBinary(operand, Operators.PLUS, new ConstantInteger((long) 1)), outerPrecedence, codeScope);
|
||||
} else if(Operators.DECREMENT.equals(operator)) {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package dk.camelot64.kickc.model.operators;
|
||||
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||
import dk.camelot64.kickc.model.values.ConstantString;
|
||||
|
||||
/** Unary get byte 0 operator byte0(x) */
|
||||
public class OperatorGetByte0 extends OperatorUnary {
|
||||
|
||||
public OperatorGetByte0(int precedence) {
|
||||
super("<", "_byte0_", precedence);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
|
||||
if(operand instanceof ConstantInteger) {
|
||||
ConstantInteger operandInt = (ConstantInteger) operand;
|
||||
return new ConstantInteger(operandInt.getInteger() & 0xff, SymbolType.BYTE);
|
||||
} else if(operand instanceof ConstantPointer) {
|
||||
return new ConstantInteger(((ConstantPointer) operand).getLocation() & 0xff, SymbolType.BYTE);
|
||||
} else if(operand instanceof ConstantString) {
|
||||
throw ConstantNotLiteral.getException();
|
||||
}
|
||||
throw ConstantNotLiteral.getException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType inferType(SymbolType operandType) {
|
||||
return SymbolType.BYTE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package dk.camelot64.kickc.model.operators;
|
||||
|
||||
import dk.camelot64.kickc.model.ConstantNotLiteral;
|
||||
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||
import dk.camelot64.kickc.model.values.ConstantLiteral;
|
||||
import dk.camelot64.kickc.model.values.ConstantPointer;
|
||||
import dk.camelot64.kickc.model.values.ConstantString;
|
||||
|
||||
/** Unary get byte 1 operator byte1(x) */
|
||||
public class OperatorGetByte1 extends OperatorUnary {
|
||||
|
||||
public OperatorGetByte1(int precedence) {
|
||||
super(">", "_byte1_", precedence);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstantLiteral calculateLiteral(ConstantLiteral operand, ProgramScope scope) {
|
||||
if(operand instanceof ConstantInteger) {
|
||||
ConstantInteger operandInt = (ConstantInteger) operand;
|
||||
return new ConstantInteger((operandInt.getInteger()>>8)&0xff, SymbolType.BYTE);
|
||||
} else if(operand instanceof ConstantPointer) {
|
||||
return new ConstantInteger((((ConstantPointer) operand).getLocation()>>8) & 0xff, SymbolType.BYTE);
|
||||
} else if(operand instanceof ConstantString) {
|
||||
throw ConstantNotLiteral.getException();
|
||||
}
|
||||
throw ConstantNotLiteral.getException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SymbolType inferType(SymbolType operandType) {
|
||||
return SymbolType.BYTE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -40,6 +40,10 @@ public class Operators {
|
||||
public static final OperatorBinary SHIFT_RIGHT = new OperatorShiftRight(5);
|
||||
public static final OperatorUnary LOWBYTE = new OperatorGetLow(14);
|
||||
public static final OperatorUnary HIBYTE = new OperatorGetHigh(14);
|
||||
public static final OperatorUnary BYTE0 = new OperatorGetByte0(14);
|
||||
public static final OperatorUnary BYTE1 = new OperatorGetByte1(14);
|
||||
//public static final OperatorUnary BYTE2 = new OperatorGetByte2(14);
|
||||
//public static final OperatorUnary BYTE3 = new OperatorGetByte3(14);
|
||||
public static final OperatorBinary LT = new OperatorLessThan(7);
|
||||
public static final OperatorBinary LE = new OperatorLessThanEqual(7);
|
||||
public static final OperatorBinary GT = new OperatorGreaterThan(7);
|
||||
@@ -132,6 +136,14 @@ public class Operators {
|
||||
return LOWBYTE;
|
||||
case ">":
|
||||
return HIBYTE;
|
||||
case "b0":
|
||||
return BYTE0;
|
||||
//case "b1":
|
||||
// return BYTE1;
|
||||
//case "b2":
|
||||
// return BYTE2;
|
||||
//case "b3":
|
||||
// return BYTE3;
|
||||
case "&":
|
||||
return ADDRESS_OF;
|
||||
default:
|
||||
|
||||
@@ -5,6 +5,7 @@ import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeProcedure;
|
||||
import dk.camelot64.kickc.model.values.ProcedureRef;
|
||||
import dk.camelot64.kickc.passes.Pass1ByteXIntrinsicRewrite;
|
||||
import dk.camelot64.kickc.passes.Pass1PrintfIntrinsicRewrite;
|
||||
|
||||
import java.util.*;
|
||||
@@ -36,7 +37,7 @@ public class Procedure extends Scope {
|
||||
private boolean isConstructor;
|
||||
|
||||
/** The names of all legal intrinsic procedures. */
|
||||
final public static List<String> INTRINSIC_PROCEDURES = Collections.singletonList(Pass1PrintfIntrinsicRewrite.INTRINSIC_PRINTF_NAME);
|
||||
final public static List<String> INTRINSIC_PROCEDURES = Arrays.asList(Pass1PrintfIntrinsicRewrite.INTRINSIC_PRINTF_NAME, Pass1ByteXIntrinsicRewrite.INTRINSIC_BYTE0_NAME, Pass1ByteXIntrinsicRewrite.INTRINSIC_BYTE1_NAME );
|
||||
|
||||
/** The method for passing parameters and return value to the procedure. */
|
||||
public enum CallingConvention {
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.CompileError;
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.operators.OperatorUnary;
|
||||
import dk.camelot64.kickc.model.operators.Operators;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* Rewrite BYTE0() / BYTE1() / BYTE2() / BYTE3() calls to special unary operators.
|
||||
*/
|
||||
public class Pass1ByteXIntrinsicRewrite extends Pass2SsaOptimization {
|
||||
|
||||
/** The byte0 procedure name. */
|
||||
public static final String INTRINSIC_BYTE0_NAME = "BYTE0";
|
||||
/** The byte1 procedure name. */
|
||||
public static final String INTRINSIC_BYTE1_NAME = "BYTE1";
|
||||
|
||||
public Pass1ByteXIntrinsicRewrite(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
final ListIterator<Statement> stmtIt = block.getStatements().listIterator();
|
||||
while(stmtIt.hasNext()) {
|
||||
Statement statement = stmtIt.next();
|
||||
if(statement instanceof StatementCall) {
|
||||
StatementCall call = (StatementCall) statement;
|
||||
final List<RValue> parameters = call.getParameters();
|
||||
if(INTRINSIC_BYTE0_NAME.equals(call.getProcedureName())) {
|
||||
generateUnaryOperator(stmtIt, call, parameters, Operators.BYTE0);
|
||||
} else if(INTRINSIC_BYTE1_NAME.equals(call.getProcedureName())) {
|
||||
generateUnaryOperator(stmtIt, call, parameters, Operators.BYTE1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an unary operator expression for the BYTEX()
|
||||
*/
|
||||
private void generateUnaryOperator(ListIterator<Statement> stmtIt, StatementCall call, List<RValue> parameters, OperatorUnary operator) {
|
||||
if(parameters.size()!=1) {
|
||||
throw new CompileError("Wrong number of parameters in call " + call.toString(getProgram(), false) + " expected " + 1, call);
|
||||
}
|
||||
// Remove the call
|
||||
stmtIt.remove();
|
||||
// Add the unary byte0 operator
|
||||
stmtIt.add(new StatementAssignment(call.getlValue(), operator, parameters.get(0), call.isInitialAssignment(), call.getSource(), call.getComments()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -44,6 +44,17 @@ public class TestPrograms {
|
||||
public TestPrograms() {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testOperatorByte1() throws IOException, URISyntaxException {
|
||||
compileAndCompare("operator-byte1.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperatorByte0() throws IOException, URISyntaxException {
|
||||
compileAndCompare("operator-byte0.c", log());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStdlibStringMemChr1() throws IOException, URISyntaxException {
|
||||
compileAndCompare("stdlib-string-memchr-1.c");
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Test operator BYTE0()
|
||||
|
||||
void main() {
|
||||
volatile unsigned char bu = 7;
|
||||
volatile signed char bs = 7;
|
||||
volatile unsigned int wu = 20000;
|
||||
volatile signed int ws = -177;
|
||||
volatile unsigned long du = 2000000;
|
||||
volatile signed long ds = -3777777;
|
||||
char * volatile ptr = 0x0000;
|
||||
|
||||
char * const SCREEN = 0x0400;
|
||||
char i = 0;
|
||||
SCREEN[i++] = BYTE0(17);
|
||||
SCREEN[i++] = BYTE0(377);
|
||||
SCREEN[i++] = BYTE0(bu);
|
||||
SCREEN[i++] = BYTE0(bs);
|
||||
SCREEN[i++] = BYTE0(wu);
|
||||
SCREEN[i++] = BYTE0(ws);
|
||||
SCREEN[i++] = BYTE0(du);
|
||||
SCREEN[i++] = BYTE0(ds);
|
||||
SCREEN[i++] = BYTE0(ptr);
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Test operator BYTE0()
|
||||
|
||||
void main() {
|
||||
volatile unsigned char bu = 7;
|
||||
volatile signed char bs = 7;
|
||||
volatile unsigned int wu = 20000;
|
||||
volatile signed int ws = -177;
|
||||
volatile unsigned long du = 2000000;
|
||||
volatile signed long ds = -3777777;
|
||||
char * volatile ptr = 0x0000;
|
||||
|
||||
char * const SCREEN = 0x0400;
|
||||
char i = 0;
|
||||
SCREEN[i++] = BYTE1(17);
|
||||
SCREEN[i++] = BYTE1(377);
|
||||
SCREEN[i++] = BYTE1(bu);
|
||||
SCREEN[i++] = BYTE1(bs);
|
||||
SCREEN[i++] = BYTE1(wu);
|
||||
SCREEN[i++] = BYTE1(ws);
|
||||
SCREEN[i++] = BYTE1(du);
|
||||
SCREEN[i++] = BYTE1(ds);
|
||||
SCREEN[i++] = BYTE1(ptr);
|
||||
}
|
||||
Reference in New Issue
Block a user