diff --git a/src/dk/camelot64/kickc/asm/AsmFragment.java b/src/dk/camelot64/kickc/asm/AsmFragment.java index 00ebdcb29..42cce8d88 100644 --- a/src/dk/camelot64/kickc/asm/AsmFragment.java +++ b/src/dk/camelot64/kickc/asm/AsmFragment.java @@ -133,11 +133,11 @@ public class AsmFragment { signature.append("_then_"); Label destination = conditionalJump.getDestination(); ControlFlowBlock destinationBlock = graph.getBlock(destination); - String destinationLabel = destination.getName(); + String destinationLabel = destination.getLocalName(); if (destinationBlock.hasPhiStatements()) { - destinationLabel = destination.getName() + "_from_" + block.getLabel().getName(); + destinationLabel = destination.getLocalName() + "_from_" + block.getLabel().getLocalName(); } - signature.append(bind(new Label(destinationLabel, false))); + signature.append(bind(new Label(destinationLabel, destination.getScope(),false))); return signature.toString(); } @@ -348,7 +348,7 @@ public class AsmFragment { bound = Integer.toString(boundInt.getNumber()); } } else if (boundValue instanceof Label) { - bound = ((Label) boundValue).getName().replace('@', 'B'); + bound = ((Label) boundValue).getLocalName().replace('@', 'B'); } else { throw new RuntimeException("Bound Value Type not implemented " + boundValue); } diff --git a/src/dk/camelot64/kickc/icl/ControlFlowBlock.java b/src/dk/camelot64/kickc/icl/ControlFlowBlock.java index 12d411846..deba039b8 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowBlock.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowBlock.java @@ -72,11 +72,11 @@ public class ControlFlowBlock { @Override public String toString() { StringBuffer out = new StringBuffer(); - out.append(label.getName() + ":" ); + out.append(label.getLocalName() + ":" ); if(predecessors.size()>0) { out.append(" from"); for (ControlFlowBlock predecessor : predecessors) { - out.append(" " + predecessor.getLabel().getName()); + out.append(" " + predecessor.getLabel().getLocalName()); } } out.append("\n"); @@ -85,7 +85,7 @@ public class ControlFlowBlock { } if(defaultSuccessor!=null) { out.append(" to:"); - out.append(defaultSuccessor.getLabel().getName()); + out.append(defaultSuccessor.getLabel().getLocalName()); } out.append("\n"); return out.toString(); diff --git a/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java b/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java index 390e03d3e..21c2bb01d 100644 --- a/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java +++ b/src/dk/camelot64/kickc/icl/ControlFlowGraphBaseVisitor.java @@ -27,8 +27,8 @@ public class ControlFlowGraphBaseVisitor { return visitConditionalJump((StatementConditionalJump) statement); } else if(statement instanceof StatementJump) { return visitJump((StatementJump) statement); - } else if(statement instanceof StatementJumpTarget) { - return visitJumpTarget((StatementJumpTarget) statement); + } else if(statement instanceof StatementLabel) { + return visitJumpTarget((StatementLabel) statement); } else if(statement instanceof StatementPhi) { return visitPhi((StatementPhi) statement); } else { @@ -48,7 +48,7 @@ public class ControlFlowGraphBaseVisitor { return null; } - public T visitJumpTarget(StatementJumpTarget jumpTarget) { + public T visitJumpTarget(StatementLabel jumpTarget) { return null; } diff --git a/src/dk/camelot64/kickc/icl/Label.java b/src/dk/camelot64/kickc/icl/Label.java index 0e3668674..c63872888 100644 --- a/src/dk/camelot64/kickc/icl/Label.java +++ b/src/dk/camelot64/kickc/icl/Label.java @@ -1,22 +1,36 @@ package dk.camelot64.kickc.icl; -/** A Symbol (variable, jump label, etc.) */ +/** A jump label */ public class Label implements Symbol { /** The name of the label. */ private String name; + /** The name of the containing scope */ + private SymbolTable scope; + private boolean intermediate; - public Label(String name, boolean intermediate) { + public Label(String name, SymbolTable scope, boolean intermediate) { this.name = name; + this.scope = scope; this.intermediate = intermediate; } - public String getName() { + public String getLocalName() { return name; } + @Override + public SymbolTable getScope() { + return scope; + } + + @Override + public String getFullName() { + return SymbolTable.getFullName(this); + } + public boolean isIntermediate() { return intermediate; } @@ -25,27 +39,32 @@ public class Label implements Symbol { return SymbolTypeBasic.LABEL; } - @Override - public String toString() { - return "("+getType().getTypeName() + ") "+name; + public String getTypedName() { + return "("+getType().getTypeName() + ") "+getFullName(); } @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; - Label that = (Label) o; + Label label = (Label) o; - return name.equals(that.name); + if (intermediate != label.intermediate) return false; + if (!name.equals(label.name)) return false; + return scope != null ? scope.equals(label.scope) : label.scope == null; } @Override public int hashCode() { - return name.hashCode(); + int result = name.hashCode(); + result = 31 * result + (scope != null ? scope.hashCode() : 0); + result = 31 * result + (intermediate ? 1 : 0); + return result; + } + + @Override + public String toString() { + return getTypedName(); } } diff --git a/src/dk/camelot64/kickc/icl/Pass1GenerateControlFlowGraph.java b/src/dk/camelot64/kickc/icl/Pass1GenerateControlFlowGraph.java index 0449dd22e..78c27e759 100644 --- a/src/dk/camelot64/kickc/icl/Pass1GenerateControlFlowGraph.java +++ b/src/dk/camelot64/kickc/icl/Pass1GenerateControlFlowGraph.java @@ -1,8 +1,6 @@ package dk.camelot64.kickc.icl; -import java.util.ArrayList; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; /** Pass that generates a control flow graph for the program */ @@ -20,13 +18,13 @@ public class Pass1GenerateControlFlowGraph { } public ControlFlowGraph generate(StatementSequence sequence) { - this.firstBlock = getOrCreateBlock(symbolTable.newNamedJumpLabel(BEGIN_BLOCK_NAME)); + this.firstBlock = getOrCreateBlock(symbolTable.addLabel(BEGIN_BLOCK_NAME)); ControlFlowBlock currentBlock = this.firstBlock; - sequence.addStatement(new StatementJumpTarget(symbolTable.newNamedJumpLabel(END_BLOCK_NAME))); + sequence.addStatement(new StatementLabel(symbolTable.addLabel(END_BLOCK_NAME))); for (Statement statement : sequence.getStatements()) { - if(statement instanceof StatementJumpTarget) { - StatementJumpTarget statementJumpTarget = (StatementJumpTarget) statement; - ControlFlowBlock nextBlock = getOrCreateBlock(statementJumpTarget.getLabel()); + if(statement instanceof StatementLabel) { + StatementLabel statementLabel = (StatementLabel) statement; + ControlFlowBlock nextBlock = getOrCreateBlock(statementLabel.getLabel()); currentBlock.setDefaultSuccessor(nextBlock); nextBlock.addPredecessor(currentBlock); currentBlock = nextBlock; @@ -35,13 +33,13 @@ public class Pass1GenerateControlFlowGraph { ControlFlowBlock jmpBlock = getOrCreateBlock(statementJump.getDestination()); currentBlock.setDefaultSuccessor(jmpBlock); jmpBlock.addPredecessor(currentBlock); - ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.newIntermediateJumpLabel()); + ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.addLabelIntermediate()); currentBlock = nextBlock; } else if(statement instanceof StatementConditionalJump) { currentBlock.addStatement(statement); StatementConditionalJump statementConditionalJump = (StatementConditionalJump) statement; ControlFlowBlock jmpBlock = getOrCreateBlock(statementConditionalJump.getDestination()); - ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.newIntermediateJumpLabel()); + ControlFlowBlock nextBlock = getOrCreateBlock(symbolTable.addLabelIntermediate()); currentBlock.setDefaultSuccessor(nextBlock); currentBlock.setConditionalSuccessor(jmpBlock); nextBlock.addPredecessor(currentBlock); diff --git a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java index 2746ae370..43721e228 100644 --- a/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java +++ b/src/dk/camelot64/kickc/icl/Pass1GenerateStatementSequence.java @@ -4,17 +4,34 @@ import dk.camelot64.kickc.parser.KickCBaseVisitor; import dk.camelot64.kickc.parser.KickCParser; import org.antlr.v4.runtime.tree.TerminalNode; -/** Generates program SSA form by visiting the ANTLR4 parse tree*/ +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +/** + * Generates program SSA form by visiting the ANTLR4 parse tree + */ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { - private SymbolTable symbolTable; + private SymbolTable programSymbols; + private Stack symbolsStack; private StatementSequence sequence; public Pass1GenerateStatementSequence() { - this.symbolTable = new SymbolTable(); + this.programSymbols = new SymbolTable(); + this.symbolsStack = new Stack<>(); + symbolsStack.push(programSymbols); this.sequence = new StatementSequence(); } + public SymbolTable getProgramSymbols() { + return programSymbols; + } + + private SymbolTable getCurrentSymbols() { + return symbolsStack.peek(); + } + public void generate(KickCParser.FileContext file) { this.visit(file); } @@ -27,7 +44,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public Void visitStmtSeq(KickCParser.StmtSeqContext ctx) { - for(int i=0; i { @Override public Void visitStmtIfElse(KickCParser.StmtIfElseContext ctx) { RValue rValue = (RValue) this.visit(ctx.expr()); - Label ifJumpLabel = symbolTable.newIntermediateJumpLabel(); - Label elseJumpLabel = symbolTable.newIntermediateJumpLabel(); + Label ifJumpLabel = getCurrentSymbols().addLabelIntermediate(); + Label elseJumpLabel = getCurrentSymbols().addLabelIntermediate(); Statement ifJmpStmt = new StatementConditionalJump(rValue, ifJumpLabel); sequence.addStatement(ifJmpStmt); Statement elseJmpStmt = new StatementJump(elseJumpLabel); sequence.addStatement(elseJmpStmt); - StatementJumpTarget ifJumpTarget = new StatementJumpTarget(ifJumpLabel); + StatementLabel ifJumpTarget = new StatementLabel(ifJumpLabel); sequence.addStatement(ifJumpTarget); this.visit(ctx.stmt(0)); KickCParser.StmtContext elseStmt = ctx.stmt(1); - if(elseStmt!=null) { - Label endJumpLabel = symbolTable.newIntermediateJumpLabel(); + if (elseStmt != null) { + Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); Statement endJmpStmt = new StatementJump(endJumpLabel); sequence.addStatement(endJmpStmt); - StatementJumpTarget elseJumpTarget = new StatementJumpTarget(elseJumpLabel); + StatementLabel elseJumpTarget = new StatementLabel(elseJumpLabel); sequence.addStatement(elseJumpTarget); this.visit(elseStmt); - StatementJumpTarget endJumpTarget = new StatementJumpTarget(endJumpLabel); + StatementLabel endJumpTarget = new StatementLabel(endJumpLabel); sequence.addStatement(endJumpTarget); - } else { - StatementJumpTarget elseJumpTarget = new StatementJumpTarget(elseJumpLabel); + } else { + StatementLabel elseJumpTarget = new StatementLabel(elseJumpLabel); sequence.addStatement(elseJumpTarget); } return null; @@ -76,30 +93,30 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public Void visitStmtWhile(KickCParser.StmtWhileContext ctx) { - Label beginJumpLabel = symbolTable.newIntermediateJumpLabel(); - Label doJumpLabel = symbolTable.newIntermediateJumpLabel(); - Label endJumpLabel = symbolTable.newIntermediateJumpLabel(); - StatementJumpTarget beginJumpTarget = new StatementJumpTarget(beginJumpLabel); + Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate(); + Label doJumpLabel = getCurrentSymbols().addLabelIntermediate(); + Label endJumpLabel = getCurrentSymbols().addLabelIntermediate(); + StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel); sequence.addStatement(beginJumpTarget); RValue rValue = (RValue) this.visit(ctx.expr()); Statement doJmpStmt = new StatementConditionalJump(rValue, doJumpLabel); sequence.addStatement(doJmpStmt); Statement endJmpStmt = new StatementJump(endJumpLabel); sequence.addStatement(endJmpStmt); - StatementJumpTarget doJumpTarget = new StatementJumpTarget(doJumpLabel); + StatementLabel doJumpTarget = new StatementLabel(doJumpLabel); sequence.addStatement(doJumpTarget); this.visit(ctx.stmt()); Statement beginJmpStmt = new StatementJump(beginJumpLabel); sequence.addStatement(beginJmpStmt); - StatementJumpTarget endJumpTarget = new StatementJumpTarget(endJumpLabel); + StatementLabel endJumpTarget = new StatementLabel(endJumpLabel); sequence.addStatement(endJumpTarget); return null; } @Override public Void visitStmtDoWhile(KickCParser.StmtDoWhileContext ctx) { - Label beginJumpLabel = symbolTable.newIntermediateJumpLabel(); - StatementJumpTarget beginJumpTarget = new StatementJumpTarget(beginJumpLabel); + Label beginJumpLabel = getCurrentSymbols().addLabelIntermediate(); + StatementLabel beginJumpTarget = new StatementLabel(beginJumpLabel); sequence.addStatement(beginJumpTarget); this.visit(ctx.stmt()); RValue rValue = (RValue) this.visit(ctx.expr()); @@ -110,22 +127,55 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public Void visitStmtFunction(KickCParser.StmtFunctionContext ctx) { - throw new RuntimeException("Not implemented"); + SymbolType type = (SymbolType) visit(ctx.typeDecl()); + String name = ctx.NAME().getText(); + Procedure procedure = getCurrentSymbols().addProcedure(name, type); + symbolsStack.push(procedure); + List parameterList = (List) this.visit(ctx.parameterListDecl()); + procedure.setParameters(parameterList); + sequence.addStatement(new StatementProcedure(procedure)); + this.visit(ctx.stmtSeq()); + symbolsStack.pop(); + return null; + } + + @Override + public List visitParameterListDecl(KickCParser.ParameterListDeclContext ctx) { + ArrayList parameterDecls = new ArrayList<>(); + for (KickCParser.ParameterDeclContext parameterDeclCtx: ctx.parameterDecl()) { + Variable parameterDecl = (Variable) this.visit(parameterDeclCtx); + parameterDecls.add(parameterDecl); + } + return parameterDecls; + } + + @Override + public Variable visitParameterDecl(KickCParser.ParameterDeclContext ctx) { + SymbolType type = (SymbolType) this.visit(ctx.typeDecl()); + VariableUnversioned param = new VariableUnversioned(ctx.NAME().getText(), getCurrentSymbols(), type); + return param; } @Override public Void visitStmtReturn(KickCParser.StmtReturnContext ctx) { - throw new RuntimeException("Not implemented"); + KickCParser.ExprContext exprCtx = ctx.expr(); + RValue rValue = null; + if (exprCtx != null) { + rValue = (RValue) this.visit(exprCtx); + } + Statement stmt = new StatementReturn(rValue); + sequence.addStatement(stmt); + return null; } @Override public Void visitStmtDeclaration(KickCParser.StmtDeclarationContext ctx) { - if(ctx.getChild(0).getText().equals("const")) { - System.out.println("Const!"+ctx.getText()); + if (ctx.getChild(0).getText().equals("const")) { + System.out.println("Const!" + ctx.getText()); } - SymbolType type = (SymbolType)visit(ctx.typeDecl()); - VariableUnversioned lValue = symbolTable.newVariableDeclaration(ctx.NAME().getText(), type); - if(ctx.initializer()!=null) { + SymbolType type = (SymbolType) visit(ctx.typeDecl()); + VariableUnversioned lValue = getCurrentSymbols().addVariable(ctx.NAME().getText(), type); + if (ctx.initializer() != null) { RValue rValue = (RValue) visit(ctx.initializer()); Statement stmt = new StatementAssignment(lValue, rValue); sequence.addStatement(stmt); @@ -144,7 +194,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public LValue visitLvalueName(KickCParser.LvalueNameContext ctx) { - return symbolTable.newVariableUsage(ctx.NAME().getText()); + return getCurrentSymbols().getVariable(ctx.NAME().getText()); } @Override @@ -155,9 +205,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public LValue visitLvaluePtr(KickCParser.LvaluePtrContext ctx) { LValue lval = (LValue) visit(ctx.lvalue()); - if(lval instanceof Variable) { + if (lval instanceof Variable) { return new PointerDereferenceSimple((Variable) lval); - } else { + } else { throw new RuntimeException("Not implemented"); } } @@ -194,10 +244,10 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { public SymbolType visitTypeArray(KickCParser.TypeArrayContext ctx) { SymbolType elementType = (SymbolType) visit(ctx.typeDecl()); Constant size = ParseTreeConstantEvaluator.evaluate(ctx.expr()); - if(size instanceof ConstantInteger) { + if (size instanceof ConstantInteger) { return new SymbolTypeArray(elementType, ((ConstantInteger) size).getNumber()); } else { - throw new RuntimeException("Array size not a constant integer "+ctx.getText()); + throw new RuntimeException("Array size not a constant integer " + ctx.getText()); } } @@ -209,7 +259,21 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public Object visitExprCall(KickCParser.ExprCallContext ctx) { - throw new RuntimeException("Not implemented"); + Label label = new Label(ctx.NAME().getText(), getCurrentSymbols(), false); + List parameters = (List) this.visit(ctx.parameterList()); + VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); + sequence.addStatement(new StatementCallLValue(tmpVar, label, parameters)); + return tmpVar; + } + + @Override + public List visitParameterList(KickCParser.ParameterListContext ctx) { + List parameters = new ArrayList<>(); + for (KickCParser.ExprContext exprContext : ctx.expr()) { + RValue param = (RValue) this.visit(exprContext); + parameters.add(param); + } + return parameters; } @Override @@ -217,7 +281,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { RValue array = (LValue) visit(ctx.expr(0)); RValue index = (RValue) visit(ctx.expr(1)); Operator operator = new Operator("*idx"); - VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment(); + VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); Statement stmt = new StatementAssignment(tmpVar, array, operator, index); sequence.addStatement(stmt); return tmpVar; @@ -226,7 +290,7 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public RValue visitExprNumber(KickCParser.ExprNumberContext ctx) { Number number = NumberParser.parseLiteral(ctx.getText()); - if(number instanceof Integer) { + if (number instanceof Integer) { return new ConstantInteger((Integer) number); } else { return new ConstantDouble((Double) number); @@ -244,14 +308,13 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { return new ConstantBool(Boolean.valueOf(bool)); } - @Override public RValue visitExprBinary(KickCParser.ExprBinaryContext ctx) { RValue left = (RValue) this.visit(ctx.expr(0)); RValue right = (RValue) this.visit(ctx.expr(1)); - String op = ((TerminalNode)ctx.getChild(1)).getSymbol().getText(); + String op = ((TerminalNode) ctx.getChild(1)).getSymbol().getText(); Operator operator = new Operator(op); - VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment(); + VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); Statement stmt = new StatementAssignment(tmpVar, left, operator, right); sequence.addStatement(stmt); return tmpVar; @@ -260,9 +323,9 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public RValue visitExprUnary(KickCParser.ExprUnaryContext ctx) { RValue child = (RValue) this.visit(ctx.expr()); - String op = ((TerminalNode)ctx.getChild(0)).getSymbol().getText(); + String op = ((TerminalNode) ctx.getChild(0)).getSymbol().getText(); Operator operator = new Operator(op); - VariableIntermediate tmpVar = symbolTable.newIntermediateAssignment(); + VariableIntermediate tmpVar = getCurrentSymbols().addVariableIntermediate(); Statement stmt = new StatementAssignment(tmpVar, operator, child); sequence.addStatement(stmt); return tmpVar; @@ -275,15 +338,11 @@ public class Pass1GenerateStatementSequence extends KickCBaseVisitor { @Override public RValue visitExprId(KickCParser.ExprIdContext ctx) { - return symbolTable.newVariableUsage(ctx.NAME().getText()); + return getCurrentSymbols().getVariable(ctx.NAME().getText()); } public StatementSequence getSequence() { return sequence; } - public SymbolTable getSymbols() { - return this.symbolTable; - } - } diff --git a/src/dk/camelot64/kickc/icl/Pass3CodeGeneration.java b/src/dk/camelot64/kickc/icl/Pass3CodeGeneration.java index 184068bc1..d120e8093 100644 --- a/src/dk/camelot64/kickc/icl/Pass3CodeGeneration.java +++ b/src/dk/camelot64/kickc/icl/Pass3CodeGeneration.java @@ -23,7 +23,7 @@ public class Pass3CodeGeneration { // Generate entry points (if needed) genBlockEntryPoints(asm, block); // Generate label - asm.addLabel(block.getLabel().getName().replace('@', 'B')); + asm.addLabel(block.getLabel().getLocalName().replace('@', 'B')); // Generate statements genStatements(asm, block); // Generate exit @@ -32,7 +32,7 @@ public class Pass3CodeGeneration { if (defaultSuccessor.hasPhiStatements()) { genBlockPhiTransition(asm, block, defaultSuccessor); } - asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getName().replace('@', 'B')); + asm.addInstruction("JMP", AsmAddressingMode.ABS, defaultSuccessor.getLabel().getLocalName().replace('@', 'B')); } } return asm; @@ -84,14 +84,14 @@ public class Pass3CodeGeneration { for (ControlFlowBlock predecessor : block.getPredecessors()) { if (block.equals(predecessor.getConditionalSuccessor())) { genBlockPhiTransition(asm, predecessor, block); - asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getName().replace('@', 'B')); + asm.addInstruction("JMP", AsmAddressingMode.ABS, block.getLabel().getLocalName().replace('@', 'B')); } } } } private void genBlockPhiTransition(AsmProgram asm, ControlFlowBlock fromBlock, ControlFlowBlock toBlock) { - asm.addLabel((toBlock.getLabel().getName() + "_from_" + fromBlock.getLabel().getName()).replace('@', 'B')); + asm.addLabel((toBlock.getLabel().getLocalName() + "_from_" + fromBlock.getLabel().getLocalName()).replace('@', 'B')); for (Statement statement : toBlock.getStatements()) { if (!(statement instanceof StatementPhi)) { // No more phi statements to handle diff --git a/src/dk/camelot64/kickc/icl/PassTypeInference.java b/src/dk/camelot64/kickc/icl/PassTypeInference.java index ffd7dd62a..e01a3d8d2 100644 --- a/src/dk/camelot64/kickc/icl/PassTypeInference.java +++ b/src/dk/camelot64/kickc/icl/PassTypeInference.java @@ -30,6 +30,14 @@ public class PassTypeInference { } } } + } else if(statement instanceof StatementCallLValue) { + StatementCallLValue callLValue = (StatementCallLValue) statement; + LValue lValue = callLValue.getLValue(); + if(lValue instanceof Variable) { + Label label = callLValue.getCallLabel(); + Procedure procedure = symbols.getProcedure(label.getLocalName()); + ((Variable) lValue).setInferredType(procedure.getReturnType()); + } } } } diff --git a/src/dk/camelot64/kickc/icl/Procedure.java b/src/dk/camelot64/kickc/icl/Procedure.java new file mode 100644 index 000000000..a17f26659 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/Procedure.java @@ -0,0 +1,71 @@ +package dk.camelot64.kickc.icl; + +import java.util.List; + +/** Symbol describing a procedure/function */ +public class Procedure extends SymbolTable { + + private final SymbolType returnType; + private List parameters; + + public Procedure(String name, SymbolType returnType, SymbolTable parentScope) { + super(name, new SymbolTypeProcedure(returnType), parentScope); + this.returnType = returnType; + } + + public void setParameters(List parameters) { + this.parameters = parameters; + for (Variable parameter : parameters) { + add(parameter); + } + } + + public Label getLabel() { + return new Label(getLocalName(), this, false); + } + + public SymbolType getReturnType() { + return returnType; + } + + public List getParameters() { + return parameters; + } + + @Override + public String getFullName() { + return super.getFullName(); + } + + @Override + public String getTypedName() { + StringBuilder res = new StringBuilder(); + res.append("("+getType().getTypeName() + ") "); + res.append(getFullName()); + res.append("("); + boolean first = true; + if(parameters!=null) { + for (Variable parameter : parameters) { + if (!first) res.append(" , "); + first = false; + res.append(parameter.getTypedName()); + } + } + res.append(")"); + return res.toString(); + } + + public String getSymbolTableContents() { + StringBuilder res = new StringBuilder(); + res.append(getTypedName()); + res.append("\n"); + res.append(super.getSymbolTableContents()); + return res.toString(); + } + + @Override + public String toString() { + return getTypedName(); + } + +} diff --git a/src/dk/camelot64/kickc/icl/StatementAssignment.java b/src/dk/camelot64/kickc/icl/StatementAssignment.java index 95a4e5b65..c468b440e 100644 --- a/src/dk/camelot64/kickc/icl/StatementAssignment.java +++ b/src/dk/camelot64/kickc/icl/StatementAssignment.java @@ -8,7 +8,7 @@ package dk.camelot64.kickc.icl; *
* lValue := rValue1 <operator> rValue2 */ -public class StatementAssignment implements Statement { +public class StatementAssignment implements StatementLValue { /** The variable being assigned a value by the statement. */ private LValue lValue; diff --git a/src/dk/camelot64/kickc/icl/StatementCallLValue.java b/src/dk/camelot64/kickc/icl/StatementCallLValue.java new file mode 100644 index 000000000..0c941ea25 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/StatementCallLValue.java @@ -0,0 +1,60 @@ +package dk.camelot64.kickc.icl; + +import java.util.List; + +/** + * Call procedure in SSA form. + *
+ * Xi := call label param1 param2 param3 ... + */ +public class StatementCallLValue implements StatementLValue { + + /** The variable being assigned a value by the call. */ + private LValue lValue; + private Label callLabel; + private List parameters; + + public StatementCallLValue(LValue lValue, Label callLabel, List parameters) { + this.lValue = lValue; + this.callLabel = callLabel; + this.parameters = parameters; + } + + public LValue getLValue() { + return lValue; + } + + public void setLValue(LValue lValue) { + this.lValue = lValue; + } + + public Label getCallLabel() { + return callLabel; + } + + public List getParameters() { + return parameters; + } + + public int getNumParameters() { + return parameters.size(); + } + + public RValue getParameter(int idx) { + return parameters.get(idx); + } + + @Override + public String toString() { + StringBuilder res = new StringBuilder(); + res.append(lValue); + res.append(" ← "); + res.append("call "); + res.append(callLabel+" "); + for (RValue parameter : parameters) { + res.append(parameter+" "); + } + return res.toString(); + } + +} diff --git a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java index c0fc9ff60..d3b8c412a 100644 --- a/src/dk/camelot64/kickc/icl/StatementConditionalJump.java +++ b/src/dk/camelot64/kickc/icl/StatementConditionalJump.java @@ -72,7 +72,7 @@ public class StatementConditionalJump implements Statement { } out.append(rValue2); out.append(") goto "); - out.append(destination.getName()); + out.append(destination.getLocalName()); return out.toString(); } diff --git a/src/dk/camelot64/kickc/icl/StatementJump.java b/src/dk/camelot64/kickc/icl/StatementJump.java index d999bad35..b66bf7574 100644 --- a/src/dk/camelot64/kickc/icl/StatementJump.java +++ b/src/dk/camelot64/kickc/icl/StatementJump.java @@ -20,7 +20,7 @@ public class StatementJump implements Statement { @Override public String toString() { - return "goto "+destination.getName(); + return "goto "+destination.getLocalName(); } public void setDestination(Label destination) { diff --git a/src/dk/camelot64/kickc/icl/StatementLValue.java b/src/dk/camelot64/kickc/icl/StatementLValue.java new file mode 100644 index 000000000..cffcf5bbb --- /dev/null +++ b/src/dk/camelot64/kickc/icl/StatementLValue.java @@ -0,0 +1,12 @@ +package dk.camelot64.kickc.icl; + +/** + * Single Static Assignment Form Statement with an LValuie - that is a statement assigning a value to a variable. + */ +public interface StatementLValue extends Statement { + + LValue getLValue(); + + void setLValue(LValue lValue); + +} diff --git a/src/dk/camelot64/kickc/icl/StatementJumpTarget.java b/src/dk/camelot64/kickc/icl/StatementLabel.java similarity index 67% rename from src/dk/camelot64/kickc/icl/StatementJumpTarget.java rename to src/dk/camelot64/kickc/icl/StatementLabel.java index bb936bbb7..f14146195 100644 --- a/src/dk/camelot64/kickc/icl/StatementJumpTarget.java +++ b/src/dk/camelot64/kickc/icl/StatementLabel.java @@ -3,11 +3,11 @@ package dk.camelot64.kickc.icl; /** * Single Static Assignment Form Statement Jump target. */ -public class StatementJumpTarget implements Statement { +public class StatementLabel implements Statement { private Label label; - public StatementJumpTarget(Label label) { + public StatementLabel(Label label) { this.label = label; } @@ -17,7 +17,7 @@ public class StatementJumpTarget implements Statement { @Override public String toString() { - return label+":"; + return label.getFullName()+":"; } diff --git a/src/dk/camelot64/kickc/icl/StatementPhi.java b/src/dk/camelot64/kickc/icl/StatementPhi.java index 8875024cc..f434fffd0 100644 --- a/src/dk/camelot64/kickc/icl/StatementPhi.java +++ b/src/dk/camelot64/kickc/icl/StatementPhi.java @@ -9,7 +9,7 @@ import java.util.List; *
* Xi := phi(Xj, Xk, ...) */ -public class StatementPhi implements Statement { +public class StatementPhi implements StatementLValue { /** The versioned variable being assigned a value by the statement. */ private VariableVersion lValue; @@ -57,14 +57,14 @@ public class StatementPhi implements Statement { return lValue; } - public void setLValue(Variable lValue) { + @Override + public void setLValue(LValue lValue) { if(!(lValue instanceof VariableVersion)) { throw new RuntimeException("Error modifying phi-statement lValue "+this.lValue+". Attempt to set to non-versioned variable "+lValue); } this.lValue = (VariableVersion) lValue; } - public void addPreviousVersion(ControlFlowBlock block, VariableVersion symbol) { previousVersions.add(new PreviousSymbol(block, symbol)); } @@ -78,7 +78,7 @@ public class StatementPhi implements Statement { StringBuilder out = new StringBuilder(); out.append(lValue + " ← " + "phi("); for (PreviousSymbol previousSymbol : previousVersions) { - out.append(" "+previousSymbol.getBlock().getLabel().getName()+"/"+previousSymbol.getRValue()); + out.append(" "+previousSymbol.getBlock().getLabel().getLocalName()+"/"+previousSymbol.getRValue()); } out.append(" )"); return out.toString(); diff --git a/src/dk/camelot64/kickc/icl/StatementProcedure.java b/src/dk/camelot64/kickc/icl/StatementProcedure.java new file mode 100644 index 000000000..ef05a4171 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/StatementProcedure.java @@ -0,0 +1,21 @@ +package dk.camelot64.kickc.icl; + +/** Procedure declaration in SSA */ +public class StatementProcedure implements Statement { + + private Procedure procedure; + + public StatementProcedure(Procedure procedure) { + this.procedure = procedure; + } + + public Procedure getProcedure() { + return procedure; + } + + @Override + public String toString() { + return "proc "+procedure.toString()+":"; + } + +} diff --git a/src/dk/camelot64/kickc/icl/StatementReturn.java b/src/dk/camelot64/kickc/icl/StatementReturn.java new file mode 100644 index 000000000..a3a93fbb8 --- /dev/null +++ b/src/dk/camelot64/kickc/icl/StatementReturn.java @@ -0,0 +1,24 @@ +package dk.camelot64.kickc.icl; + +/** + * Return Statement inside procedure in Single Static Assignment Form. + */ +public class StatementReturn implements Statement { + + /** Return value. May be null if not returning a value. */ + private RValue value; + + public StatementReturn(RValue value) { + this.value = value; + } + + public RValue getValue() { + return value; + } + + @Override + public String toString() { + return "return "+(value==null?"":value); + } + +} diff --git a/src/dk/camelot64/kickc/icl/StatementSequence.java b/src/dk/camelot64/kickc/icl/StatementSequence.java index 83294f0fc..1a3f59244 100644 --- a/src/dk/camelot64/kickc/icl/StatementSequence.java +++ b/src/dk/camelot64/kickc/icl/StatementSequence.java @@ -20,7 +20,7 @@ public class StatementSequence { public String toString() { StringBuffer out = new StringBuffer(); for (Statement statement : statements) { - if(!(statement instanceof StatementJumpTarget)) { + if(!(statement instanceof StatementLabel)) { out.append(" "); } out.append(statement.toString()+"\n"); diff --git a/src/dk/camelot64/kickc/icl/Symbol.java b/src/dk/camelot64/kickc/icl/Symbol.java index e3feb7eba..e78edc7a4 100644 --- a/src/dk/camelot64/kickc/icl/Symbol.java +++ b/src/dk/camelot64/kickc/icl/Symbol.java @@ -3,8 +3,15 @@ package dk.camelot64.kickc.icl; /** A Symbol (variable, jump label, etc.) */ public interface Symbol extends Value { - public String getName(); + String getLocalName(); + + String getFullName(); + + String getTypedName(); + + SymbolType getType(); + + SymbolTable getScope(); - public SymbolType getType(); } diff --git a/src/dk/camelot64/kickc/icl/SymbolTable.java b/src/dk/camelot64/kickc/icl/SymbolTable.java index 6eec7ecee..5c104c8a1 100644 --- a/src/dk/camelot64/kickc/icl/SymbolTable.java +++ b/src/dk/camelot64/kickc/icl/SymbolTable.java @@ -1,122 +1,181 @@ package dk.camelot64.kickc.icl; -import sun.jvm.hotspot.debugger.cdbg.Sym; - import java.util.*; /** * Manages symbols (variables, labels) */ -public class SymbolTable { +public class SymbolTable implements Symbol { + private String name; + private SymbolType type; private Map symbols; private int intermediateVarCount = 0; private int intermediateLabelCount = 1; private RegisterAllocation allocation; + private SymbolTable parentScope; + + public SymbolTable(String name, SymbolType type, SymbolTable parentScope) { + this.name = name; + this.type = type; + this.parentScope = parentScope; + this.symbols = new LinkedHashMap<>(); + } public SymbolTable() { + this.name = ""; + this.type = new SymbolTypeProgram(); + this.parentScope = null; this.symbols = new LinkedHashMap<>(); } + @Override + public String getLocalName() { + return name; + } + + @Override + public String getFullName() { + return getFullName(this); + } + + public static String getFullName(Symbol symbol) { + if(symbol.getScope()!=null) { + String scopeName = symbol.getScope().getFullName(); + if(scopeName.length()>0) { + return scopeName+"::"+symbol.getLocalName(); + } + } + return symbol.getLocalName(); + } + + + @Override + public SymbolTable getScope() { + return parentScope; + } + + @Override + public String getTypedName() { + return "(" + getType().getTypeName() + ") " + getFullName(); + } + + @Override + public SymbolType getType() { + return type; + } + + public Symbol add(Symbol symbol) { + if (symbols.get(symbol.getLocalName()) != null) { + throw new RuntimeException("Symbol already declared " + symbol.getLocalName()); + } + symbols.put(symbol.getLocalName(), symbol); + return symbol; + } + + public void remove(Symbol symbol) { + symbols.remove(symbol.getLocalName()); + } + + public VariableUnversioned addVariable(String name, SymbolType type) { + VariableUnversioned symbol = new VariableUnversioned(name, this, type); + add(symbol); + return symbol; + } + + public VariableIntermediate addVariableIntermediate() { + String name = "$" + intermediateVarCount++; + VariableIntermediate symbol = new VariableIntermediate(name, this, SymbolTypeBasic.VAR); + add(symbol); + return symbol; + } + + public Variable getVariable(String name) { + return (Variable) symbols.get(name); + } + public Collection getAllVariables() { Collection vars = new ArrayList<>(); for (Symbol symbol : symbols.values()) { - if(symbol instanceof Variable) { + if (symbol instanceof Variable) { vars.add((Variable) symbol); } } return vars; } - private Symbol addSymbol(Symbol symbol) { - if(symbols.get(symbol.getName())!=null) { - throw new RuntimeException("Symbol already declared "+symbol.getName()); + public Label addLabel(String name) { + Label symbol = new Label(name, this, false); + add(symbol); + return symbol; + } + + public Label addLabelIntermediate() { + String name = "@" + intermediateLabelCount++; + Label symbol = new Label(name, this, true); + add(symbol); + return symbol; + } + + + public Procedure addProcedure(String name, SymbolType type) { + Symbol symbol = symbols.get(name); + if (symbol != null) { + throw new RuntimeException("Error! Symbol already defined " + symbol); } - symbols.put(symbol.getName(), symbol); - return symbol; + Procedure procedure = new Procedure(name, type, this); + add(procedure); + return procedure; } - public VariableUnversioned newVariableDeclaration(String name, SymbolType type) { - VariableUnversioned symbol = new VariableUnversioned(name, type); - addSymbol(symbol); - return symbol; - } - - public VariableUnversioned newVariableDeclaration(String name, String type) { - SymbolType symbolType = SymbolTypeBasic.get(type); - VariableUnversioned symbol = new VariableUnversioned(name, symbolType); - addSymbol(symbol); - return symbol; - } - - public VariableUnversioned newVariableUsage(String name) { - return (VariableUnversioned) symbols.get(name); - } - - public VariableIntermediate newIntermediateAssignment() { - String name = "$"+intermediateVarCount++; - VariableIntermediate symbol = new VariableIntermediate(name, SymbolTypeBasic.VAR); - addSymbol(symbol); - return symbol; - } - - public Label newNamedJumpLabel(String name) { - Label symbol = new Label(name, false); - addSymbol(symbol); - return symbol; - } - - public Label newIntermediateJumpLabel() { - String name = "@"+ intermediateLabelCount++; - Label symbol = new Label(name, true); - addSymbol(symbol); - return symbol; - } - - public void remove(Symbol symbol) { - symbols.remove(symbol.getName()); + public Procedure getProcedure(String name) { + Symbol symbol = symbols.get(name); + if (symbol != null && symbol instanceof Procedure) { + return (Procedure) symbol; + } else { + return null; + } } public VariableVersion createVersion(VariableUnversioned symbol) { VariableVersion version = new VariableVersion(symbol, symbol.getNextVersionNumber()); - symbols.put(version.getName(), version); + symbols.put(version.getLocalName(), version); return version; } - public Variable getVariable(String name) { - return (Variable) symbols.get(name); - } - public void setAllocation(RegisterAllocation allocation) { this.allocation = allocation; } public RegisterAllocation.Register getRegister(Variable variable) { RegisterAllocation.Register register = null; - if(allocation!=null) { + if (allocation != null) { register = allocation.getRegister(variable); } return register; } - @Override - public String toString() { - StringBuffer out = new StringBuffer(); + public String getSymbolTableContents() { + StringBuilder res = new StringBuilder(); Set names = symbols.keySet(); List sortedNames = new ArrayList<>(names); Collections.sort(sortedNames); for (String name : sortedNames) { Symbol symbol = symbols.get(name); - out.append(symbol.toString()); - if(symbol instanceof Variable) { + if (symbol instanceof SymbolTable) { + res.append(((SymbolTable) symbol).getSymbolTableContents()); + } else { + res.append(symbol.toString()); + } + if (symbol instanceof Variable) { RegisterAllocation.Register register = getRegister((Variable) symbol); - if(register!=null) { - out.append(" "+register); + if (register != null) { + res.append(" " + register); } } - out.append("\n"); + res.append("\n"); } - return out.toString(); + return res.toString(); } } diff --git a/src/dk/camelot64/kickc/icl/SymbolTypeBasic.java b/src/dk/camelot64/kickc/icl/SymbolTypeBasic.java index 57b62199d..2e4bfe468 100644 --- a/src/dk/camelot64/kickc/icl/SymbolTypeBasic.java +++ b/src/dk/camelot64/kickc/icl/SymbolTypeBasic.java @@ -6,7 +6,9 @@ public enum SymbolTypeBasic implements SymbolType { WORD("word"), STRING("string"), BOOLEAN("boolean"), + // A label LABEL("label"), + // Unresolved type. Will be infered later VAR("var"); private String typeName; diff --git a/src/dk/camelot64/kickc/icl/SymbolTypeProcedure.java b/src/dk/camelot64/kickc/icl/SymbolTypeProcedure.java new file mode 100644 index 000000000..b38e2655c --- /dev/null +++ b/src/dk/camelot64/kickc/icl/SymbolTypeProcedure.java @@ -0,0 +1,20 @@ +package dk.camelot64.kickc.icl; + +/** A function returning another type */ +public class SymbolTypeProcedure implements SymbolType { + + private SymbolType returnType; + + public SymbolTypeProcedure(SymbolType returnType) { + this.returnType = returnType; + } + + public SymbolType getReturnType() { + return returnType; + } + + @Override + public String getTypeName() { + return returnType.getTypeName() + "()"; + } +} diff --git a/src/dk/camelot64/kickc/icl/SymbolTypeProgram.java b/src/dk/camelot64/kickc/icl/SymbolTypeProgram.java new file mode 100644 index 000000000..18888629f --- /dev/null +++ b/src/dk/camelot64/kickc/icl/SymbolTypeProgram.java @@ -0,0 +1,14 @@ +package dk.camelot64.kickc.icl; + +/** A program */ +public class SymbolTypeProgram implements SymbolType { + + public SymbolTypeProgram() { + + } + + @Override + public String getTypeName() { + return "PROGRAM"; + } +} diff --git a/src/dk/camelot64/kickc/icl/Variable.java b/src/dk/camelot64/kickc/icl/Variable.java index af5131be3..998c6cbdd 100644 --- a/src/dk/camelot64/kickc/icl/Variable.java +++ b/src/dk/camelot64/kickc/icl/Variable.java @@ -1,27 +1,51 @@ package dk.camelot64.kickc.icl; -/** A Symbol (variable, jump label, etc.) */ -public abstract class Variable implements Symbol, RValue, LValue { +/** + * A Symbol (variable, jump label, etc.) + */ +public abstract class Variable implements Symbol, RValue, LValue { - /** The name of the symbol. */ + /** + * The name of the symbol. + */ private String name; - /** The type of the symbol. VAR means tha type is unknown, and has not been inferred yet. */ + /** + * Scope + */ + private SymbolTable scope; + + /** + * The type of the symbol. VAR means tha type is unknown, and has not been inferred yet. + */ private SymbolType type; - /** true if the symbol type is infered (not declared) */ + /** + * true if the symbol type is infered (not declared) + */ private boolean inferredType; - public Variable(String name, SymbolType type) { + public Variable(String name, SymbolTable scope, SymbolType type) { this.name = name; + this.scope = scope; this.type = type; this.inferredType = false; } - public String getName() { + public String getLocalName() { return name; } + @Override + public String getFullName() { + return SymbolTable.getFullName(this); + } + + @Override + public String getTypedName() { + return "(" + type.getTypeName() + (inferredType ? "~" : "") + ") " + getFullName(); + } + public SymbolType getType() { return type; } @@ -39,24 +63,34 @@ public abstract class Variable implements Symbol, RValue, LValue { public abstract boolean isIntermediate(); - @Override - public String toString() { - return "("+type.getTypeName() + (inferredType ?"~":"") + ") "+name; - } - @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - Variable symbol = (Variable) o; - if (!name.equals(symbol.name)) return false; - return type == symbol.type; + + Variable variable = (Variable) o; + + if (inferredType != variable.inferredType) return false; + if (!name.equals(variable.name)) return false; + if (scope != null ? !scope.equals(variable.scope) : variable.scope != null) return false; + return type.equals(variable.type); } @Override public int hashCode() { int result = name.hashCode(); + result = 31 * result + (scope != null ? scope.hashCode() : 0); + result = 31 * result + type.hashCode(); + result = 31 * result + (inferredType ? 1 : 0); return result; } + @Override + public String toString() { + return getTypedName(); + } + + public SymbolTable getScope() { + return scope; + } } diff --git a/src/dk/camelot64/kickc/icl/VariableIntermediate.java b/src/dk/camelot64/kickc/icl/VariableIntermediate.java index 92f34dd66..083495500 100644 --- a/src/dk/camelot64/kickc/icl/VariableIntermediate.java +++ b/src/dk/camelot64/kickc/icl/VariableIntermediate.java @@ -1,10 +1,12 @@ package dk.camelot64.kickc.icl; -/** A Symbol (variable, jump label, etc.) */ +/** + * A Symbol (variable, jump label, etc.) + */ public class VariableIntermediate extends Variable { - public VariableIntermediate(String name, SymbolType type) { - super(name, type); + public VariableIntermediate(String name, SymbolTable scope, SymbolType type) { + super(name, scope, type); } @Override diff --git a/src/dk/camelot64/kickc/icl/VariableUnversioned.java b/src/dk/camelot64/kickc/icl/VariableUnversioned.java index a4de81748..cebe4a421 100644 --- a/src/dk/camelot64/kickc/icl/VariableUnversioned.java +++ b/src/dk/camelot64/kickc/icl/VariableUnversioned.java @@ -1,17 +1,23 @@ package dk.camelot64.kickc.icl; -/** A Symbol (variable, jump label, etc.) */ +/** + * A Symbol (variable, jump label, etc.) + */ public class VariableUnversioned extends Variable { - /** The number of the next version */ + /** + * The number of the next version + */ private Integer nextVersionNumber; - public VariableUnversioned(String name, SymbolType type) { - super(name, type); - this.nextVersionNumber = 0; + public VariableUnversioned(String name, SymbolTable scope, SymbolType type) { + super(name, scope, type); + this.nextVersionNumber = 0; } - /** Get the version number of the next version. (if anyone versions the symbol). */ + /** + * Get the version number of the next version. (if anyone versions the symbol). + */ int getNextVersionNumber() { return nextVersionNumber++; } diff --git a/src/dk/camelot64/kickc/icl/VariableVersion.java b/src/dk/camelot64/kickc/icl/VariableVersion.java index 7cd3c49a0..95fee28c5 100644 --- a/src/dk/camelot64/kickc/icl/VariableVersion.java +++ b/src/dk/camelot64/kickc/icl/VariableVersion.java @@ -6,7 +6,7 @@ public class VariableVersion extends Variable { private VariableUnversioned versionOf; public VariableVersion(VariableUnversioned versionOf, int version) { - super(versionOf.getName()+"#"+version, versionOf.getType()); + super(versionOf.getLocalName()+"#"+version, versionOf.getScope(), versionOf.getType()); this.versionOf = versionOf; } diff --git a/src/dk/camelot64/kickc/parser/KickC.g4 b/src/dk/camelot64/kickc/parser/KickC.g4 index 7b6067cb0..c186679fd 100644 --- a/src/dk/camelot64/kickc/parser/KickC.g4 +++ b/src/dk/camelot64/kickc/parser/KickC.g4 @@ -18,7 +18,7 @@ stmt | 'if' '(' expr ')' stmt ( 'else' stmt )? #stmtIfElse | 'while' '(' expr ')' stmt #stmtWhile | 'do' stmt 'while' '(' expr ')' #stmtDoWhile - | 'return' expr ';' #stmtReturn + | 'return' expr? ';' #stmtReturn ; parameterListDecl diff --git a/src/dk/camelot64/kickc/parser/KickCParser.java b/src/dk/camelot64/kickc/parser/KickCParser.java index 6cdccf500..5fb8ddb46 100644 --- a/src/dk/camelot64/kickc/parser/KickCParser.java +++ b/src/dk/camelot64/kickc/parser/KickCParser.java @@ -419,9 +419,9 @@ public class KickCParser extends Parser { enterRule(_localctx, 4, RULE_stmt); int _la; try { - setState(91); + setState(92); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) { case 1: _localctx = new StmtBlockContext(_localctx); enterOuterAlt(_localctx, 1); @@ -606,9 +606,17 @@ public class KickCParser extends Parser { { setState(87); match(T__11); - setState(88); - expr(0); setState(89); + _errHandler.sync(this); + _la = _input.LA(1); + if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { + { + setState(88); + expr(0); + } + } + + setState(91); match(T__6); } break; @@ -658,21 +666,21 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(93); + setState(94); parameterDecl(); - setState(98); + setState(99); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__12) { { { - setState(94); - match(T__12); setState(95); + match(T__12); + setState(96); parameterDecl(); } } - setState(100); + setState(101); _errHandler.sync(this); _la = _input.LA(1); } @@ -719,9 +727,9 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(101); - typeDecl(0); setState(102); + typeDecl(0); + setState(103); match(NAME); } } @@ -827,28 +835,28 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(105); + setState(106); match(SIMPLETYPE); } _ctx.stop = _input.LT(-1); - setState(117); + setState(118); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,11,_ctx); + _alt = getInterpreter().adaptivePredict(_input,12,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(115); + setState(116); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) { case 1: { _localctx = new TypePtrContext(new TypeDeclContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_typeDecl); - setState(107); - if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); setState(108); + if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)"); + setState(109); match(T__13); } break; @@ -856,30 +864,30 @@ public class KickCParser extends Parser { { _localctx = new TypeArrayContext(new TypeDeclContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_typeDecl); - setState(109); - if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); setState(110); + if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); + setState(111); match(T__14); - setState(112); + setState(113); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { { - setState(111); + setState(112); expr(0); } } - setState(114); + setState(115); match(T__15); } break; } } } - setState(119); + setState(120); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,11,_ctx); + _alt = getInterpreter().adaptivePredict(_input,12,_ctx); } } } @@ -952,7 +960,7 @@ public class KickCParser extends Parser { enterRule(_localctx, 12, RULE_initializer); int _la; try { - setState(132); + setState(133); _errHandler.sync(this); switch (_input.LA(1)) { case T__2: @@ -969,7 +977,7 @@ public class KickCParser extends Parser { _localctx = new InitExprContext(_localctx); enterOuterAlt(_localctx, 1); { - setState(120); + setState(121); expr(0); } break; @@ -977,27 +985,27 @@ public class KickCParser extends Parser { _localctx = new InitListContext(_localctx); enterOuterAlt(_localctx, 2); { - setState(121); - match(T__0); setState(122); + match(T__0); + setState(123); initializer(); - setState(127); + setState(128); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__12) { { { - setState(123); - match(T__12); setState(124); + match(T__12); + setState(125); initializer(); } } - setState(129); + setState(130); _errHandler.sync(this); _la = _input.LA(1); } - setState(130); + setState(131); match(T__1); } break; @@ -1120,7 +1128,7 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(142); + setState(143); _errHandler.sync(this); switch (_input.LA(1)) { case T__2: @@ -1129,11 +1137,11 @@ public class KickCParser extends Parser { _ctx = _localctx; _prevctx = _localctx; - setState(135); - match(T__2); setState(136); - lvalue(0); + match(T__2); setState(137); + lvalue(0); + setState(138); match(T__3); } break; @@ -1142,7 +1150,7 @@ public class KickCParser extends Parser { _localctx = new LvalueNameContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(139); + setState(140); match(NAME); } break; @@ -1151,9 +1159,9 @@ public class KickCParser extends Parser { _localctx = new LvaluePtrContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(140); - match(T__13); setState(141); + match(T__13); + setState(142); lvalue(2); } break; @@ -1161,9 +1169,9 @@ public class KickCParser extends Parser { throw new NoViableAltException(this); } _ctx.stop = _input.LT(-1); - setState(151); + setState(152); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,15,_ctx); + _alt = getInterpreter().adaptivePredict(_input,16,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); @@ -1172,20 +1180,20 @@ public class KickCParser extends Parser { { _localctx = new LvalueArrayContext(new LvalueContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_lvalue); - setState(144); - if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); setState(145); - match(T__14); + if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)"); setState(146); - expr(0); + match(T__14); setState(147); + expr(0); + setState(148); match(T__15); } } } - setState(153); + setState(154); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,15,_ctx); + _alt = getInterpreter().adaptivePredict(_input,16,_ctx); } } } @@ -1420,20 +1428,20 @@ public class KickCParser extends Parser { int _alt; enterOuterAlt(_localctx, 1); { - setState(176); + setState(177); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,17,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) { case 1: { _localctx = new ExprParContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(155); - match(T__2); setState(156); - expr(0); + match(T__2); setState(157); + expr(0); + setState(158); match(T__3); } break; @@ -1442,21 +1450,21 @@ public class KickCParser extends Parser { _localctx = new ExprCallContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(159); - match(NAME); setState(160); + match(NAME); + setState(161); match(T__2); - setState(162); + setState(163); _errHandler.sync(this); _la = _input.LA(1); if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << STRING) | (1L << BOOLEAN) | (1L << NUMBER) | (1L << NAME))) != 0)) { { - setState(161); + setState(162); parameterList(); } } - setState(164); + setState(165); match(T__3); } break; @@ -1465,13 +1473,13 @@ public class KickCParser extends Parser { _localctx = new ExprCastContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(165); - match(T__2); setState(166); - typeDecl(0); + match(T__2); setState(167); - match(T__3); + typeDecl(0); setState(168); + match(T__3); + setState(169); expr(13); } break; @@ -1480,7 +1488,7 @@ public class KickCParser extends Parser { _localctx = new ExprUnaryContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(170); + setState(171); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__13) | (1L << T__16) | (1L << T__17) | (1L << T__18) | (1L << T__19) | (1L << T__20))) != 0)) ) { _errHandler.recoverInline(this); @@ -1490,7 +1498,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(171); + setState(172); expr(11); } break; @@ -1499,7 +1507,7 @@ public class KickCParser extends Parser { _localctx = new ExprIdContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(172); + setState(173); match(NAME); } break; @@ -1508,7 +1516,7 @@ public class KickCParser extends Parser { _localctx = new ExprNumberContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(173); + setState(174); match(NUMBER); } break; @@ -1517,7 +1525,7 @@ public class KickCParser extends Parser { _localctx = new ExprStringContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(174); + setState(175); match(STRING); } break; @@ -1526,30 +1534,30 @@ public class KickCParser extends Parser { _localctx = new ExprBoolContext(_localctx); _ctx = _localctx; _prevctx = _localctx; - setState(175); + setState(176); match(BOOLEAN); } break; } _ctx.stop = _input.LT(-1); - setState(203); + setState(204); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,19,_ctx); + _alt = getInterpreter().adaptivePredict(_input,20,_ctx); while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( _parseListeners!=null ) triggerExitRuleEvent(); _prevctx = _localctx; { - setState(201); + setState(202); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) { + switch ( getInterpreter().adaptivePredict(_input,19,_ctx) ) { case 1: { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(178); - if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); setState(179); + if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)"); + setState(180); _la = _input.LA(1); if ( !(_la==T__21 || _la==T__22) ) { _errHandler.recoverInline(this); @@ -1559,7 +1567,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(180); + setState(181); expr(11); } break; @@ -1567,9 +1575,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(181); - if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); setState(182); + if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)"); + setState(183); _la = _input.LA(1); if ( !(_la==T__13 || _la==T__23) ) { _errHandler.recoverInline(this); @@ -1579,7 +1587,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(183); + setState(184); expr(10); } break; @@ -1587,9 +1595,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(184); - if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); setState(185); + if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)"); + setState(186); _la = _input.LA(1); if ( !(_la==T__16 || _la==T__17) ) { _errHandler.recoverInline(this); @@ -1599,7 +1607,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(186); + setState(187); expr(9); } break; @@ -1607,9 +1615,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(187); - if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); setState(188); + if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)"); + setState(189); _la = _input.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__24) | (1L << T__25) | (1L << T__26) | (1L << T__27) | (1L << T__28) | (1L << T__29) | (1L << T__30) | (1L << T__31) | (1L << T__32))) != 0)) ) { _errHandler.recoverInline(this); @@ -1619,7 +1627,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(189); + setState(190); expr(8); } break; @@ -1627,9 +1635,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(190); - if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); setState(191); + if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)"); + setState(192); _la = _input.LA(1); if ( !(_la==T__33 || _la==T__34) ) { _errHandler.recoverInline(this); @@ -1639,7 +1647,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(192); + setState(193); expr(7); } break; @@ -1647,9 +1655,9 @@ public class KickCParser extends Parser { { _localctx = new ExprBinaryContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(193); - if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); setState(194); + if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)"); + setState(195); _la = _input.LA(1); if ( !(_la==T__35 || _la==T__36) ) { _errHandler.recoverInline(this); @@ -1659,7 +1667,7 @@ public class KickCParser extends Parser { _errHandler.reportMatch(this); consume(); } - setState(195); + setState(196); expr(6); } break; @@ -1667,22 +1675,22 @@ public class KickCParser extends Parser { { _localctx = new ExprArrayContext(new ExprContext(_parentctx, _parentState)); pushNewRecursionContext(_localctx, _startState, RULE_expr); - setState(196); - if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); setState(197); - match(T__14); + if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)"); setState(198); - expr(0); + match(T__14); setState(199); + expr(0); + setState(200); match(T__15); } break; } } } - setState(205); + setState(206); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,19,_ctx); + _alt = getInterpreter().adaptivePredict(_input,20,_ctx); } } } @@ -1730,21 +1738,21 @@ public class KickCParser extends Parser { try { enterOuterAlt(_localctx, 1); { - setState(206); + setState(207); expr(0); - setState(211); + setState(212); _errHandler.sync(this); _la = _input.LA(1); while (_la==T__12) { { { - setState(207); - match(T__12); setState(208); + match(T__12); + setState(209); expr(0); } } - setState(213); + setState(214); _errHandler.sync(this); _la = _input.LA(1); } @@ -1809,77 +1817,77 @@ public class KickCParser extends Parser { } public static final String _serializedATN = - "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\67\u00d9\4\2\t\2"+ + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3\67\u00da\4\2\t\2"+ "\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ "\t\13\3\2\3\2\3\2\3\3\6\3\33\n\3\r\3\16\3\34\3\4\3\4\5\4!\n\4\3\4\3\4"+ "\3\4\3\4\3\4\5\4(\n\4\3\4\3\4\3\4\5\4-\n\4\3\4\3\4\3\4\5\4\62\n\4\3\4"+ "\3\4\3\4\3\4\5\48\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+ "\3\4\3\4\3\4\3\4\3\4\5\4K\n\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3\4"+ - "\3\4\3\4\3\4\3\4\3\4\3\4\3\4\5\4^\n\4\3\5\3\5\3\5\7\5c\n\5\f\5\16\5f\13"+ - "\5\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\5\7s\n\7\3\7\7\7v\n\7\f"+ - "\7\16\7y\13\7\3\b\3\b\3\b\3\b\3\b\7\b\u0080\n\b\f\b\16\b\u0083\13\b\3"+ - "\b\3\b\5\b\u0087\n\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\5\t\u0091\n\t\3\t"+ - "\3\t\3\t\3\t\3\t\7\t\u0098\n\t\f\t\16\t\u009b\13\t\3\n\3\n\3\n\3\n\3\n"+ - "\3\n\3\n\3\n\5\n\u00a5\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ - "\3\n\5\n\u00b3\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ - "\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\7\n\u00cc\n\n\f\n\16\n\u00cf"+ - "\13\n\3\13\3\13\3\13\7\13\u00d4\n\13\f\13\16\13\u00d7\13\13\3\13\2\5\f"+ - "\20\22\f\2\4\6\b\n\f\16\20\22\24\2\t\4\2\20\20\23\27\3\2\30\31\4\2\20"+ - "\20\32\32\3\2\23\24\3\2\33#\3\2$%\3\2&\'\2\u00f6\2\26\3\2\2\2\4\32\3\2"+ - "\2\2\6]\3\2\2\2\b_\3\2\2\2\ng\3\2\2\2\fj\3\2\2\2\16\u0086\3\2\2\2\20\u0090"+ - "\3\2\2\2\22\u00b2\3\2\2\2\24\u00d0\3\2\2\2\26\27\5\4\3\2\27\30\7\2\2\3"+ - "\30\3\3\2\2\2\31\33\5\6\4\2\32\31\3\2\2\2\33\34\3\2\2\2\34\32\3\2\2\2"+ - "\34\35\3\2\2\2\35\5\3\2\2\2\36 \7\3\2\2\37!\5\4\3\2 \37\3\2\2\2 !\3\2"+ - "\2\2!\"\3\2\2\2\"^\7\4\2\2#$\5\f\7\2$%\7\64\2\2%\'\7\5\2\2&(\5\b\5\2\'"+ - "&\3\2\2\2\'(\3\2\2\2()\3\2\2\2)*\7\6\2\2*,\7\3\2\2+-\5\4\3\2,+\3\2\2\2"+ - ",-\3\2\2\2-.\3\2\2\2./\7\4\2\2/^\3\2\2\2\60\62\7\7\2\2\61\60\3\2\2\2\61"+ - "\62\3\2\2\2\62\63\3\2\2\2\63\64\5\f\7\2\64\67\7\64\2\2\65\66\7\b\2\2\66"+ - "8\5\16\b\2\67\65\3\2\2\2\678\3\2\2\289\3\2\2\29:\7\t\2\2:^\3\2\2\2;<\5"+ - "\20\t\2<=\7\b\2\2=>\5\22\n\2>?\7\t\2\2?^\3\2\2\2@A\5\22\n\2AB\7\t\2\2"+ - "B^\3\2\2\2CD\7\n\2\2DE\7\5\2\2EF\5\22\n\2FG\7\6\2\2GJ\5\6\4\2HI\7\13\2"+ - "\2IK\5\6\4\2JH\3\2\2\2JK\3\2\2\2K^\3\2\2\2LM\7\f\2\2MN\7\5\2\2NO\5\22"+ - "\n\2OP\7\6\2\2PQ\5\6\4\2Q^\3\2\2\2RS\7\r\2\2ST\5\6\4\2TU\7\f\2\2UV\7\5"+ - "\2\2VW\5\22\n\2WX\7\6\2\2X^\3\2\2\2YZ\7\16\2\2Z[\5\22\n\2[\\\7\t\2\2\\"+ - "^\3\2\2\2]\36\3\2\2\2]#\3\2\2\2]\61\3\2\2\2];\3\2\2\2]@\3\2\2\2]C\3\2"+ - "\2\2]L\3\2\2\2]R\3\2\2\2]Y\3\2\2\2^\7\3\2\2\2_d\5\n\6\2`a\7\17\2\2ac\5"+ - "\n\6\2b`\3\2\2\2cf\3\2\2\2db\3\2\2\2de\3\2\2\2e\t\3\2\2\2fd\3\2\2\2gh"+ - "\5\f\7\2hi\7\64\2\2i\13\3\2\2\2jk\b\7\1\2kl\7(\2\2lw\3\2\2\2mn\f\4\2\2"+ - "nv\7\20\2\2op\f\3\2\2pr\7\21\2\2qs\5\22\n\2rq\3\2\2\2rs\3\2\2\2st\3\2"+ - "\2\2tv\7\22\2\2um\3\2\2\2uo\3\2\2\2vy\3\2\2\2wu\3\2\2\2wx\3\2\2\2x\r\3"+ - "\2\2\2yw\3\2\2\2z\u0087\5\22\n\2{|\7\3\2\2|\u0081\5\16\b\2}~\7\17\2\2"+ - "~\u0080\5\16\b\2\177}\3\2\2\2\u0080\u0083\3\2\2\2\u0081\177\3\2\2\2\u0081"+ - "\u0082\3\2\2\2\u0082\u0084\3\2\2\2\u0083\u0081\3\2\2\2\u0084\u0085\7\4"+ - "\2\2\u0085\u0087\3\2\2\2\u0086z\3\2\2\2\u0086{\3\2\2\2\u0087\17\3\2\2"+ - "\2\u0088\u0089\b\t\1\2\u0089\u008a\7\5\2\2\u008a\u008b\5\20\t\2\u008b"+ - "\u008c\7\6\2\2\u008c\u0091\3\2\2\2\u008d\u0091\7\64\2\2\u008e\u008f\7"+ - "\20\2\2\u008f\u0091\5\20\t\4\u0090\u0088\3\2\2\2\u0090\u008d\3\2\2\2\u0090"+ - "\u008e\3\2\2\2\u0091\u0099\3\2\2\2\u0092\u0093\f\3\2\2\u0093\u0094\7\21"+ - "\2\2\u0094\u0095\5\22\n\2\u0095\u0096\7\22\2\2\u0096\u0098\3\2\2\2\u0097"+ - "\u0092\3\2\2\2\u0098\u009b\3\2\2\2\u0099\u0097\3\2\2\2\u0099\u009a\3\2"+ - "\2\2\u009a\21\3\2\2\2\u009b\u0099\3\2\2\2\u009c\u009d\b\n\1\2\u009d\u009e"+ - "\7\5\2\2\u009e\u009f\5\22\n\2\u009f\u00a0\7\6\2\2\u00a0\u00b3\3\2\2\2"+ - "\u00a1\u00a2\7\64\2\2\u00a2\u00a4\7\5\2\2\u00a3\u00a5\5\24\13\2\u00a4"+ - "\u00a3\3\2\2\2\u00a4\u00a5\3\2\2\2\u00a5\u00a6\3\2\2\2\u00a6\u00b3\7\6"+ - "\2\2\u00a7\u00a8\7\5\2\2\u00a8\u00a9\5\f\7\2\u00a9\u00aa\7\6\2\2\u00aa"+ - "\u00ab\5\22\n\17\u00ab\u00b3\3\2\2\2\u00ac\u00ad\t\2\2\2\u00ad\u00b3\5"+ - "\22\n\r\u00ae\u00b3\7\64\2\2\u00af\u00b3\7+\2\2\u00b0\u00b3\7)\2\2\u00b1"+ - "\u00b3\7*\2\2\u00b2\u009c\3\2\2\2\u00b2\u00a1\3\2\2\2\u00b2\u00a7\3\2"+ - "\2\2\u00b2\u00ac\3\2\2\2\u00b2\u00ae\3\2\2\2\u00b2\u00af\3\2\2\2\u00b2"+ - "\u00b0\3\2\2\2\u00b2\u00b1\3\2\2\2\u00b3\u00cd\3\2\2\2\u00b4\u00b5\f\f"+ - "\2\2\u00b5\u00b6\t\3\2\2\u00b6\u00cc\5\22\n\r\u00b7\u00b8\f\13\2\2\u00b8"+ - "\u00b9\t\4\2\2\u00b9\u00cc\5\22\n\f\u00ba\u00bb\f\n\2\2\u00bb\u00bc\t"+ - "\5\2\2\u00bc\u00cc\5\22\n\13\u00bd\u00be\f\t\2\2\u00be\u00bf\t\6\2\2\u00bf"+ - "\u00cc\5\22\n\n\u00c0\u00c1\f\b\2\2\u00c1\u00c2\t\7\2\2\u00c2\u00cc\5"+ - "\22\n\t\u00c3\u00c4\f\7\2\2\u00c4\u00c5\t\b\2\2\u00c5\u00cc\5\22\n\b\u00c6"+ - "\u00c7\f\16\2\2\u00c7\u00c8\7\21\2\2\u00c8\u00c9\5\22\n\2\u00c9\u00ca"+ - "\7\22\2\2\u00ca\u00cc\3\2\2\2\u00cb\u00b4\3\2\2\2\u00cb\u00b7\3\2\2\2"+ - "\u00cb\u00ba\3\2\2\2\u00cb\u00bd\3\2\2\2\u00cb\u00c0\3\2\2\2\u00cb\u00c3"+ - "\3\2\2\2\u00cb\u00c6\3\2\2\2\u00cc\u00cf\3\2\2\2\u00cd\u00cb\3\2\2\2\u00cd"+ - "\u00ce\3\2\2\2\u00ce\23\3\2\2\2\u00cf\u00cd\3\2\2\2\u00d0\u00d5\5\22\n"+ - "\2\u00d1\u00d2\7\17\2\2\u00d2\u00d4\5\22\n\2\u00d3\u00d1\3\2\2\2\u00d4"+ - "\u00d7\3\2\2\2\u00d5\u00d3\3\2\2\2\u00d5\u00d6\3\2\2\2\u00d6\25\3\2\2"+ - "\2\u00d7\u00d5\3\2\2\2\27\34 \',\61\67J]druw\u0081\u0086\u0090\u0099\u00a4"+ - "\u00b2\u00cb\u00cd\u00d5"; + "\3\4\3\4\3\4\3\4\3\4\5\4\\\n\4\3\4\5\4_\n\4\3\5\3\5\3\5\7\5d\n\5\f\5\16"+ + "\5g\13\5\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\7\3\7\3\7\5\7t\n\7\3\7\7\7"+ + "w\n\7\f\7\16\7z\13\7\3\b\3\b\3\b\3\b\3\b\7\b\u0081\n\b\f\b\16\b\u0084"+ + "\13\b\3\b\3\b\5\b\u0088\n\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\5\t\u0092"+ + "\n\t\3\t\3\t\3\t\3\t\3\t\7\t\u0099\n\t\f\t\16\t\u009c\13\t\3\n\3\n\3\n"+ + "\3\n\3\n\3\n\3\n\3\n\5\n\u00a6\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ + "\3\n\3\n\3\n\5\n\u00b4\n\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n"+ + "\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\n\7\n\u00cd\n\n\f\n\16"+ + "\n\u00d0\13\n\3\13\3\13\3\13\7\13\u00d5\n\13\f\13\16\13\u00d8\13\13\3"+ + "\13\2\5\f\20\22\f\2\4\6\b\n\f\16\20\22\24\2\t\4\2\20\20\23\27\3\2\30\31"+ + "\4\2\20\20\32\32\3\2\23\24\3\2\33#\3\2$%\3\2&\'\2\u00f8\2\26\3\2\2\2\4"+ + "\32\3\2\2\2\6^\3\2\2\2\b`\3\2\2\2\nh\3\2\2\2\fk\3\2\2\2\16\u0087\3\2\2"+ + "\2\20\u0091\3\2\2\2\22\u00b3\3\2\2\2\24\u00d1\3\2\2\2\26\27\5\4\3\2\27"+ + "\30\7\2\2\3\30\3\3\2\2\2\31\33\5\6\4\2\32\31\3\2\2\2\33\34\3\2\2\2\34"+ + "\32\3\2\2\2\34\35\3\2\2\2\35\5\3\2\2\2\36 \7\3\2\2\37!\5\4\3\2 \37\3\2"+ + "\2\2 !\3\2\2\2!\"\3\2\2\2\"_\7\4\2\2#$\5\f\7\2$%\7\64\2\2%\'\7\5\2\2&"+ + "(\5\b\5\2\'&\3\2\2\2\'(\3\2\2\2()\3\2\2\2)*\7\6\2\2*,\7\3\2\2+-\5\4\3"+ + "\2,+\3\2\2\2,-\3\2\2\2-.\3\2\2\2./\7\4\2\2/_\3\2\2\2\60\62\7\7\2\2\61"+ + "\60\3\2\2\2\61\62\3\2\2\2\62\63\3\2\2\2\63\64\5\f\7\2\64\67\7\64\2\2\65"+ + "\66\7\b\2\2\668\5\16\b\2\67\65\3\2\2\2\678\3\2\2\289\3\2\2\29:\7\t\2\2"+ + ":_\3\2\2\2;<\5\20\t\2<=\7\b\2\2=>\5\22\n\2>?\7\t\2\2?_\3\2\2\2@A\5\22"+ + "\n\2AB\7\t\2\2B_\3\2\2\2CD\7\n\2\2DE\7\5\2\2EF\5\22\n\2FG\7\6\2\2GJ\5"+ + "\6\4\2HI\7\13\2\2IK\5\6\4\2JH\3\2\2\2JK\3\2\2\2K_\3\2\2\2LM\7\f\2\2MN"+ + "\7\5\2\2NO\5\22\n\2OP\7\6\2\2PQ\5\6\4\2Q_\3\2\2\2RS\7\r\2\2ST\5\6\4\2"+ + "TU\7\f\2\2UV\7\5\2\2VW\5\22\n\2WX\7\6\2\2X_\3\2\2\2Y[\7\16\2\2Z\\\5\22"+ + "\n\2[Z\3\2\2\2[\\\3\2\2\2\\]\3\2\2\2]_\7\t\2\2^\36\3\2\2\2^#\3\2\2\2^"+ + "\61\3\2\2\2^;\3\2\2\2^@\3\2\2\2^C\3\2\2\2^L\3\2\2\2^R\3\2\2\2^Y\3\2\2"+ + "\2_\7\3\2\2\2`e\5\n\6\2ab\7\17\2\2bd\5\n\6\2ca\3\2\2\2dg\3\2\2\2ec\3\2"+ + "\2\2ef\3\2\2\2f\t\3\2\2\2ge\3\2\2\2hi\5\f\7\2ij\7\64\2\2j\13\3\2\2\2k"+ + "l\b\7\1\2lm\7(\2\2mx\3\2\2\2no\f\4\2\2ow\7\20\2\2pq\f\3\2\2qs\7\21\2\2"+ + "rt\5\22\n\2sr\3\2\2\2st\3\2\2\2tu\3\2\2\2uw\7\22\2\2vn\3\2\2\2vp\3\2\2"+ + "\2wz\3\2\2\2xv\3\2\2\2xy\3\2\2\2y\r\3\2\2\2zx\3\2\2\2{\u0088\5\22\n\2"+ + "|}\7\3\2\2}\u0082\5\16\b\2~\177\7\17\2\2\177\u0081\5\16\b\2\u0080~\3\2"+ + "\2\2\u0081\u0084\3\2\2\2\u0082\u0080\3\2\2\2\u0082\u0083\3\2\2\2\u0083"+ + "\u0085\3\2\2\2\u0084\u0082\3\2\2\2\u0085\u0086\7\4\2\2\u0086\u0088\3\2"+ + "\2\2\u0087{\3\2\2\2\u0087|\3\2\2\2\u0088\17\3\2\2\2\u0089\u008a\b\t\1"+ + "\2\u008a\u008b\7\5\2\2\u008b\u008c\5\20\t\2\u008c\u008d\7\6\2\2\u008d"+ + "\u0092\3\2\2\2\u008e\u0092\7\64\2\2\u008f\u0090\7\20\2\2\u0090\u0092\5"+ + "\20\t\4\u0091\u0089\3\2\2\2\u0091\u008e\3\2\2\2\u0091\u008f\3\2\2\2\u0092"+ + "\u009a\3\2\2\2\u0093\u0094\f\3\2\2\u0094\u0095\7\21\2\2\u0095\u0096\5"+ + "\22\n\2\u0096\u0097\7\22\2\2\u0097\u0099\3\2\2\2\u0098\u0093\3\2\2\2\u0099"+ + "\u009c\3\2\2\2\u009a\u0098\3\2\2\2\u009a\u009b\3\2\2\2\u009b\21\3\2\2"+ + "\2\u009c\u009a\3\2\2\2\u009d\u009e\b\n\1\2\u009e\u009f\7\5\2\2\u009f\u00a0"+ + "\5\22\n\2\u00a0\u00a1\7\6\2\2\u00a1\u00b4\3\2\2\2\u00a2\u00a3\7\64\2\2"+ + "\u00a3\u00a5\7\5\2\2\u00a4\u00a6\5\24\13\2\u00a5\u00a4\3\2\2\2\u00a5\u00a6"+ + "\3\2\2\2\u00a6\u00a7\3\2\2\2\u00a7\u00b4\7\6\2\2\u00a8\u00a9\7\5\2\2\u00a9"+ + "\u00aa\5\f\7\2\u00aa\u00ab\7\6\2\2\u00ab\u00ac\5\22\n\17\u00ac\u00b4\3"+ + "\2\2\2\u00ad\u00ae\t\2\2\2\u00ae\u00b4\5\22\n\r\u00af\u00b4\7\64\2\2\u00b0"+ + "\u00b4\7+\2\2\u00b1\u00b4\7)\2\2\u00b2\u00b4\7*\2\2\u00b3\u009d\3\2\2"+ + "\2\u00b3\u00a2\3\2\2\2\u00b3\u00a8\3\2\2\2\u00b3\u00ad\3\2\2\2\u00b3\u00af"+ + "\3\2\2\2\u00b3\u00b0\3\2\2\2\u00b3\u00b1\3\2\2\2\u00b3\u00b2\3\2\2\2\u00b4"+ + "\u00ce\3\2\2\2\u00b5\u00b6\f\f\2\2\u00b6\u00b7\t\3\2\2\u00b7\u00cd\5\22"+ + "\n\r\u00b8\u00b9\f\13\2\2\u00b9\u00ba\t\4\2\2\u00ba\u00cd\5\22\n\f\u00bb"+ + "\u00bc\f\n\2\2\u00bc\u00bd\t\5\2\2\u00bd\u00cd\5\22\n\13\u00be\u00bf\f"+ + "\t\2\2\u00bf\u00c0\t\6\2\2\u00c0\u00cd\5\22\n\n\u00c1\u00c2\f\b\2\2\u00c2"+ + "\u00c3\t\7\2\2\u00c3\u00cd\5\22\n\t\u00c4\u00c5\f\7\2\2\u00c5\u00c6\t"+ + "\b\2\2\u00c6\u00cd\5\22\n\b\u00c7\u00c8\f\16\2\2\u00c8\u00c9\7\21\2\2"+ + "\u00c9\u00ca\5\22\n\2\u00ca\u00cb\7\22\2\2\u00cb\u00cd\3\2\2\2\u00cc\u00b5"+ + "\3\2\2\2\u00cc\u00b8\3\2\2\2\u00cc\u00bb\3\2\2\2\u00cc\u00be\3\2\2\2\u00cc"+ + "\u00c1\3\2\2\2\u00cc\u00c4\3\2\2\2\u00cc\u00c7\3\2\2\2\u00cd\u00d0\3\2"+ + "\2\2\u00ce\u00cc\3\2\2\2\u00ce\u00cf\3\2\2\2\u00cf\23\3\2\2\2\u00d0\u00ce"+ + "\3\2\2\2\u00d1\u00d6\5\22\n\2\u00d2\u00d3\7\17\2\2\u00d3\u00d5\5\22\n"+ + "\2\u00d4\u00d2\3\2\2\2\u00d5\u00d8\3\2\2\2\u00d6\u00d4\3\2\2\2\u00d6\u00d7"+ + "\3\2\2\2\u00d7\25\3\2\2\2\u00d8\u00d6\3\2\2\2\30\34 \',\61\67J[^esvx\u0082"+ + "\u0087\u0091\u009a\u00a5\u00b3\u00cc\u00ce\u00d6"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/src/dk/camelot64/kickc/test/Main.java b/src/dk/camelot64/kickc/test/Main.java index 27e86c2f2..3d456d4f7 100644 --- a/src/dk/camelot64/kickc/test/Main.java +++ b/src/dk/camelot64/kickc/test/Main.java @@ -13,7 +13,7 @@ import java.util.List; /** Test my KickC Grammar */ public class Main { public static void main(String[] args) throws IOException { - final String fileName = "src/dk/camelot64/kickc/test/selfassign.kc"; + final String fileName = "src/dk/camelot64/kickc/test/callsum.kc"; final CharStream input = CharStreams.fromFileName(fileName); System.out.println(input.toString()); KickCLexer lexer = new KickCLexer(input); @@ -29,11 +29,13 @@ public class Main { Pass1GenerateStatementSequence pass1GenerateStatementSequence = new Pass1GenerateStatementSequence(); pass1GenerateStatementSequence.generate(file); StatementSequence statementSequence = pass1GenerateStatementSequence.getSequence(); - SymbolTable symbolTable = pass1GenerateStatementSequence.getSymbols(); + SymbolTable symbolTable = pass1GenerateStatementSequence.getProgramSymbols(); new PassTypeInference().inferTypes(statementSequence, symbolTable); System.out.println("PROGRAM"); System.out.println(statementSequence.toString()); + System.out.println("SYMBOLS"); + System.out.println(symbolTable.getSymbolTableContents()); Pass1GenerateControlFlowGraph pass1GenerateControlFlowGraph = new Pass1GenerateControlFlowGraph(symbolTable); ControlFlowGraph controlFlowGraph = pass1GenerateControlFlowGraph.generate(statementSequence); diff --git a/src/dk/camelot64/kickc/test/callinc.kc b/src/dk/camelot64/kickc/test/callinc.kc new file mode 100644 index 000000000..a908b6687 --- /dev/null +++ b/src/dk/camelot64/kickc/test/callinc.kc @@ -0,0 +1,9 @@ +byte i = 5; +a = inc(3); +a = inc(a); +a = a + i; + +byte inc(byte a) { + i = i + 1; + return a + i; +} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/test/callsum.kc b/src/dk/camelot64/kickc/test/callsum.kc new file mode 100644 index 000000000..42e74c773 --- /dev/null +++ b/src/dk/camelot64/kickc/test/callsum.kc @@ -0,0 +1,9 @@ +byte a = 12; +byte s = sum(5,a); +a = a+s; +a = sum(s, a); +return; + +byte sum(byte b1, byte b2) { + return b1+b2; +} \ No newline at end of file diff --git a/src/dk/camelot64/kickc/test/fct-inc.txt b/src/dk/camelot64/kickc/test/fct-inc.txt index 658c2c77e..a1eb38697 100644 --- a/src/dk/camelot64/kickc/test/fct-inc.txt +++ b/src/dk/camelot64/kickc/test/fct-inc.txt @@ -11,12 +11,11 @@ byte inc(byte a) { // Not committed to a specific parameter transfer style (non SSA) @BEGIN: (byte) i := 5 - (byte) a := call INC 3 - (byte) a := call INC a + (byte) a := call inc 3 + (byte) a := call inc a (byte) a := a + i to: @END -INC: - (byte) param INC.a +byte inc(byte a): (byte) i := i + 1 (byte§) $1 := INC.a + i return (byte) $1 @@ -25,38 +24,37 @@ INC: // Variable/Register parameter/return transfer (non SSA) @BEGIN: (byte) i := 5 - (byte) INC.a := 3 - (byte) a := call INC + (byte) inc.a := 3 + (byte) a := call inc to: @1 @1: - (byte) INC.a := a - (byte) a := call INC + (byte) inc.a := a + (byte) a := call inc to: @2 @2: (byte§) a := a + i to: @END -INC: - (byte) param INC.a +inc: (byte) inc((byte) a) (byte) i := i + 1 - (byte§) $1 := INC.a + i + (byte§) $1 := inc.a + i (byte)return $1 to: @RETURN // Variable/Register parameter/return transfer (SSA) @BEGIN: (byte) i#0 := 5 - (byte) INC.a#0 := 3 - call INC - (byte) a#0 := INC.return#0 - (byte) i#3 := INC.i#1 + (byte) inc.a#0 := 3 + call inc + (byte) a#0 := inc.return#0 + (byte) i#3 := inc.i#1 to: @1 @1: (byte) i#2 = phi( @BEGIN/i#3) (byte§) a#1 := phi(@BEGIN/a#0) - (byte) INC.a#1 := a#1 - call INC - (byte) a#1 := INC.return#0 - (byte) i#4 := INC.i#1 + (byte) inc.a#1 := a#1 + call inc + (byte) a#1 := inc.return#0 + (byte) i#4 := inc.i#1 to @2 @2: (byte) i#1 = phi( @1/i#4) @@ -64,47 +62,46 @@ INC: (byte§) $2 := a#2 + i#1 (byte§) a#2 := $2 to: @END -INC: from @BEGIN @1 - (byte) param INC.a - (byte) INC.a#2 = phi( @BEGIN/INC.a#0 @1/INC.a#1) - (byte) INC.i#0 = phi( @BEGIN/i#0 @1/i#2) - (byte) INC.i#1 := INC.i#0 + INC.1#0; - (byte§) $1 := INC.a#2 + INC.i#1; - (byte) INC.return#0 := $1 - (byte) return INC.return#0 +inc: (byte) inc((byte) a) from @BEGIN @1 + (byte) inc.a#2 = phi( @BEGIN/inc.a#0 @1/inc.a#1) + (byte) inc.i#0 = phi( @BEGIN/i#0 @1/i#2) + (byte) inc.i#1 := inc.i#0 + 1; + (byte§) $1 := inc.a#2 + inc.i#1; + (byte) inc.return#0 := $1 + (byte) return inc.return#0 to: @RETURN // Variable/Register parameter/return transfer (SSA) optimized @BEGIN: - call INC + call inc to: @1 @1: - call INC + call inc to @2 @2: - (byte§) a#2 := INC.return#0 + INC.i#1 + (byte§) a#2 := inc.return#0 + inc.i#1 to: @END -INC: from @BEGIN @1 - (byte) INC.a#2 = phi( @BEGIN/3 @1/INC.return#0) - (byte) INC.i#0 = phi( @BEGIN/5 @1/INC.i#1) - (byte) INC.i#1 := INC.i#0 + 1; - (byte) INC.return#0 := INC.a#2 + INC.i#1 +inc: (byte) inc((byte) a) from @BEGIN @1 + (byte) inc.a#2 = phi( @BEGIN/3 @1/inc.return#0) + (byte) inc.i#0 = phi( @BEGIN/5 @1/inc.i#1) + (byte) inc.i#1 := inc.i#0 + 1; + (byte) inc.return#0 := inc.a#2 + inc.i#1 to: @RETURN // Inline call (non SSA) @BEGIN: (byte) i := 5 - to: INC@1 -INC@1: - (byte) INC.a := 3 + to: inc@1 +inc@1: + (byte) inc.a := 3 (byte) i := i + 1 - (byte§) $2 := INC.a + i + (byte§) $2 := inc.a + i (byte) a := (byte) $2 - to: INC@2 -INC@2: - (byte) INC.a := a + to: inc@2 +inc@2: + (byte) inc.a := a (byte) i := i + 1 - (byte§) $3 := INC.a + i + (byte§) $3 := inc.a + i (byte) a := (byte) $3 to: @1 @1: @@ -114,28 +111,29 @@ INC@2: // Inline call (SSA) @BEGIN: (byte) i#0 := 5 - to: INC@1 -INC@1: + to: inc@1 +inc@1: from @BEGIN (byte) i#5 := phi(@BEGIN/i#0) - (byte) INC.a#0 := 3 + (byte) inc.a#0 := 3 (byte) i#1 := i#5 + 1 - (byte§) $2 := INC.a#0 + i#1 + (byte§) $2 := inc.a#0 + i#1 (byte) a#0 := (byte) $2 - to: INC@2 -INC@2: - (byte) i#4 := phi(INC@2/i#1) - (byte) a#4 := phi(INC@1/a#0) - (byte) INC.a#1 := a#4 + to: inc@2 +inc@2: from inc@1 + (byte) i#4 := phi(inc@2/i#1) + (byte) a#4 := phi(inc@1/a#0) + (byte) inc.a#1 := a#4 (byte) i#2 := i#4 + 1 - (byte§) $3 := INC.a#1 + i#2 + (byte§) $3 := inc.a#1 + i#2 (byte) a#1 := (byte) $3 to: @1 -@1: - (byte) i#3 := phi(INC@2/i#2) - (byte) a#3 := phi(INC@2/a#1) +@1: from inc@2 + (byte) i#3 := phi(inc@2/i#2) + (byte) a#3 := phi(inc@2/a#1) (byte) a#2 := a#3 + i#3; to: @END + // Inline call (SSA) - optimized @BEGIN: (byte) i#3 := 7