-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathforStatement.cpp
83 lines (75 loc) · 3.45 KB
/
forStatement.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
* Implementation of \ref forStatement class
*/
#include <utility>
#include "forStatement.h"
#include "utilities.h"
/**
* Constructor for the class
* @param loop_variable variable iterated in the loop
* @param init initial value for the loop variable
* @param condition condition for the loop variable to break
* @param block body of the for loop
*/
forStatement::forStatement(string loop_variable, class Expression *init, class Expression *condition,
class Block *block) {
this->stype = stmtType::NonReturn;
this->var = std::move(loop_variable);
this->init = init;
this->condition = condition;
this->body = block;
}
Value *forStatement::generateCode(Constructs *compilerConstructs) {
Value *start = init->generateCode(compilerConstructs);
if (start == nullptr) {
return nullptr;
}
if (init->getEtype() == exprType::location) {
start = compilerConstructs->Builder->CreateLoad(start);
}
/* Get the parent method of this for loop */
Function *TheFunction = compilerConstructs->Builder->GetInsertBlock()->getParent();
/* Create memory for the loop variable */
llvm::AllocaInst *Alloca = compilerConstructs->CreateEntryBlockAlloca(TheFunction, var, string("int"));
compilerConstructs->Builder->CreateStore(start, Alloca);
Value *step_val = ConstantInt::get(compilerConstructs->Context, APInt(32, 1));
BasicBlock *pre_header_basic_block = compilerConstructs->Builder->GetInsertBlock();
BasicBlock *loop_body = BasicBlock::Create(compilerConstructs->Context, "loop", TheFunction);
BasicBlock *afterBB = BasicBlock::Create(compilerConstructs->Context, "afterloop", TheFunction);
compilerConstructs->Builder->CreateBr(loop_body);
compilerConstructs->Builder->SetInsertPoint(loop_body);
PHINode *Variable = compilerConstructs->Builder->CreatePHI(Type::getInt32Ty(compilerConstructs->Context), 2, var);
Variable->addIncoming(start, pre_header_basic_block);
/* Store the old value */
Value *cond = condition->generateCode(compilerConstructs);
if (cond == nullptr) {
compilerConstructs->errors++;
return reportError("Invalid Condition");
}
// Check if condition is a location
if (condition->getEtype() == exprType::location) {
cond = compilerConstructs->Builder->CreateLoad(cond);
}
compilerConstructs->loops->push(new loopInfo(afterBB, loop_body, cond, var, Variable));
llvm::AllocaInst *OldVal = compilerConstructs->NamedValues[var];
compilerConstructs->NamedValues[var] = Alloca;
/* Generate the code for the body */
if (body->generateCode(compilerConstructs) == nullptr) {
return nullptr;
}
Value *cur = compilerConstructs->Builder->CreateLoad(Alloca, var);
Value *next_val = compilerConstructs->Builder->CreateAdd(cur, step_val, "NextVal");
compilerConstructs->Builder->CreateStore(next_val, Alloca);
cond = compilerConstructs->Builder->CreateICmpSLT(next_val, cond, "loopcondition");
BasicBlock *loopEndBlock = compilerConstructs->Builder->GetInsertBlock();
compilerConstructs->Builder->CreateCondBr(cond, loop_body, afterBB);
compilerConstructs->Builder->SetInsertPoint(afterBB);
Variable->addIncoming(next_val, loopEndBlock);
if (OldVal) {
compilerConstructs->NamedValues[var] = OldVal;
} else {
compilerConstructs->NamedValues.erase(var);
}
llvm::Value *V = ConstantInt::get(compilerConstructs->Context, APInt(32, 1));
return V;
}