void IRGenerator::accept(MatchStmt& stmt) { FNTRACE(); Value* cond = codegen(stmt.condition()); BasicBlock* contBlock = createBlock("match.cont"); MatchInstr* matchInstr = createMatch(stmt.op(), cond); for (const MatchCase& one: stmt.cases()) { BasicBlock* bb = createBlock("match.case"); setInsertPoint(bb); codegen(one.second.get()); createBr(contBlock); for (auto& labelNode: one.first) { Constant* label = getConstant(labelNode.get()); matchInstr->addCase(label, bb); } } if (stmt.elseStmt()) { BasicBlock* elseBlock = createBlock("match.else"); setInsertPoint(elseBlock); codegen(stmt.elseStmt()); createBr(contBlock); matchInstr->setElseBlock(elseBlock); } setInsertPoint(contBlock); }
void IRGenerator::accept(MatchStmt& stmt) { FNTRACE(); // TODO BasicBlock* contBlock = createBlock("match.cont"); MatchInstr* matchInstr = new MatchInstr(stmt.op()); Value* cond = codegen(stmt.condition()); matchInstr->setCondition(cond); for (const MatchCase& one: stmt.cases()) { Value* label; if (auto e = dynamic_cast<StringExpr*>(one.first.get())) label = get(e->value()); else if (auto e = dynamic_cast<RegExpExpr*>(one.first.get())) label = get(e->value()); else { reportError("FIXME: Invalid (unsupported) literal type <%s> in match case.", tos(one.first->getType()).c_str()); result_ = nullptr; return; } BasicBlock* bb = createBlock("match.case"); setInsertPoint(bb); codegen(one.second.get()); createBr(contBlock); matchInstr->addCase(label, bb); } if (stmt.elseStmt()) { BasicBlock* elseBlock = createBlock("match.else"); setInsertPoint(elseBlock); codegen(stmt.elseStmt()); createBr(contBlock); matchInstr->setElseBlock(elseBlock); } setInsertPoint(contBlock); }
void IRGenerator::accept(CondStmt& stmt) { FNTRACE(); BasicBlock* trueBlock = createBlock("trueBlock"); BasicBlock* falseBlock = createBlock("falseBlock"); BasicBlock* contBlock = createBlock("contBlock"); Value* cond = codegen(stmt.condition()); createCondBr(cond, trueBlock, falseBlock); setInsertPoint(trueBlock); codegen(stmt.thenStmt()); createBr(contBlock); setInsertPoint(falseBlock); codegen(stmt.elseStmt()); createBr(contBlock); setInsertPoint(contBlock); }
void IRGenerator::accept(BinaryExpr& expr) { FNTRACE(); static const std::unordered_map< int /*FlowVM::Opcode*/, Value* (IRGenerator::*)(Value*, Value*, const std::string&) > ops = { // numerical { FlowVM::Opcode::NADD, &IRGenerator::createAdd }, { FlowVM::Opcode::NSUB, &IRGenerator::createSub }, { FlowVM::Opcode::NMUL, &IRGenerator::createMul }, { FlowVM::Opcode::NDIV, &IRGenerator::createDiv }, { FlowVM::Opcode::NREM, &IRGenerator::createRem }, { FlowVM::Opcode::NSHL, &IRGenerator::createShl }, { FlowVM::Opcode::NSHR, &IRGenerator::createShr }, { FlowVM::Opcode::NPOW, &IRGenerator::createPow }, { FlowVM::Opcode::NAND, &IRGenerator::createAnd }, { FlowVM::Opcode::NOR, &IRGenerator::createOr }, { FlowVM::Opcode::NXOR, &IRGenerator::createXor }, { FlowVM::Opcode::NCMPEQ, &IRGenerator::createNCmpEQ }, { FlowVM::Opcode::NCMPNE, &IRGenerator::createNCmpNE }, { FlowVM::Opcode::NCMPLE, &IRGenerator::createNCmpLE }, { FlowVM::Opcode::NCMPGE, &IRGenerator::createNCmpGE }, { FlowVM::Opcode::NCMPLT, &IRGenerator::createNCmpLT }, { FlowVM::Opcode::NCMPGT, &IRGenerator::createNCmpGT }, // string { FlowVM::Opcode::SADD, &IRGenerator::createSAdd }, { FlowVM::Opcode::SCMPEQ, &IRGenerator::createSCmpEQ }, { FlowVM::Opcode::SCMPNE, &IRGenerator::createSCmpNE }, { FlowVM::Opcode::SCMPLE, &IRGenerator::createSCmpLE }, { FlowVM::Opcode::SCMPGE, &IRGenerator::createSCmpGE }, { FlowVM::Opcode::SCMPLT, &IRGenerator::createSCmpLT }, { FlowVM::Opcode::SCMPGT, &IRGenerator::createSCmpGT }, { FlowVM::Opcode::SCMPBEG, &IRGenerator::createSCmpEB }, { FlowVM::Opcode::SCMPEND, &IRGenerator::createSCmpEE }, { FlowVM::Opcode::SCONTAINS, &IRGenerator::createSIn }, // regex { FlowVM::Opcode::SREGMATCH, &IRGenerator::createSCmpRE }, // ip { FlowVM::Opcode::PCMPEQ, &IRGenerator::createPCmpEQ }, { FlowVM::Opcode::PCMPNE, &IRGenerator::createPCmpNE }, { FlowVM::Opcode::PINCIDR, &IRGenerator::createPInCidr }, }; if (expr.op() == FlowVM::Opcode::BOR) { // (lhs || rhs) // // L = lhs(); // if (L) goto end; // R = rhs(); // L = R; // end: // result = L; BasicBlock* borLeft = createBlock("bor.left"); BasicBlock* borRight = createBlock("bor.right"); BasicBlock* borCont = createBlock("bor.cont"); AllocaInstr* result = createAlloca(FlowType::Boolean, get(1), "bor"); Value* lhs = codegen(expr.leftExpr()); createCondBr(lhs, borLeft, borRight); setInsertPoint(borLeft); createStore(result, lhs, "bor.left"); createBr(borCont); setInsertPoint(borRight); Value* rhs = codegen(expr.rightExpr()); createStore(result, rhs, "bor.right"); createBr(borCont); setInsertPoint(borCont); result_ = result; return; } Value* lhs = codegen(expr.leftExpr()); Value* rhs = codegen(expr.rightExpr()); auto i = ops.find(expr.op()); if (i != ops.end()) { result_ = (this->*i->second)(lhs, rhs, ""); } else { fprintf(stderr, "BUG: Binary operation `%s` not implemented.\n", mnemonic(expr.op())); assert(!"Unimplemented"); result_ = nullptr; } }