Value *AstVarExpr::Codegen(CodeGenerator *codegen) { codegen->incrementVarCount(); Function *func = codegen->getCurrentFunction(); IAstExpression *expr = this->getAssignmentExpression(); Value *initialVal = nullptr; AllocaInst *Alloca = nullptr; if (expr == nullptr) { // variable declaration without an assignment, e.g: 'var x : int;' if (this->InferredType->getIsArray()) { // type is an array. Type *arrayType = this->InferredType->GetLLVMType(codegen); Alloca = Helpers::CreateEntryBlockAlloca(codegen, func, this->Name.c_str(), arrayType); } else { initialVal = Helpers::GetDefaultValue(codegen, this->InferredType); Alloca = Helpers::CreateEntryBlockAlloca(codegen, func, this->Name.c_str(), this->InferredType->GetLLVMType(codegen)); } } else { initialVal = expr->Codegen(codegen); auto type = Helpers::GetLLVMTypeName(initialVal->getType()); Alloca = Helpers::CreateEntryBlockAlloca(codegen, func, this->Name, initialVal->getType()); } if (initialVal != nullptr) { codegen->getBuilder().CreateStore(initialVal, Alloca); } codegen->setNamedValue(this->Name, Alloca); return initialVal == nullptr ? Alloca : initialVal; }
// EmitScopeBlock - Emits a std::vector of ast::IAstExpr* expressions and returns their value // in a std::vector<Value*> std::vector<Value*> EmitScopeBlock(CodeGenerator *codegen, const std::vector<IAstExpression*> &block, bool stopAtFirstReturn, bool *stopped) { unsigned varCount = codegen->getVarCount(); codegen->incrementNestDepth(); std::vector<Value*> vals; for (unsigned i = 0, size = block.size(); i < size; ++i) { IAstExpression *expr = block[i]; if (codegen->getBuilder().GetInsertBlock()->getTerminator() != nullptr) // stops multiple terminators per block. { Warning(expr->getPos(), "Unreachable code."); continue; } Value *val = expr->Codegen(codegen); if (val == nullptr) { vals.clear(); goto RETURN; } vals.push_back(val); if (stopAtFirstReturn && expr->getNodeType() == AstNodeType::node_return) { if (stopped != nullptr) { *stopped = true; } goto RETURN; } } if (stopped != nullptr) { *stopped = false; } RETURN: // Pops all variables declared within this scope codegen->popFromScopeStack(codegen->getVarCount() - varCount); codegen->decrementNestDepth(); return vals; }
Value *AstForExpr::Codegen(CodeGenerator *codegen) { auto x = this; Function *func = codegen->getCurrentFunction(); BasicBlock *outsideBB = codegen->getOutsideBlock(); BasicBlock *loopEndBB = BasicBlock::Create(codegen->getContext(), "loop_end", func, outsideBB); BasicBlock *loopBodyBB = BasicBlock::Create(codegen->getContext(), "loop_body", func, loopEndBB); codegen->setOutsideBlock(loopEndBB); unsigned varCountBeforeInit = codegen->getVarCount(); // Keep track of the variables created within the for loop init. // Emit the init. for (unsigned i = 0, size = this->Init.size(); i < size; ++i) { IAstExpression *expr = this->Init[i]; if (expr == nullptr || expr->Codegen(codegen) == nullptr) { return Helpers::Error(this->getPos(), "Could not initialize 'for' loop."); } } unsigned varCountAfterInit = codegen->getVarCount(); if (this->Condition == nullptr) { // Disallow for loop without condition. return Helpers::Error(this->getPos(), "For loop must have a condition."); } Value *cond = this->Condition->Codegen(codegen); if (!cond->getType()->isIntegerTy()) { // Condition isn't a possible boolean type. return Helpers::Error(this->Condition->getPos(), "'for' condition not boolean"); } Value *toBool = Helpers::ToBoolean(codegen, cond); // Eval the bool and branch accordingly codegen->getBuilder().CreateCondBr(toBool, loopBodyBB, loopEndBB); // Emit the loop body. codegen->getBuilder().SetInsertPoint(loopBodyBB); Helpers::EmitScopeBlock(codegen, this->Body, true); // Emit the afterthough Helpers::EmitScopeBlock(codegen, this->Afterthought, true); // Eval the condition, branch accordingly cond = this->Condition->Codegen(codegen); toBool = Helpers::ToBoolean(codegen, cond); codegen->getBuilder().CreateCondBr(toBool, loopBodyBB, loopEndBB); // Cleanup the variables created in the init. codegen->popFromScopeStack(varCountAfterInit - varCountBeforeInit); // Set insert point to the loop and and cleanup. codegen->getBuilder().SetInsertPoint(loopEndBB); loopBodyBB = codegen->getBuilder().GetInsertBlock(); loopEndBB = codegen->getBuilder().GetInsertBlock(); codegen->setOutsideBlock(outsideBB); return loopEndBB; }