-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathifElseStatements.cpp
100 lines (90 loc) · 3.58 KB
/
ifElseStatements.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/**
* Implementation of \ref ifElseStatements class
*/
#include "ifElseStatements.h"
#include "utilities.h"
/**
* Constructor for the class
* @param condition condition in the if
* @param block1 block for the if
* @param block2 block for else part
*/
ifElseStatements::ifElseStatements(class Expression *condition, class Block *block1, class Block *block2) {
this->stype = stmtType::NonReturn;
this->condition = condition;
this->if_block = block1;
this->else_block = block2;
}
Value *ifElseStatements::generateCode(Constructs *compilerConstructs) {
/* Generate code for the condition */
Value *cond = condition->generateCode(compilerConstructs);
if (cond == nullptr) {
compilerConstructs->errors++;
return reportError("Invalid Expression in the IF");
}
/* Create blocks for if, else and next part of the code */
Function *TheFunction = compilerConstructs->Builder->GetInsertBlock()->getParent();
BasicBlock *ifBlock = BasicBlock::Create(compilerConstructs->Context, "if", TheFunction);
BasicBlock *elseBlock = BasicBlock::Create(compilerConstructs->Context, "else");
BasicBlock *nextBlock = BasicBlock::Create(compilerConstructs->Context, "ifcont");
BasicBlock *otherBlock = elseBlock;
bool ret_if = if_block->has_return(), ret_else = false;
/// Create a conditional break and an insert point
if (else_block == nullptr) {
otherBlock = nextBlock;
}
compilerConstructs->Builder->CreateCondBr(cond, ifBlock, otherBlock);
compilerConstructs->Builder->SetInsertPoint(ifBlock);
/// generate the code for if block
Value *if_val = if_block->generateCode(compilerConstructs);
if (if_val == nullptr) {
return nullptr;
}
/// Create a break for next part of the code after else block
if (!ret_if) {
compilerConstructs->Builder->CreateBr(nextBlock);
}
ifBlock = compilerConstructs->Builder->GetInsertBlock();
/// Create insert point for else block
Value *else_val = nullptr;
if (else_block != nullptr) {
/// Generate code for else block
TheFunction->getBasicBlockList().push_back(elseBlock);
compilerConstructs->Builder->SetInsertPoint(elseBlock);
else_val = else_block->generateCode(compilerConstructs);
if (else_val == nullptr) {
return nullptr;
}
ret_else = else_block->has_return();
if (!ret_else)
compilerConstructs->Builder->CreateBr(nextBlock);
}
// Create a break for the next part of the code
TheFunction->getBasicBlockList().push_back(nextBlock);
compilerConstructs->Builder->SetInsertPoint(nextBlock);
if (ret_else && ret_if) {
// if both if and else block have a return statement create a dummy instruction to hold a next block
Type *retType = compilerConstructs->Builder->GetInsertBlock()->getParent()->getReturnType();
if (retType == Type::getVoidTy(compilerConstructs->Context))
compilerConstructs->Builder->CreateRetVoid();
else {
compilerConstructs->Builder->CreateRet(ConstantInt::get(compilerConstructs->Context, APInt(32, 0)));
}
}
Value *V = ConstantInt::get(compilerConstructs->Context, APInt(32, 0));
return V;
}
/**
* See if this block of if else statements return a value
* @return true if the return a value false otherwise
*/
bool ifElseStatements::has_return() {
bool status = false;
if (if_block != nullptr) {
status = status | if_block->has_return();
}
if (else_block != nullptr) {
status = status | if_block->has_return();
}
return status;
}