From 2fb9a5baf3b33b9775864c301be18b5409964d1e Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Wed, 22 May 2019 23:38:34 +0200 Subject: [PATCH] Moved symbol table update functions to PassNTypeInference (cleaning up SymbolTypeInference). --- .../kickc/model/types/SymbolType.java | 6 +- .../model/types/SymbolTypeInference.java | 110 ------------- .../kickc/passes/Pass1FixLValuesLoHi.java | 3 +- .../kickc/passes/PassNTypeInference.java | 149 +++++++++++++++--- 4 files changed, 135 insertions(+), 133 deletions(-) diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java index 34747ed97..bff9cc686 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolType.java @@ -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. */ diff --git a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java index 4a244cbdb..6c308eec4 100644 --- a/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/model/types/SymbolTypeInference.java @@ -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); - } - } - } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java index 1b2f990e8..68d13d0e3 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass1FixLValuesLoHi.java @@ -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); diff --git a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java index d4baa4e7d..d37114431 100644 --- a/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java +++ b/src/main/java/dk/camelot64/kickc/passes/PassNTypeInference.java @@ -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()); - } - } else if(statement instanceof StatementPhiBlock) { - for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) { - try { - SymbolTypeInference.inferPhiVariable(getProgram(), phiVariable, false); - } catch(CompileError e) { - throw new CompileError(e.getMessage(), statement.getSource()); + try { + if(statement instanceof StatementLValue) { + inferLValue(getProgram(), (StatementLValue) statement); + } else if(statement instanceof StatementPhiBlock) { + for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) { + inferPhiVariable(getProgram(), phiVariable); } } - } else if(statement instanceof StatementCall) { - SymbolTypeInference.inferCallLValue(getProgram(), (StatementCall) statement, false); - } else if(statement instanceof StatementCallPointer) { - SymbolTypeInference.inferCallPointerLValue(getProgram(), (StatementCallPointer) statement, false); + } catch(CompileError e) { + throw new CompileError(e.getMessage(), statement.getSource()); } - } } 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); + } + + }