summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-11-27 11:31:52 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-11-27 11:31:52 +0000
commit9fab57d4267770c5dd36524445c915e76b2d606a (patch)
treed799d82075e54890a63bdb0356ffb50e526d51dc
parentae6a72437d596112fc9ee38783088560d3fd5c8b (diff)
downloadpp2cc-9fab57d4267770c5dd36524445c915e76b2d606a.tar.gz
Allow if(1){}else{} to compile, optimize if/else
-rwxr-xr-xpp2cc.py74
1 files changed, 39 insertions, 35 deletions
diff --git a/pp2cc.py b/pp2cc.py
index 045cdb9..040f7c9 100755
--- a/pp2cc.py
+++ b/pp2cc.py
@@ -132,7 +132,7 @@ class Asm(object):
Note that the Zero, Negative and oVerflow flags are modified
"""
- return self.binary_op("LOAD", register, register, label)
+ return self.binary_op("LOAD", register, register, label) + " ; NOOP"
class LinkedNode(object):
"""Stores nodes with a reference to the parent"""
@@ -622,48 +622,52 @@ class Parse(object):
def parseIf(self, linked_node):
linked_node.incrementLevel()
node = linked_node.node
- #lbl_if = self.uniqLbl("if") # if
- #lbl_th = self.uniqLbl("th") # then
- if node.iffalse:
- lbl_el = self.uniqLbl("el") # else
- lbl_end = self.uniqLbl("fi") # endif
- else:
- lbl_end = lbl_fi = self.uniqLbl("fi") # endif
-
lines = self.parseStatement(node.cond, linked_node)
- # unused label, but insert it for clearness if possible
- #if len(lines) > 0:
- # if not self.asm.has_label(lines[0]):
- # lines[0] = self.asm.insert_label(lines[0], lbl_if)
-
- # if cond is zero, go to else (BEQ branches if Z=0). Do not use CMP
- lines.append(self.asm.branch_op("BEQ", lbl_el))
-
- # if true...
+ branch_op = "BEQ"
then_block = self.parseStatement(node.iftrue, linked_node)
- # required label, so insert a NOOP if necessary
- #if len(then_block) > 0:
- # if self.asm.has_label(then_block[0]):
- # lines.append(self.asm.noop(lbl_th))
- # else:
- # then_block[0] = self.asm.insert_label(then_block, lbl_th)
- lines += then_block
- lines.append(self.asm.branch_op("BRA", lbl_end))
-
- # else...
if node.iffalse:
else_block = self.parseStatement(node.iffalse, linked_node)
- if len(else_block) > 0:
+ # if(x){}else{y} is equivalent to if(!x){}
+ if not then_block:
+ # note: else can still be empty, if(x){}else{}, but that is
+ # handled below with the "if then_block"
+ then_block = else_block
+ else_block = []
+ # invert result
+ branch_op = "BNE"
+ else:
+ else_block = []
+
+ # if(x){}else{} is equivalent to x, which do not need the below
+ if then_block:
+ if else_block:
+ lbl_false = self.uniqLbl("el") # else
+ lbl_end = self.uniqLbl("fi") # endif
+ else:
+ lbl_end = lbl_false = self.uniqLbl("fi") # endif
+
+ # if cond is satisfied, go to else (BEQ branches if Z=0, BNE
+ # branches if Z!=0). Do not use CMP, rely on the status flags set
+ # set by the condition
+ lines.append(self.asm.branch_op(branch_op, lbl_false))
+ # if true...
+ lines += then_block
+
+ # else...
+ if else_block:
+ # this branch is part of the then block, but include it here to
+ # avoid redundancy (BRA lbl, lbl: NOOP)
+ lines.append(self.asm.branch_op("BRA", lbl_end))
+
+ # XXX this is optimization for labelling else, do it later?
if self.asm.has_label(else_block[0]):
- lines.append(self.asm.noop(lbl_el))
+ lines.append(self.asm.noop(lbl_false))
else:
- else_block[0] = self.asm.insert_label(else_block[0], lbl_el)
- lines += else_block
- # why branch if already at the end of the block? hmm
- #lines.append(self.asm.branch_op("BRA", lbl_end))
+ else_block[0] = self.asm.insert_label(else_block[0], lbl_false)
+ lines += else_block
- lines.append(self.asm.noop(lbl_end))
+ lines.append(self.asm.noop(lbl_end))
return lines
def parseReturn(self, linked_node):
"""Return from a function. For non-void functions the result is in R0"""