示例#1
0
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;
 }
示例#3
0
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;
}