1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-11-23 08:32:39 +00:00

Moved symbol table update functions to PassNTypeInference (cleaning up SymbolTypeInference).

This commit is contained in:
jespergravgaard 2019-05-22 23:38:34 +02:00
parent 9636e26191
commit 2fb9a5baf3
4 changed files with 135 additions and 133 deletions

View File

@ -15,8 +15,12 @@ public interface SymbolType {
SymbolTypeIntegerFixed DWORD = new SymbolTypeIntegerFixed("dword", 0, 4_294_967_296L, false, 32);
/** Signed double word (4 bytes, 32 bits). */
SymbolTypeIntegerFixed SDWORD = new SymbolTypeIntegerFixed("signed dword", -2_147_483_648, 2_147_483_647, true, 32);
/** Integer with unknown size (used for constant expressions). */
/** Integer with unknown size and unknown signedness (used for constant expressions). */
SymbolTypeIntegerAuto NUMBER = new SymbolTypeIntegerAuto("number");
/** Unsigned integer with unknown size (used for constant expressions). */
SymbolTypeIntegerAuto UNUMBER = new SymbolTypeIntegerAuto("unumber");
/** Signed integer with unknown size (used for constant expressions). */
SymbolTypeIntegerAuto SNUMBER = new SymbolTypeIntegerAuto("snumber");
/** String value (treated like byte* ). */
SymbolTypeNamed STRING = new SymbolTypeNamed("string", 99);
/** Boolean value. */

View File

@ -178,114 +178,4 @@ public class SymbolTypeInference {
return rValueType;
}
public static void inferCallLValue(Program program, StatementCall call, boolean reinfer) {
ProgramScope programScope = program.getScope();
LValue lValue = call.getlValue();
if(lValue instanceof VariableRef) {
Variable symbol = programScope.getVariable((VariableRef) lValue);
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
Procedure procedure = programScope.getProcedure(call.getProcedure());
SymbolType type = procedure.getReturnType();
setInferedType(program, call, symbol, type);
}
}
}
public static void inferCallPointerLValue(Program program, StatementCallPointer call, boolean reinfer) {
ProgramScope programScope = program.getScope();
LValue lValue = call.getlValue();
if(lValue instanceof VariableRef) {
Variable symbol = programScope.getVariable((VariableRef) lValue);
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
SymbolType procedureType = inferType(programScope, call.getProcedure());
if(procedureType instanceof SymbolTypeProcedure) {
SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType();
setInferedType(program, call, symbol, returnType);
}
}
}
}
public static void inferPhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable, boolean reinfer) {
ProgramScope programScope = program.getScope();
Variable symbol = programScope.getVariable(phiVariable.getVariable());
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
SymbolType type = null;
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
RValue rValue = phiRValue.getrValue();
SymbolType valueType = inferType(programScope, rValue);
if(type == null) {
type = valueType;
} else if(!type.equals(valueType))
if(valueType instanceof SymbolTypeInteger && type instanceof SymbolTypeInteger) {
type = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) valueType, (SymbolTypeInteger) type);
} else {
throw new CompileError("Phi value has type mismatch "+phiRValue.toString() + " not matching type " + type.getTypeName());
}
}
if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program));
}
symbol.setTypeInferred(type);
}
}
public static void inferAssignmentLValue(Program program, StatementAssignment assignment, boolean reinfer) {
ProgramScope programScope = program.getScope();
LValue lValue = assignment.getlValue();
if(lValue instanceof VariableRef) {
Variable symbol = programScope.getVariable((VariableRef) lValue);
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
// Unresolved symbol - perform inference
Operator operator = assignment.getOperator();
if(assignment.getrValue1() == null && operator == null) {
// Copy operation
RValue rValue = assignment.getrValue2();
SymbolType type = inferType(programScope, rValue);
setInferedType(program, assignment, symbol, type);
} else if(assignment.getrValue1() == null && operator instanceof OperatorUnary) {
// Unary operation
RValue rValue = assignment.getrValue2();
SymbolType type = inferType(programScope, (OperatorUnary) operator, rValue);
setInferedType(program, assignment, symbol, type);
} else if(operator instanceof OperatorBinary) {
// Binary operation
SymbolType type = inferType(
programScope, assignment.getrValue1(),
(OperatorBinary) assignment.getOperator(),
assignment.getrValue2());
setInferedType(program, assignment, symbol, type);
} else {
throw new CompileError("Cannot infer type of " + assignment);
}
// If the type is an array or a string the symbol is constant
if(symbol.getType() instanceof SymbolTypeArray) {
symbol.setDeclaredConstant(true);
} else if(SymbolType.STRING.equals(symbol.getType())) {
symbol.setDeclaredConstant(true);
}
}
}
}
private static void setInferedType(Program program, Statement statement, Variable symbol, SymbolType type) {
if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
program.getLog().append("Inferred type updated to " + type + " in " + statement.toString(program, false));
}
symbol.setTypeInferred(type);
}
public static void inferLValue(Program program, StatementLValue statementLValue, boolean reinfer) {
if(statementLValue instanceof StatementAssignment) {
inferAssignmentLValue(program, (StatementAssignment) statementLValue, reinfer);
} else if(statementLValue instanceof StatementCall) {
inferCallLValue(program, (StatementCall) statementLValue, reinfer);
} else if(statementLValue instanceof StatementCallPointer) {
inferCallPointerLValue(program, (StatementCallPointer) statementLValue, reinfer);
} else {
throw new RuntimeException("LValue statement not implemented " + statementLValue);
}
}
}

