-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlogicalcond.cpp
More file actions
81 lines (67 loc) · 2.17 KB
/
logicalcond.cpp
File metadata and controls
81 lines (67 loc) · 2.17 KB
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
#include "logicalcond.hpp"
#include "symbol.h"
LogicalCond::LogicalCond(Condition *l, char o, Condition *r): c1(l), op(o), c2(r) {}
LogicalCond::~LogicalCond() { delete c1; delete c2; }
void LogicalCond::printAST(std::ostream &out) const {
out << op << "(" << *c1;
if (c2 != nullptr)
out << ", " << *c2 << ")";
}
void LogicalCond::sem()
{
c1->type_check(typeBoolean);
if (c2 != nullptr)
c2->type_check(typeBoolean);
expr_type = typeBoolean;
}
llvm::Value* LogicalCond::compile() {
llvm::Value *L = c1->compile();
llvm::Value *R;
if (!L)
return nullptr;
/* 'not' logical condition*/
if (op == 'n')
return Builder.CreateNot(L, "logicalnottemp");
/* 'and' and 'or' logical conditions */
/* Grab current function and create basic blocks */
llvm::Function *TheFunction = Builder.GetInsertBlock()->getParent();
llvm::BasicBlock *NoSkipBB = llvm::BasicBlock::Create(TheContext, "noskip", TheFunction);
llvm::BasicBlock *SkipBB = llvm::BasicBlock::Create(TheContext, "skip", TheFunction);
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
/*
* Short circuit:
* and: If L is false, then we skip R
* or: If L is true, then we skip R
*/
if (op == 'a')
Builder.CreateCondBr(L, NoSkipBB, SkipBB);
else if (op == 'o')
Builder.CreateCondBr(L, SkipBB, NoSkipBB);
else
/* Execution should never reach this point */
return nullptr;
/* Compile c2 */
Builder.SetInsertPoint(NoSkipBB);
R = c2->compile();
/* Create the Instruction */
llvm::Value *opVal;
if (op == 'a')
opVal = Builder.CreateAnd(L, R, "logicalandtemp");
else if (op == 'o')
opVal = Builder.CreateOr(L, R, "logicalandtemp");
else
/* Execution should never reach this point */
return nullptr;
/*
* This is important, in case of multiple chained logical operations we want the phi instruction below
* to have the correct incoming edge
*/
llvm::BasicBlock *OpValBB = Builder.GetInsertBlock();
Builder.CreateBr(SkipBB);
/* SkipBB */
Builder.SetInsertPoint(SkipBB);
llvm::PHINode *val = Builder.CreatePHI(L->getType(), 2, "phival");
val->addIncoming(L, CurBB);
val->addIncoming(opVal, OpValBB);
return val;
}