mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-11-20 02:32:36 +00:00
Working on fixing test errors.
This commit is contained in:
parent
87e6fecb8f
commit
47aa623f25
@ -11,11 +11,10 @@ import dk.camelot64.kickc.model.values.RValue;
|
||||
|
||||
/**
|
||||
* Rules for converting integer types.
|
||||
*
|
||||
* <p>
|
||||
* Integer conversion implements C99 6.3.1.8 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf#page=70
|
||||
*
|
||||
* <p>
|
||||
* The special number type is converted as described here https://gitlab.com/camelot/kickc/issues/181
|
||||
*
|
||||
*/
|
||||
public class SymbolTypeConversion {
|
||||
|
||||
@ -37,19 +36,19 @@ public class SymbolTypeConversion {
|
||||
if(type1.equals(type2))
|
||||
return type1;
|
||||
// C99 6.3.1.8 b. If both are signed or both are unsigned then the smallest type is converted to the size of the large type (byte->word->sword, sbyte->sword->sdword)
|
||||
if(fixed1.isSigned()==fixed2.isSigned())
|
||||
return (fixed1.getBits()>fixed2.getBits()) ? fixed1 : fixed2;
|
||||
if(fixed1.isSigned() == fixed2.isSigned())
|
||||
return (fixed1.getBits() > fixed2.getBits()) ? fixed1 : fixed2;
|
||||
// C99 6.3.1.8 c. One is signed and one unsigned.
|
||||
// If the signed type can contain all values of the unsigned type then the unsigned value is converted to the signed type. (byte->sword, byte->sdword, word->sdword).
|
||||
SymbolTypeIntegerFixed typeS, typeU;
|
||||
if(fixed1.isSigned()) {
|
||||
typeS = fixed1;
|
||||
typeU = fixed2;
|
||||
} else {
|
||||
} else {
|
||||
typeS = fixed2;
|
||||
typeU = fixed1;
|
||||
}
|
||||
if(typeS.getBits()>typeU.getBits())
|
||||
if(typeS.getBits() > typeU.getBits())
|
||||
return typeS;
|
||||
// C99 6.3.1.8 d. The unsigned type is the same size as or larger than the signed type.
|
||||
// The signed value is first converted to the size of the unsigned type and then converted to unsigned changing the sign and the value
|
||||
@ -59,6 +58,7 @@ public class SymbolTypeConversion {
|
||||
|
||||
/**
|
||||
* Find the integer type that results from a binary operator according to the special number type conversion https://gitlab.com/camelot/kickc/issues/181
|
||||
*
|
||||
* @param left The left value
|
||||
* @param right The right value
|
||||
* @param symbols The program scope symbols (used for looking up symbols and constants)
|
||||
@ -92,7 +92,8 @@ public class SymbolTypeConversion {
|
||||
fixedType = (SymbolTypeIntegerFixed) leftType;
|
||||
} else {
|
||||
// Binary operator combining number and non-integer
|
||||
throw new CompileError("Error! Incompatible operands " + left.toString() + " and " + right.toString(), currentStmt);
|
||||
return null;
|
||||
//throw new CompileError("Error! Incompatible operands " + left.toString() + " and " + right.toString(), currentStmt);
|
||||
}
|
||||
|
||||
if(numberVal instanceof ConstantValue) {
|
||||
|
@ -0,0 +1,31 @@
|
||||
package dk.camelot64.kickc.model.types;
|
||||
|
||||
/** Container for function checking if types of an assignment match up */
|
||||
public class SymbolTypeMatch {
|
||||
|
||||
/**
|
||||
* Determines if the types of an assignment match up properly
|
||||
* @param lValueType The type of the LValue
|
||||
* @param rValueType The type of the RValue
|
||||
* @return true if the types match up
|
||||
*/
|
||||
public static boolean assignmentTypeMatch(SymbolType lValueType, SymbolType rValueType) {
|
||||
if(lValueType.equals(rValueType)) {
|
||||
return true;
|
||||
}
|
||||
if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
|
||||
// L-value is still a number - constants are probably not done being identified & typed
|
||||
return true;
|
||||
}
|
||||
if(SymbolType.STRING.equals(rValueType) && lValueType instanceof SymbolTypePointer && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) {
|
||||
// String value can be assigned into a pointer
|
||||
return true;
|
||||
}
|
||||
if(lValueType instanceof SymbolTypePointer && rValueType instanceof SymbolTypePointer && assignmentTypeMatch(((SymbolTypePointer) lValueType).getElementType(), ((SymbolTypePointer) rValueType).getElementType())) {
|
||||
// Pointer types assigned from each other
|
||||
// TODO: Maybe handle sizes
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import dk.camelot64.kickc.model.statements.StatementAssignment;
|
||||
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeMatch;
|
||||
import dk.camelot64.kickc.model.values.LValue;
|
||||
import dk.camelot64.kickc.model.values.RValue;
|
||||
|
||||
@ -51,17 +51,7 @@ public class Pass2AssertTypeMatch extends Pass2SsaAssertion {
|
||||
LValue lValue = statement.getlValue();
|
||||
SymbolType lValueType = SymbolTypeInference.inferType(getScope(), lValue);
|
||||
SymbolType rValueType = SymbolTypeInference.inferTypeRValue(getScope(), statement);
|
||||
if(lValueType.equals(rValueType)) {
|
||||
return;
|
||||
}
|
||||
if(SymbolType.NUMBER.equals(rValueType) && SymbolType.isInteger(lValueType)) {
|
||||
// L-value is still a number - constants are probably not done being identified & typed
|
||||
return;
|
||||
}
|
||||
if(lValueType instanceof SymbolTypePointer && SymbolType.STRING.equals(rValueType) && ((SymbolTypePointer) lValueType).getElementType().equals(SymbolType.BYTE)) {
|
||||
// String value can be assigned into a pointer
|
||||
return;
|
||||
}
|
||||
if(SymbolTypeMatch.assignmentTypeMatch(lValueType, rValueType)) return;
|
||||
// Types do not match
|
||||
getLog().append("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false));
|
||||
throw new CompileError("ERROR! Type mismatch (" + lValueType.getTypeName() + ") cannot be assigned from (" + rValueType.getTypeName() + "). In " + statement.toString(getProgram(), false), statement.getSource());
|
||||
|
@ -15,11 +15,14 @@ import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||
import dk.camelot64.kickc.model.symbols.Scope;
|
||||
import dk.camelot64.kickc.model.symbols.Variable;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeArray;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeMatch;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Compiler Pass propagating constants in expressions eliminating constant variables
|
||||
@ -69,24 +72,19 @@ public class Pass2ConstantIdentification extends Pass2SsaOptimization {
|
||||
ConstantValue constVal = constVarVal.getConstantValue();
|
||||
SymbolType valueType = SymbolTypeInference.inferType(getScope(), constVal);
|
||||
SymbolType variableType = variable.getType();
|
||||
SymbolType constType = variableType;
|
||||
|
||||
if(!valueType.equals(variableType)) {
|
||||
if(variableType.equals(valueType)) {
|
||||
constType = variableType;
|
||||
} else {
|
||||
if(!SymbolTypeMatch.assignmentTypeMatch(variableType, valueType)) {
|
||||
throw new CompileError(
|
||||
"Constant variable has a non-matching type \n variable: " + variable.toString(getProgram()) +
|
||||
"\n value: (" + valueType.toString() + ") " + constVal.calculateLiteral(getScope()) +
|
||||
"\n value definition: " + constVal.toString(getProgram())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ConstantVar constantVar = new ConstantVar(
|
||||
variable.getName(),
|
||||
constScope,
|
||||
constType,
|
||||
variableType,
|
||||
constVal);
|
||||
constantVar.setDeclaredAlignment(variable.getDeclaredAlignment());
|
||||
constantVar.setDeclaredRegister(variable.getDeclaredRegister());
|
||||
|
@ -16,7 +16,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Compiler Pass consolidating L-values that are constant into a single {@link ConstantValue}
|
||||
* Compiler Pass consolidating R-values that are constant into a single {@link ConstantValue}
|
||||
*/
|
||||
public class Pass2ConstantRValueConsolidation extends Pass2SsaOptimization {
|
||||
|
||||
|
@ -76,12 +76,12 @@ public class Pass2SizeOfSimplification extends Pass2SsaOptimization {
|
||||
SymbolTypeArray arrayType = (SymbolTypeArray) symbolType;
|
||||
RValue arraySize = arrayType.getSize();
|
||||
if(arraySize instanceof ConstantValue) {
|
||||
getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
|
||||
getLog().append("Resolving array sizeof() " + unary.toString(getProgram()));
|
||||
ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType());
|
||||
programValue.set(new ConstantBinary((ConstantValue) arraySize, Operators.MULTIPLY, sizeOfConstantVar));
|
||||
modified.set(true);
|
||||
} else if(constant.getValue() instanceof ConstantArrayList) {
|
||||
getLog().append("Resolving sizeof() " + unary.toString(getProgram()));
|
||||
getLog().append("Resolving array sizeof() " + unary.toString(getProgram()));
|
||||
int size = ((ConstantArrayList) constant.getValue()).getElements().size();
|
||||
ConstantRef sizeOfConstantVar = OperatorSizeOf.getSizeOfConstantVar(getScope(), arrayType.getElementType());
|
||||
programValue.set(new ConstantBinary(new ConstantInteger((long) size), Operators.MULTIPLY, sizeOfConstantVar));
|
||||
@ -97,6 +97,7 @@ public class Pass2SizeOfSimplification extends Pass2SsaOptimization {
|
||||
if(stringLiteral instanceof ConstantString) {
|
||||
ConstantString constString = (ConstantString) stringLiteral;
|
||||
int length = constString.getString().length();
|
||||
getLog().append("Resolving string sizeof() " + unary.toString(getProgram()));
|
||||
ConstantRef sizeOfChar = OperatorSizeOf.getSizeOfConstantVar(getScope(), SymbolType.BYTE);
|
||||
programValue.set(new ConstantBinary(new ConstantInteger((long) length), Operators.MULTIPLY, sizeOfChar));
|
||||
modified.set(true);
|
||||
|
@ -34,7 +34,7 @@ public class TestPrograms {
|
||||
|
||||
@Test
|
||||
public void testHelloWorld0() throws IOException, URISyntaxException {
|
||||
compileAndCompare("helloworld0", log());
|
||||
compileAndCompare("helloworld0");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Tests minimal hello world
|
||||
|
||||
byte[] msg = "hello world";
|
||||
byte[] msg = "hello world!";
|
||||
byte* SCREEN = 0x0400;
|
||||
|
||||
void main() {
|
||||
|
Loading…
Reference in New Issue
Block a user