View File

@ -12,7 +12,6 @@ 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.symbols.VariableIntermediate;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import java.util.ArrayList;
import java.util.List;
@ -80,7 +79,7 @@ public class Pass1FixLValuesLoHi extends Pass1Base {
VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
VariableRef tmpVarRef = tmpVar.getRef();
statementLValue.setlValue(tmpVarRef);
SymbolTypeInference.inferLValue(getProgram(), statementLValue, false);
PassNTypeInference.inferLValue(getProgram(), statementLValue);
// Insert an extra "set low" assignment statement
Statement setLoHiAssignment = new StatementAssignment(loHiVar, loHiVar, loHiOperator, tmpVarRef, statementLValue.getSource(), new ArrayList<>());
statementsIt.add(setLoHiAssignment);

View File

@ -3,10 +3,17 @@ 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.Operator;
import dk.camelot64.kickc.model.operators.OperatorBinary;
import dk.camelot64.kickc.model.operators.OperatorUnary;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
import dk.camelot64.kickc.model.symbols.ProgramScope;
import dk.camelot64.kickc.model.symbols.Variable;
import dk.camelot64.kickc.model.types.*;
import dk.camelot64.kickc.model.values.LValue;
import dk.camelot64.kickc.model.values.RValue;
import dk.camelot64.kickc.model.values.VariableRef;
/**
* Pass through the generated statements inferring types of unresolved variables.
@ -18,34 +25,136 @@ public class PassNTypeInference extends Pass2SsaOptimization {
super(program);
}
@Override
public boolean step() {
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
for(Statement statement : block.getStatements()) {
if(statement instanceof StatementAssignment) {
StatementAssignment assignment = (StatementAssignment) statement;
try {
SymbolTypeInference.inferAssignmentLValue(getProgram(), assignment, false);
} catch(CompileError e) {
throw new CompileError(e.getMessage(), statement.getSource());
}
if(statement instanceof StatementLValue) {
inferLValue(getProgram(), (StatementLValue) statement);
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
try {
SymbolTypeInference.inferPhiVariable(getProgram(), phiVariable, false);
inferPhiVariable(getProgram(), phiVariable);
}
}
} catch(CompileError e) {
throw new CompileError(e.getMessage(), statement.getSource());
}
}
} else if(statement instanceof StatementCall) {
SymbolTypeInference.inferCallLValue(getProgram(), (StatementCall) statement, false);
} else if(statement instanceof StatementCallPointer) {
SymbolTypeInference.inferCallPointerLValue(getProgram(), (StatementCallPointer) statement, false);
}
}
}
return false;
}
public static void inferLValue(Program program, StatementLValue statementLValue) {
if(statementLValue instanceof StatementAssignment) {
inferAssignmentLValue(program, (StatementAssignment) statementLValue);
} else if(statementLValue instanceof StatementCall) {
inferCallLValue(program, (StatementCall) statementLValue);
} else if(statementLValue instanceof StatementCallPointer) {
inferCallPointerLValue(program, (StatementCallPointer) statementLValue);
} else {
throw new RuntimeException("LValue statement not implemented " + statementLValue);
}
}
private static void inferCallLValue(Program program, StatementCall call) {
ProgramScope programScope = program.getScope();
LValue lValue = call.getlValue();
if(lValue instanceof VariableRef) {
Variable symbol = programScope.getVariable((VariableRef) lValue);
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
Procedure procedure = programScope.getProcedure(call.getProcedure());
SymbolType type = procedure.getReturnType();
setInferedType(program, call, symbol, type);
}
}
}
private static void inferCallPointerLValue(Program program, StatementCallPointer call) {
ProgramScope programScope = program.getScope();
LValue lValue = call.getlValue();
if(lValue instanceof VariableRef) {
Variable symbol = programScope.getVariable((VariableRef) lValue);
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
SymbolType procedureType = SymbolTypeInference.inferType(programScope, call.getProcedure());
if(procedureType instanceof SymbolTypeProcedure) {
SymbolType returnType = ((SymbolTypeProcedure) procedureType).getReturnType();
setInferedType(program, call, symbol, returnType);
}
}
}
}
private static void inferPhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable) {
ProgramScope programScope = program.getScope();
Variable symbol = programScope.getVariable(phiVariable.getVariable());
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
SymbolType type = null;
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
RValue rValue = phiRValue.getrValue();
SymbolType valueType = SymbolTypeInference.inferType(programScope, rValue);
if(type == null) {
type = valueType;
} else if(!type.equals(valueType))
if(valueType instanceof SymbolTypeInteger && type instanceof SymbolTypeInteger) {
type = SymbolTypeConversion.convertedMathType((SymbolTypeInteger) valueType, (SymbolTypeInteger) type);
} else {
throw new CompileError("Phi value has type mismatch " + phiRValue.toString() + " not matching type " + type.getTypeName());
}
}
if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program));
}
symbol.setTypeInferred(type);
}
}
private static void inferAssignmentLValue(Program program, StatementAssignment assignment) {
ProgramScope programScope = program.getScope();
LValue lValue = assignment.getlValue();
if(lValue instanceof VariableRef) {
Variable symbol = programScope.getVariable((VariableRef) lValue);
if(SymbolType.VAR.equals(symbol.getType()) || SymbolType.NUMBER.equals(symbol.getType())) {
// Unresolved symbol - perform inference
Operator operator = assignment.getOperator();
if(assignment.getrValue1() == null && operator == null) {
// Copy operation
RValue rValue = assignment.getrValue2();
SymbolType type = SymbolTypeInference.inferType(programScope, rValue);
setInferedType(program, assignment, symbol, type);
} else if(assignment.getrValue1() == null && operator instanceof OperatorUnary) {
// Unary operation
RValue rValue = assignment.getrValue2();
SymbolType type = SymbolTypeInference.inferType(programScope, (OperatorUnary) operator, rValue);
setInferedType(program, assignment, symbol, type);
} else if(operator instanceof OperatorBinary) {
// Binary operation
SymbolType type = SymbolTypeInference.inferType(
programScope, assignment.getrValue1(),
(OperatorBinary) assignment.getOperator(),
assignment.getrValue2());
setInferedType(program, assignment, symbol, type);
} else {
throw new CompileError("Cannot infer type of " + assignment);
}
// If the type is an array or a string the symbol is constant
if(symbol.getType() instanceof SymbolTypeArray) {
symbol.setDeclaredConstant(true);
} else if(SymbolType.STRING.equals(symbol.getType())) {
symbol.setDeclaredConstant(true);
}
}
}
}
private static void setInferedType(Program program, Statement statement, Variable symbol, SymbolType type) {
if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
program.getLog().append("Inferred type updated to " + type + " in " + statement.toString(program, false));
}
symbol.setTypeInferred(type);
}
}