-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathCIfNode.cpp
116 lines (87 loc) · 3.34 KB
/
CIfNode.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/*
* CIfNode.cpp
* HyperCompiler
*
* Created by Uli Kusterer on 19.05.07.
* Copyright 2007 M. Uli Kusterer. All rights reserved.
*
*/
#include "CIfNode.h"
#include "CCodeBlock.h"
#include "CNodeTransformation.h"
namespace Carlson
{
/*
- Push condition
- Check condition & jump to else section if false -+
- If section |
+-- jump over else section |
| - else section <----------------------------+
+-->
*/
void CIfNode::GenerateCode( CCodeBlock* inBlock )
{
// Push condition:
mCondition->GenerateCode(inBlock);
// Check condition, jump to Else start if FALSE:
int32_t compareInstructionOffset = (int32_t) inBlock->GetNextInstructionOffset();
inBlock->GenerateJumpRelativeIfFalseInstruction( 0 );
// Generate If section:
CCodeBlockNode::GenerateCode( inBlock );
// At end of If section, jump *over* Else section:
int32_t jumpOverElseInstructionOffset = (int32_t) inBlock->GetNextInstructionOffset();
inBlock->GenerateJumpRelativeInstruction( 0 );
// Retroactively fill in the address of the Else section in the if's jump instruction:
int32_t elseSectionStartOffset = (int32_t) inBlock->GetNextInstructionOffset();
inBlock->SetJumpAddressOfInstructionAtIndex( compareInstructionOffset, elseSectionStartOffset -compareInstructionOffset );
// Generate Else section:
if( mElseBlock )
mElseBlock->GenerateCode( inBlock );
// Retroactively fill in the address of the end of the Else section in the jump instruction at the If's end:
int32_t elseSectionEndOffset = (int32_t) inBlock->GetNextInstructionOffset();
inBlock->SetJumpAddressOfInstructionAtIndex( jumpOverElseInstructionOffset, elseSectionEndOffset -jumpOverElseInstructionOffset );
}
void CIfNode::Simplify()
{
CNode * originalNode = mCondition;
originalNode->Simplify(); // Give subnodes a chance to apply transformations first. Might expose simpler sub-nodes we can then simplify.
CNode* newNode = CNodeTransformationBase::Apply( originalNode ); // Returns either originalNode, or a totally new object, in which case we delete the old one.
if( newNode != originalNode )
{
assert( dynamic_cast<CValueNode*>(newNode) != NULL );
mCondition = (CValueNode*)newNode;
}
CCodeBlockNode::Simplify();
if( mElseBlock )
{
originalNode = mElseBlock;
originalNode->Simplify(); // Give subnodes a chance to apply transformations first. Might expose simpler sub-nodes we can then simplify.
newNode = CNodeTransformationBase::Apply( originalNode ); // Returns either 'this', or an optimized copy. We get to keep one and delete the other.
if( newNode != originalNode )
{
assert( dynamic_cast<CCodeBlockNode*>(newNode) != NULL );
mElseBlock = (CCodeBlockNode*)newNode;
}
}
}
void CIfNode::Visit( std::function<void(CNode*)> visitorBlock )
{
mCondition->Visit(visitorBlock);
if( mElseBlock )
mElseBlock->Visit(visitorBlock);
CCodeBlockNode::Visit( visitorBlock );
}
void CIfNode::DebugPrint( std::ostream& destStream, size_t indentLevel )
{
INDENT_PREPARE(indentLevel);
destStream << indentChars << "If (" << std::endl;
mCondition->DebugPrint( destStream, indentLevel );
destStream << indentChars << ")" << std::endl;
DebugPrintInner( destStream, indentLevel );
if( mElseBlock )
{
destStream << indentChars << "else" << std::endl;
mElseBlock->DebugPrintInner( destStream, indentLevel );
}
}
}