mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-24 16:30:54 +00:00
New literal word constructor handling - 277/354
This commit is contained in:
parent
07b67efb7c
commit
fe60b31f73
@ -254,6 +254,7 @@ public class Compiler {
|
|||||||
optimizations.add(new Pass2ConstantIfs(program));
|
optimizations.add(new Pass2ConstantIfs(program));
|
||||||
optimizations.add(new Pass2ConstantStringConsolidation(program));
|
optimizations.add(new Pass2ConstantStringConsolidation(program));
|
||||||
optimizations.add(new Pass2FixInlineConstructors(program));
|
optimizations.add(new Pass2FixInlineConstructors(program));
|
||||||
|
optimizations.add(new Pass2FixInlineConstructorsNew(program));
|
||||||
optimizations.add(new Pass2TypeInference(program));
|
optimizations.add(new Pass2TypeInference(program));
|
||||||
optimizations.add(new PassNEliminateUnusedVars(program, true));
|
optimizations.add(new PassNEliminateUnusedVars(program, true));
|
||||||
optimizations.add(new Pass2EliminateRedundantCasts(program));
|
optimizations.add(new Pass2EliminateRedundantCasts(program));
|
||||||
|
@ -5,9 +5,7 @@ import dk.camelot64.kickc.model.Program;
|
|||||||
import dk.camelot64.kickc.model.statements.Statement;
|
import dk.camelot64.kickc.model.statements.Statement;
|
||||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||||
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
||||||
import dk.camelot64.kickc.model.values.ConstantBinary;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
import dk.camelot64.kickc.model.values.ConstantUnary;
|
|
||||||
import dk.camelot64.kickc.model.values.PointerDereferenceIndexed;
|
|
||||||
|
|
||||||
import java.util.ListIterator;
|
import java.util.ListIterator;
|
||||||
|
|
||||||
@ -33,6 +31,8 @@ public class ProgramExpressionIterator {
|
|||||||
handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), null, null, null);
|
handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryConstant(programValue), null, null, null);
|
||||||
} else if(programValue.get() instanceof PointerDereferenceIndexed) {
|
} else if(programValue.get() instanceof PointerDereferenceIndexed) {
|
||||||
handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), null, null, null);
|
handler.execute(new ProgramExpressionBinary.ProgramExpressionBinaryPointerDereferenceIndexed(programValue), null, null, null);
|
||||||
|
} else if(programValue.get() instanceof ConstantCastValue) {
|
||||||
|
handler.execute(new ProgramExpressionUnary.ProgramExpressionUnaryCast(programValue), null, null, null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ProgramValueIterator.execute(program.getScope(), programValueHandler);
|
ProgramValueIterator.execute(program.getScope(), programValueHandler);
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package dk.camelot64.kickc.model.iterator;
|
package dk.camelot64.kickc.model.iterator;
|
||||||
|
|
||||||
import dk.camelot64.kickc.model.operators.OperatorUnary;
|
import dk.camelot64.kickc.model.operators.OperatorUnary;
|
||||||
|
import dk.camelot64.kickc.model.operators.Operators;
|
||||||
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||||
|
import dk.camelot64.kickc.model.values.ConstantCastValue;
|
||||||
import dk.camelot64.kickc.model.values.ConstantUnary;
|
import dk.camelot64.kickc.model.values.ConstantUnary;
|
||||||
import dk.camelot64.kickc.model.values.RValue;
|
import dk.camelot64.kickc.model.values.RValue;
|
||||||
import dk.camelot64.kickc.model.values.Value;
|
import dk.camelot64.kickc.model.values.Value;
|
||||||
@ -81,4 +83,37 @@ public interface ProgramExpressionUnary extends ProgramExpression {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Unary cast expression {@link ConstantCastValue} as part of a constant expression. */
|
||||||
|
class ProgramExpressionUnaryCast implements ProgramExpressionUnary {
|
||||||
|
|
||||||
|
/** A ProgramValue containing a {@link ConstantCastValue}. */
|
||||||
|
private ProgramValue programValue;
|
||||||
|
|
||||||
|
ProgramExpressionUnaryCast(ProgramValue programValue) {
|
||||||
|
this.programValue = programValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConstantCastValue getConstantUnary() {
|
||||||
|
return (ConstantCastValue) programValue.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OperatorUnary getOperator() {
|
||||||
|
return Operators.getCastUnary(getConstantUnary().getToType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RValue getOperand() {
|
||||||
|
return getConstantUnary().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(Value value) {
|
||||||
|
programValue.set(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,12 +31,8 @@ public class SymbolTypeArray extends SymbolTypePointer {
|
|||||||
@Override
|
@Override
|
||||||
public String getTypeName() {
|
public String getTypeName() {
|
||||||
SymbolType elementType = getElementType();
|
SymbolType elementType = getElementType();
|
||||||
if(elementType instanceof SymbolTypeMulti) {
|
|
||||||
return "(" + elementType.getTypeName() + ")" + "[" + (size == null ? "" : size.toString()) + "]";
|
|
||||||
} else {
|
|
||||||
return elementType.getTypeName() + "[" + (size == null ? "" : size.toString()) + "]";
|
return elementType.getTypeName() + "[" + (size == null ? "" : size.toString()) + "]";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
|
@ -9,10 +9,6 @@ import dk.camelot64.kickc.model.statements.*;
|
|||||||
import dk.camelot64.kickc.model.symbols.*;
|
import dk.camelot64.kickc.model.symbols.*;
|
||||||
import dk.camelot64.kickc.model.values.*;
|
import dk.camelot64.kickc.model.values.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type inference of expressions (rValues & unary/binary operators)
|
* Type inference of expressions (rValues & unary/binary operators)
|
||||||
*/
|
*/
|
||||||
@ -148,21 +144,8 @@ public class SymbolTypeInference {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(elmType != null) {
|
if(elmType != null) {
|
||||||
if((list.getList().size() == 2 && SymbolType.BYTE.equals(elmType) || SymbolType.SBYTE.equals(elmType))) {
|
long size = list.getList().size();
|
||||||
// Potentially a word constructor - return a composite type
|
return new SymbolTypeArray(elmType, new ConstantInteger(size, size<256?SymbolType.BYTE:SymbolType.WORD));
|
||||||
ArrayList<SymbolType> types = new ArrayList<>();
|
|
||||||
types.add(new SymbolTypeArray(elmType));
|
|
||||||
types.add(SymbolType.WORD);
|
|
||||||
return new SymbolTypeMulti(types);
|
|
||||||
} else if((list.getList().size() == 2 && SymbolType.WORD.equals(elmType))) {
|
|
||||||
// Potentially a dword constructor - return a composite type
|
|
||||||
ArrayList<SymbolType> types = new ArrayList<>();
|
|
||||||
types.add(new SymbolTypeArray(elmType));
|
|
||||||
types.add(SymbolType.DWORD);
|
|
||||||
return new SymbolTypeMulti(types);
|
|
||||||
} else {
|
|
||||||
return new SymbolTypeArray(elmType);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Cannot infer list element type " + list.toString());
|
throw new RuntimeException("Cannot infer list element type " + list.toString());
|
||||||
}
|
}
|
||||||
@ -223,14 +206,9 @@ public class SymbolTypeInference {
|
|||||||
SymbolType valueType = inferType(programScope, rValue);
|
SymbolType valueType = inferType(programScope, rValue);
|
||||||
if(type == null) {
|
if(type == null) {
|
||||||
type = valueType;
|
type = valueType;
|
||||||
} else {
|
} else if(!type.equals(valueType))
|
||||||
SymbolType newType = intersectTypes(type, valueType);
|
|
||||||
if(newType == null) {
|
|
||||||
throw new CompileError("Types not compatible " + type + " and " + valueType);
|
throw new CompileError("Types not compatible " + type + " and " + valueType);
|
||||||
}
|
}
|
||||||
type = newType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
|
if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
|
||||||
program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program));
|
program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program));
|
||||||
}
|
}
|
||||||
@ -295,53 +273,4 @@ public class SymbolTypeInference {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the symbol type that is the intersection between the two passed types.
|
|
||||||
* Handles SymbolTypeMulti by intersecting the sub type lists.
|
|
||||||
*
|
|
||||||
* @param type1 The first type
|
|
||||||
* @param type2 The second type
|
|
||||||
* @return The intersection between the two types (handling multi-types)
|
|
||||||
*/
|
|
||||||
public static SymbolType intersectTypes(SymbolType type1, SymbolType type2) {
|
|
||||||
List<SymbolType> newSubTypes = new ArrayList<>();
|
|
||||||
if(type1 instanceof SymbolTypeMulti) {
|
|
||||||
Collection<SymbolType> subTypes1 = ((SymbolTypeMulti) type1).getTypes();
|
|
||||||
if(type2 instanceof SymbolTypeMulti) {
|
|
||||||
Collection<SymbolType> subTypes2 = ((SymbolTypeMulti) type2).getTypes();
|
|
||||||
for(SymbolType subType1 : subTypes1) {
|
|
||||||
if(subTypes2.contains(subType1)) {
|
|
||||||
newSubTypes.add(subType1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Element type is not multi - check if the list type contains it
|
|
||||||
if(subTypes1.contains(type2)) {
|
|
||||||
newSubTypes.add(type2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// List-type not multi - check if the element type contains it
|
|
||||||
if(type2 instanceof SymbolTypeMulti) {
|
|
||||||
Collection<SymbolType> subTypes2 = ((SymbolTypeMulti) type2).getTypes();
|
|
||||||
if(subTypes2.contains(type1)) {
|
|
||||||
newSubTypes.add(type1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Element type is not multi - check if the list type is the same
|
|
||||||
if(type1.equals(type2)) {
|
|
||||||
newSubTypes.add(type1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(newSubTypes.size() == 0) {
|
|
||||||
return null;
|
|
||||||
} else if(newSubTypes.size() == 1) {
|
|
||||||
// A single type matching - use it
|
|
||||||
return newSubTypes.get(0);
|
|
||||||
} else {
|
|
||||||
// Multiple matches was found - use them
|
|
||||||
return new SymbolTypeMulti(newSubTypes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -38,4 +38,8 @@ public class ValueList implements RValue {
|
|||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return toString(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,37 +53,6 @@ public class Pass2ConstantCastSimplification extends Pass2SsaOptimization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ProgramValueIterator.execute(getProgram(), (programValue, currentStmt, stmtIt, currentBlock) -> {
|
|
||||||
if(programValue.get() instanceof ConstantCastValue) {
|
|
||||||
ConstantCastValue constantCastValue = (ConstantCastValue) programValue.get();
|
|
||||||
if(constantCastValue.getValue() instanceof ConstantInteger) {
|
|
||||||
ConstantInteger constantInteger = (ConstantInteger) constantCastValue.getValue();
|
|
||||||
SymbolType castType = constantCastValue.getToType();
|
|
||||||
if(SymbolType.NUMBER.equals(constantInteger.getType())) {
|
|
||||||
if(castType instanceof SymbolTypeIntegerFixed ) {
|
|
||||||
ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
|
|
||||||
programValue.set(newConstInt);
|
|
||||||
getLog().append("Simplifying constant integer cast " + newConstInt.toString());
|
|
||||||
optimized.set(true);
|
|
||||||
} else if(castType instanceof SymbolTypePointer) {
|
|
||||||
ConstantPointer newConstPointer = new ConstantPointer(constantInteger.getInteger(), ((SymbolTypePointer) castType).getElementType());
|
|
||||||
programValue.set(newConstPointer);
|
|
||||||
getLog().append("Simplifying constant pointer cast " + newConstPointer.toString());
|
|
||||||
optimized.set(true);
|
|
||||||
}
|
|
||||||
} else if(castType instanceof SymbolTypeIntegerFixed) {
|
|
||||||
if(((SymbolTypeIntegerFixed) castType).contains(constantInteger.getValue())) {
|
|
||||||
// Cast type contains the value - cast not needed
|
|
||||||
ConstantInteger newConstInt = new ConstantInteger(constantInteger.getInteger(), castType);
|
|
||||||
programValue.set(newConstInt);
|
|
||||||
getLog().append("Simplifying constant integer cast " + newConstInt.toString());
|
|
||||||
optimized.set(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
return optimized.get();
|
return optimized.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
package dk.camelot64.kickc.passes;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.model.Comment;
|
||||||
|
import dk.camelot64.kickc.model.Program;
|
||||||
|
import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
|
||||||
|
import dk.camelot64.kickc.model.iterator.ProgramExpressionUnary;
|
||||||
|
import dk.camelot64.kickc.model.operators.OperatorBinary;
|
||||||
|
import dk.camelot64.kickc.model.operators.Operators;
|
||||||
|
import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||||
|
import dk.camelot64.kickc.model.symbols.Scope;
|
||||||
|
import dk.camelot64.kickc.model.symbols.VariableIntermediate;
|
||||||
|
import dk.camelot64.kickc.model.types.SymbolType;
|
||||||
|
import dk.camelot64.kickc.model.values.CastValue;
|
||||||
|
import dk.camelot64.kickc.model.values.RValue;
|
||||||
|
import dk.camelot64.kickc.model.values.ValueList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifies word constructors <code> (word) { b1, b2 }</code> and replaces
|
||||||
|
* them with a binary operator <code>word w = b1 w= b2 ;</code>
|
||||||
|
*/
|
||||||
|
public class Pass2FixInlineConstructorsNew extends Pass2SsaOptimization {
|
||||||
|
|
||||||
|
public Pass2FixInlineConstructorsNew(Program program) {
|
||||||
|
super(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean step() {
|
||||||
|
AtomicBoolean optimized = new AtomicBoolean(false);
|
||||||
|
ProgramExpressionIterator.execute(getProgram(), (programExpression, currentStmt, stmtIt, currentBlock) -> {
|
||||||
|
if(programExpression instanceof ProgramExpressionUnary) {
|
||||||
|
if(programExpression.getOperator().equals(Operators.CAST_WORD)) {
|
||||||
|
if(((ProgramExpressionUnary) programExpression).getOperand() instanceof ValueList) {
|
||||||
|
ValueList list = (ValueList) ((ProgramExpressionUnary) programExpression).getOperand();
|
||||||
|
List<RValue> listValues = list.getList();
|
||||||
|
if(listValues.size()==2) {
|
||||||
|
|
||||||
|
OperatorBinary constructOperator = Operators.WORD;
|
||||||
|
SymbolType constructType = SymbolType.WORD;
|
||||||
|
|
||||||
|
// Convert list to a word constructor in a new tmp variable
|
||||||
|
Scope currentScope = Pass2FixInlineConstructorsNew.this.getScope().getScope(currentBlock.getScope());
|
||||||
|
VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
|
||||||
|
tmpVar.setTypeInferred(constructType);
|
||||||
|
// Move backward - to insert before the current statement
|
||||||
|
stmtIt.previous();
|
||||||
|
// Add assignment of the new tmpVar
|
||||||
|
StatementAssignment assignment = new StatementAssignment(tmpVar.getRef(), new CastValue(SymbolType.BYTE, listValues.get(0)), constructOperator, new CastValue(SymbolType.BYTE, listValues.get(1)), currentStmt.getSource(), Comment.NO_COMMENTS);
|
||||||
|
stmtIt.add(assignment);
|
||||||
|
// Move back before the current statement
|
||||||
|
stmtIt.next();
|
||||||
|
// Replace current value with the reference
|
||||||
|
programExpression.set(tmpVar.getRef());
|
||||||
|
Pass2FixInlineConstructorsNew.this.getLog().append("Fixing inline constructor with " + assignment.toString());
|
||||||
|
optimized.set(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return optimized.get();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -4,6 +4,7 @@ import dk.camelot64.kickc.model.Program;
|
|||||||
import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
|
import dk.camelot64.kickc.model.iterator.ProgramExpressionBinary;
|
||||||
import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
|
import dk.camelot64.kickc.model.iterator.ProgramExpressionIterator;
|
||||||
import dk.camelot64.kickc.model.types.*;
|
import dk.camelot64.kickc.model.types.*;
|
||||||
|
import dk.camelot64.kickc.model.values.ConstantInteger;
|
||||||
import dk.camelot64.kickc.model.values.RValue;
|
import dk.camelot64.kickc.model.values.RValue;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
@ -37,6 +38,15 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
|
|||||||
binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
|
binary.addRightCast(leftType, stmtIt, currentBlock.getScope(), getScope());
|
||||||
modified.set(true);
|
modified.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect word literal constructor
|
||||||
|
if(leftType.equals(SymbolType.WORD) && isLiteralWordCandidate(rightType)) {
|
||||||
|
SymbolType conversionType = SymbolType.WORD;
|
||||||
|
getLog().append("Identified literal word (" + conversionType + ") " + binary.getRight().toString() + " in " + (currentStmt == null ? "" : currentStmt.toString(getProgram(), false)));
|
||||||
|
binary.addRightCast(SymbolType.WORD, stmtIt, currentBlock == null ? null : currentBlock.getScope(), getScope());
|
||||||
|
modified.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if(leftType instanceof SymbolTypeIntegerFixed && SymbolType.isInteger(rightType)) {
|
if(leftType instanceof SymbolTypeIntegerFixed && SymbolType.isInteger(rightType)) {
|
||||||
SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType);
|
SymbolType conversionType = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) leftType, (SymbolTypeInteger) rightType);
|
||||||
@ -53,5 +63,14 @@ public class PassNAddTypeConversionAssignment extends Pass2SsaOptimization {
|
|||||||
return modified.get();
|
return modified.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isLiteralWordCandidate(SymbolType rightType) {
|
||||||
|
if(rightType instanceof SymbolTypeArray) {
|
||||||
|
SymbolTypeArray rightArray = (SymbolTypeArray) rightType;
|
||||||
|
if(new ConstantInteger(2L, SymbolType.BYTE).equals(rightArray.getSize()))
|
||||||
|
if(SymbolType.BYTE.equals(rightArray.getElementType()) || SymbolType.NUMBER.equals(rightArray.getElementType()))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1359,6 +1359,21 @@ public class TestPrograms {
|
|||||||
compileAndCompare("inline-assignment");
|
compileAndCompare("inline-assignment");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInlineWord0() throws IOException, URISyntaxException {
|
||||||
|
compileAndCompare("inline-word-0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInlineWord1() throws IOException, URISyntaxException {
|
||||||
|
compileAndCompare("inline-word-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInlineWord2() throws IOException, URISyntaxException {
|
||||||
|
compileAndCompare("inline-word-2");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInlineWord() throws IOException, URISyntaxException {
|
public void testInlineWord() throws IOException, URISyntaxException {
|
||||||
compileAndCompare("inline-word");
|
compileAndCompare("inline-word");
|
||||||
|
7
src/test/kc/inline-word-0.kc
Normal file
7
src/test/kc/inline-word-0.kc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// Tests minimal inline word
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
word w = { 0x02ub, 0x01ub };
|
||||||
|
word* screen = 0x0400;
|
||||||
|
screen[0] = w;
|
||||||
|
}
|
7
src/test/kc/inline-word-1.kc
Normal file
7
src/test/kc/inline-word-1.kc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// Tests minimal inline word
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
word w = { 0x01, 0x02 };
|
||||||
|
word* screen = 0x0400;
|
||||||
|
screen[0] = w;
|
||||||
|
}
|
7
src/test/kc/inline-word-2.kc
Normal file
7
src/test/kc/inline-word-2.kc
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// Tests minimal inline word
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
word w = { 0x01, 0x02ub };
|
||||||
|
word* screen = 0x0400;
|
||||||
|
screen[0] = w;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user