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:
parent
9636e26191
commit
2fb9a5baf3
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user