diff --git a/src/ast/ArrayAccessNode.cpp b/src/ast/ArrayAccessNode.cpp index 1300de6..81f0f29 100644 --- a/src/ast/ArrayAccessNode.cpp +++ b/src/ast/ArrayAccessNode.cpp @@ -2,8 +2,8 @@ #include "ir/Tac.hpp" Operand ArrayAccessNode::generateIR(CFG &graph, SymbolTable &st) { + auto arrayName = array->generateIR(graph, st); auto indexName = index->generateIR(graph, st); - auto arrayName = array->value; auto name = graph.getTemporaryName(); st.addIntegerVariable(name); graph.addInstruction(new ArrayAccessTac(name, arrayName, indexName)); diff --git a/src/ast/ArrayLengthNode.cpp b/src/ast/ArrayLengthNode.cpp index 9659ff2..6996c10 100644 --- a/src/ast/ArrayLengthNode.cpp +++ b/src/ast/ArrayLengthNode.cpp @@ -4,7 +4,7 @@ Operand ArrayLengthNode::generateIR(CFG &graph, SymbolTable &st) { auto name = graph.getTemporaryName(); st.addIntegerVariable(name); - auto arrayName = array->value; + auto arrayName = array->generateIR(graph, st); graph.addInstruction(new ArrayLengthTac(name, arrayName)); return name; } diff --git a/src/ast/BooleanExpressionNode.cpp b/src/ast/BooleanExpressionNode.cpp index dd394a9..39400dd 100644 --- a/src/ast/BooleanExpressionNode.cpp +++ b/src/ast/BooleanExpressionNode.cpp @@ -1,20 +1,76 @@ #include "ast/BooleanExpressionNode.hpp" -#include "ir/BooleanTac.hpp" +#include "ir/Tac.hpp" Operand AndNode::generateIR(CFG &graph, SymbolTable &st) { - auto lhs_name = left->generateIR(graph, st); - auto rhs_name = right->generateIR(graph, st); + auto lhsName = left->generateIR(graph, st); auto name = graph.getTemporaryName(); st.addBooleanVariable(name); - graph.addInstruction(new AndTac(name, lhs_name, rhs_name)); + + auto *rhsEvalBlock = graph.newBlock(); + auto *trueBlock = graph.newBlock(); + auto *falseBlock = graph.newBlock(); + auto *joinBlock = graph.newBlock(); + + auto *entryBlock = graph.getCurrentBlock(); + graph.addInstruction(new CondJumpTac(falseBlock->getName(), lhsName)); + graph.addInstruction(new JumpTac(rhsEvalBlock->getName())); + entryBlock->setTrueBlock(rhsEvalBlock); + entryBlock->setFalseBlock(falseBlock); + + graph.setCurrentBlock(rhsEvalBlock); + auto rhsName = right->generateIR(graph, st); + graph.addInstruction(new CondJumpTac(falseBlock->getName(), rhsName)); + graph.addInstruction(new JumpTac(trueBlock->getName())); + rhsEvalBlock->setTrueBlock(trueBlock); + rhsEvalBlock->setFalseBlock(falseBlock); + + graph.setCurrentBlock(trueBlock); + graph.addInstruction(new CopyTac(1, name)); + graph.addInstruction(new JumpTac(joinBlock->getName())); + trueBlock->setTrueBlock(joinBlock); + + graph.setCurrentBlock(falseBlock); + graph.addInstruction(new CopyTac(0, name)); + graph.addInstruction(new JumpTac(joinBlock->getName())); + falseBlock->setTrueBlock(joinBlock); + + graph.setCurrentBlock(joinBlock); return name; } Operand OrNode::generateIR(CFG &graph, SymbolTable &st) { - auto lhs_name = left->generateIR(graph, st); - auto rhs_name = right->generateIR(graph, st); + auto lhsName = left->generateIR(graph, st); auto name = graph.getTemporaryName(); st.addBooleanVariable(name); - graph.addInstruction(new OrTac(name, lhs_name, rhs_name)); + + auto *rhsEvalBlock = graph.newBlock(); + auto *trueBlock = graph.newBlock(); + auto *falseBlock = graph.newBlock(); + auto *joinBlock = graph.newBlock(); + + auto *entryBlock = graph.getCurrentBlock(); + graph.addInstruction(new CondJumpTac(rhsEvalBlock->getName(), lhsName)); + graph.addInstruction(new JumpTac(trueBlock->getName())); + entryBlock->setTrueBlock(trueBlock); + entryBlock->setFalseBlock(rhsEvalBlock); + + graph.setCurrentBlock(rhsEvalBlock); + auto rhsName = right->generateIR(graph, st); + graph.addInstruction(new CondJumpTac(falseBlock->getName(), rhsName)); + graph.addInstruction(new JumpTac(trueBlock->getName())); + rhsEvalBlock->setTrueBlock(trueBlock); + rhsEvalBlock->setFalseBlock(falseBlock); + + graph.setCurrentBlock(trueBlock); + graph.addInstruction(new CopyTac(1, name)); + graph.addInstruction(new JumpTac(joinBlock->getName())); + trueBlock->setTrueBlock(joinBlock); + + graph.setCurrentBlock(falseBlock); + graph.addInstruction(new CopyTac(0, name)); + graph.addInstruction(new JumpTac(joinBlock->getName())); + falseBlock->setTrueBlock(joinBlock); + + graph.setCurrentBlock(joinBlock); return name; } diff --git a/src/ast/ControlStatementNode.cpp b/src/ast/ControlStatementNode.cpp index 101888e..98702e2 100644 --- a/src/ast/ControlStatementNode.cpp +++ b/src/ast/ControlStatementNode.cpp @@ -15,8 +15,6 @@ Operand IfNode::generateIR(CFG &graph, SymbolTable &st) { currentBlock->setTrueBlock(trueBlock); currentBlock->setFalseBlock(joinBlock); - trueBlock->setTrueBlock(joinBlock); - graph.setCurrentBlock(trueBlock); stmt->generateIR(graph, st); graph.addInstruction(new JumpTac(joinLabel)); @@ -43,16 +41,15 @@ Operand IfElseNode::generateIR(CFG &graph, SymbolTable &st) { currentBlock->setTrueBlock(trueBlock); currentBlock->setFalseBlock(falseBlock); - trueBlock->setTrueBlock(joinBlock); - falseBlock->setTrueBlock(joinBlock); - graph.setCurrentBlock(trueBlock); stmt->generateIR(graph, st); graph.addInstruction(new JumpTac(joinLabel)); + graph.getCurrentBlock()->setTrueBlock(joinBlock); graph.setCurrentBlock(falseBlock); elseStmt->generateIR(graph, st); graph.addInstruction(new JumpTac(joinLabel)); + graph.getCurrentBlock()->setTrueBlock(joinBlock); graph.setCurrentBlock(joinBlock); @@ -76,7 +73,6 @@ Operand WhileNode::generateIR(CFG &graph, SymbolTable &st) { graph.addInstruction(new JumpTac(bodyBlock->getName())); graph.setCurrentBlock(bodyBlock); - currentBlock->setTrueBlock(headerBlock); stmt->generateIR(graph, st); graph.getCurrentBlock()->setTrueBlock(headerBlock); graph.addInstruction(new JumpTac(headerLabel)); diff --git a/src/ast/MethodCallNode.cpp b/src/ast/MethodCallNode.cpp index abc4e26..9a7b357 100644 --- a/src/ast/MethodCallNode.cpp +++ b/src/ast/MethodCallNode.cpp @@ -23,6 +23,7 @@ Operand MethodCallNode::generateIR(CFG &graph, SymbolTable &st) { } const auto &methodType = method->getType(); + object->generateIR(graph, st); for (const auto &arg : exprList->children) { const auto &argName = arg->generateIR(graph, st); @@ -33,7 +34,7 @@ Operand MethodCallNode::generateIR(CFG &graph, SymbolTable &st) { st.addVariable(methodType, name); const auto &methodName = id->value; - const auto argCount = std::to_string(exprList->children.size() + 1); + const auto argCount = std::to_string(exprList->children.size()); graph.addInstruction( new MethodCallTac(name, methodName, *caller_type, argCount)); return name; diff --git a/src/ast/MethodCallWithoutArgumentsNode.cpp b/src/ast/MethodCallWithoutArgumentsNode.cpp index 218e47c..ad7eb0e 100644 --- a/src/ast/MethodCallWithoutArgumentsNode.cpp +++ b/src/ast/MethodCallWithoutArgumentsNode.cpp @@ -21,11 +21,12 @@ Operand MethodCallWithoutArgumentsNode::generateIR(CFG &graph, } const auto &methodType = method->getType(); + object->generateIR(graph, st); const auto &name = graph.getTemporaryName(); st.addVariable(methodType, name); const auto &methodName = id->value; graph.addInstruction( - new MethodCallTac(name, methodName, *caller_type, "1")); + new MethodCallTac(name, methodName, *caller_type, "0")); return name; } diff --git a/src/ir/CFG.cpp b/src/ir/CFG.cpp index 5513d43..eb8a7bf 100644 --- a/src/ir/CFG.cpp +++ b/src/ir/CFG.cpp @@ -1,11 +1,42 @@ #include #include #include +#include #include #include "ir/CFG.hpp" #include "semantic/TypeCheckVisitor.hpp" +namespace { +void appendStopToLeafBlocks(BBlock *root, BytecodeMethod &method) { + std::vector stack{root}; + std::unordered_set visited; + + while (!stack.empty()) { + auto *block = stack.back(); + stack.pop_back(); + + if (!visited.insert(block).second) { + continue; + } + + const auto hasTrueBlock = block->hasTrueBlock(); + const auto hasFalseBlock = block->hasFalseBlock(); + if (!hasTrueBlock && !hasFalseBlock) { + method.getBytecodeMethodBlock(block->getName()).stop(); + continue; + } + + if (hasTrueBlock) { + stack.push_back(block->getTrueBlock()); + } + if (hasFalseBlock) { + stack.push_back(block->getFalseBlock()); + } + } +} +} // namespace + std::string CFG::getTemporaryName() { auto name = "_t" + std::to_string(temporaryIndex); temporaryIndex++; @@ -53,7 +84,13 @@ const std::string *CFG::typeOf(const Node &node) const { } void CFG::generateBytecode(BytecodeProgram &program, SymbolTable &st) { + BBlock *mainRoot = nullptr; + for (auto *basicBlock : methodBlocks) { + if (mainRoot == nullptr) { + mainRoot = basicBlock; + } + const auto &className = basicBlock->getClassName(); const auto &methodName = basicBlock->getMethodName(); @@ -76,8 +113,9 @@ void CFG::generateBytecode(BytecodeProgram &program, SymbolTable &st) { basicBlock->generateBytecode(bytecodeMethod); } - const auto mainName = methodBlocks.front()->getName(); - auto &mainMethod = program.getBytecodeMethod(mainName); - auto &mainBlock = mainMethod.getBytecodeMethodBlock(mainName); - mainBlock.stop(); + + if (mainRoot != nullptr) { + auto &mainMethod = program.getBytecodeMethod(mainRoot->getName()); + appendStopToLeafBlocks(mainRoot, mainMethod); + } } diff --git a/src/ir/Tac.cpp b/src/ir/Tac.cpp index 344fb27..fc55945 100644 --- a/src/ir/Tac.cpp +++ b/src/ir/Tac.cpp @@ -48,7 +48,7 @@ void CondJumpTac::print(std::ostream &os) const { os << "iffalse " << lhs << " goto " << rhs << "\n"; } void CondJumpTac::generateBytecode(BytecodeMethodBlock &block) { - block.push(lhs).cjump(rhs); + block.push(lhsOp).cjump(rhs); } void MethodCallTac::print(std::ostream &os) const {