mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-17 10:30:43 +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);
|
SymbolTypeIntegerFixed DWORD = new SymbolTypeIntegerFixed("dword", 0, 4_294_967_296L, false, 32);
|
||||||
/** Signed double word (4 bytes, 32 bits). */
|
/** Signed double word (4 bytes, 32 bits). */
|
||||||
SymbolTypeIntegerFixed SDWORD = new SymbolTypeIntegerFixed("signed dword", -2_147_483_648, 2_147_483_647, true, 32);
|
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");
|
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* ). */
|
/** String value (treated like byte* ). */
|
||||||
SymbolTypeNamed STRING = new SymbolTypeNamed("string", 99);
|
SymbolTypeNamed STRING = new SymbolTypeNamed("string", 99);
|
||||||
/** Boolean value. */
|
/** Boolean value. */
|
||||||
|
@ -178,114 +178,4 @@ public class SymbolTypeInference {
|
|||||||
return rValueType;
|
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.Scope;
|
||||||
import dk.camelot64.kickc.model.symbols.Variable;
|
import dk.camelot64.kickc.model.symbols.Variable;
|
||||||
import dk.camelot64.kickc.model.symbols.VariableIntermediate;
|
import dk.camelot64.kickc.model.symbols.VariableIntermediate;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -80,7 +79,7 @@ public class Pass1FixLValuesLoHi extends Pass1Base {
|
|||||||
VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
|
VariableIntermediate tmpVar = currentScope.addVariableIntermediate();
|
||||||
VariableRef tmpVarRef = tmpVar.getRef();
|
VariableRef tmpVarRef = tmpVar.getRef();
|
||||||
statementLValue.setlValue(tmpVarRef);
|
statementLValue.setlValue(tmpVarRef);
|
||||||
SymbolTypeInference.inferLValue(getProgram(), statementLValue, false);
|
PassNTypeInference.inferLValue(getProgram(), statementLValue);
|
||||||
// Insert an extra "set low" assignment statement
|
// Insert an extra "set low" assignment statement
|
||||||
Statement setLoHiAssignment = new StatementAssignment(loHiVar, loHiVar, loHiOperator, tmpVarRef, statementLValue.getSource(), new ArrayList<>());
|
Statement setLoHiAssignment = new StatementAssignment(loHiVar, loHiVar, loHiOperator, tmpVarRef, statementLValue.getSource(), new ArrayList<>());
|
||||||
statementsIt.add(setLoHiAssignment);
|
statementsIt.add(setLoHiAssignment);
|
||||||
|
@ -3,10 +3,17 @@ package dk.camelot64.kickc.passes;
|
|||||||
import dk.camelot64.kickc.model.CompileError;
|
import dk.camelot64.kickc.model.CompileError;
|
||||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||||
import dk.camelot64.kickc.model.Program;
|
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.statements.*;
|
||||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||||
import dk.camelot64.kickc.model.symbols.Scope;
|
import dk.camelot64.kickc.model.symbols.ProgramScope;
|
||||||
import dk.camelot64.kickc.model.types.SymbolTypeInference;
|
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.
|
* Pass through the generated statements inferring types of unresolved variables.
|
||||||
@ -18,34 +25,136 @@ public class PassNTypeInference extends Pass2SsaOptimization {
|
|||||||
super(program);
|
super(program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean step() {
|
public boolean step() {
|
||||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||||
for(Statement statement : block.getStatements()) {
|
for(Statement statement : block.getStatements()) {
|
||||||
if(statement instanceof StatementAssignment) {
|
|
||||||
StatementAssignment assignment = (StatementAssignment) statement;
|
|
||||||
try {
|
try {
|
||||||
SymbolTypeInference.inferAssignmentLValue(getProgram(), assignment, false);
|
if(statement instanceof StatementLValue) {
|
||||||
} catch(CompileError e) {
|
inferLValue(getProgram(), (StatementLValue) statement);
|
||||||
throw new CompileError(e.getMessage(), statement.getSource());
|
|
||||||
}
|
|
||||||
} else if(statement instanceof StatementPhiBlock) {
|
} else if(statement instanceof StatementPhiBlock) {
|
||||||
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
|
||||||
try {
|
inferPhiVariable(getProgram(), phiVariable);
|
||||||
SymbolTypeInference.inferPhiVariable(getProgram(), phiVariable, false);
|
}
|
||||||
|
}
|
||||||
} catch(CompileError e) {
|
} catch(CompileError e) {
|
||||||
throw new CompileError(e.getMessage(), statement.getSource());
|
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;
|
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…
x
Reference in New Issue
Block a user