Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(128)

Side by Side Diff: src/IceInstVarIter.h

Issue 1323693002: Subzero: Provide a macro for iterating over instruction variables. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 //===- subzero/src/IceInstVarIter.h - Iterate over inst vars-----*- C++ -*-===//
Jim Stichnoth 2015/08/29 23:20:39 s/vars-/vars /
John 2015/08/31 16:26:39 Done.
2 //
3 // The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This file defines a common pattern for iterating over the variables of an
12 /// instruction.
13 ///
14 //===----------------------------------------------------------------------===//
15
16 #ifndef SUBZERO_SRC_ICEINSTVARITER_H
17 #define SUBZERO_SRC_ICEINSTVARITER_H
18
19 /// In Subzero, an Instr may have multiple Ice::Operands, and each Operand can
20 /// have zero, one, or more Variables.
21 ///
22 /// We found that a common pattern in Subzero is to iterate over all the
23 /// Variables in an Instruction. This lead to the following pattern being
Jim Stichnoth 2015/08/29 23:20:39 leads or led
John 2015/08/31 16:26:39 Done.
24 /// repeated multiple times across the codebase:
25 ///
26 /// for (Operand Op : Instr.Operands())
27 /// for (Variable Var : Op.Vars())
28 /// do_my_thing(Var, Instr)
29 ///
30 ///
31 /// This code is straightforward, but one may take a couple of seconds to
32 /// identify what it is doing. We therefore introduce a macroized iterator for
33 /// hiding this common idiom behind a more explicit interface.
34 ///
35 /// FOREACH_VAR_IN_INST(Var, Instr) provides this interface. Its first argument
36 /// needs to be a valid C++ identifier currently undeclared in the current
37 /// scope; Instr can be any expression yielding a Ice::Inst&&. Even though its
38 /// definition is ugly, awful, painful-to-read, using it is fairly simple:
ascull 2015/08/31 16:30:21 Why no use a function for this and pass in a lambd
John 2015/08/31 17:43:09 I am all for avoiding macros/macro-trickery and ot
39 ///
40 /// FOREACH_VAR_IN_INST(Var, Instr)
41 /// do_my_thing(Var, Instr)
42 ///
43 /// If your loop body contains more than one statement, you can wrap it with a
44 /// {}, just like any other C++ statement. Note that doing
45 ///
46 /// FOREACH_VAR_IN_INST(Var0, Instr0)
47 /// FOREACH_VAR_IN_INST(Var1, Instr1)
48 ///
49 /// is perfectly safe and legal -- as long as Var0 and Var1 are different
50 /// identifiers.
51 ///
52 /// It is sometimes useful to know Var's index in Instr, which can be obtained
53 /// with
54 ///
55 /// IndexOfVarInInst(Var)
56 ///
57 /// Similarly, the current Variable's Operand index can be obtained with
58 ///
59 /// IndexOfVarOperandInInst(Var).
60 ///
61 /// And that's pretty much it. Now, if you really hate yourself, keep reading,
62 /// but beware! The iterator implementation abuses comma operators, for
63 /// statements, variable initialization and expression evaluations. You have
64 /// been warned.
65 ///
66 /// **Implementation details**
67 ///
68 /// First, let's "break" the two loops into multiple parts:
69 ///
70 /// for ( Init1; Cond1; Step1 )
71 /// for ( Init2; Cond2; Step2 )
72 ///
73 /// The hariest, scariest, most confusing parts here are Init2 and Cond2, so
Jim Stichnoth 2015/08/29 23:20:39 hairiest
John 2015/08/31 16:26:39 Done.
74 /// let's save them for later.
75 ///
76 /// 1) Init1 declares five integer variables:
77 /// * i --> outer loop control variable;
78 /// * Var##Index --> the current variable index
79 /// * SrcSize --> how many operands does Instr have?
80 /// * j --> the inner loop control variable
81 /// * NumVars --> how many variables does the current operand have?
82 ///
83 /// 2) Cond1 and Step1 are your typical for condition and step expressions.
84 ///
85 /// 3) Init2 is where the voodoo starts. It declares a Variable * local
86 /// variable name 'Var' (i.e., whatever identifier the first parameter to
87 /// FOREACH_VAR_IN_INST is), and initialize it with nullptr. Why nullptr?
Jim Stichnoth 2015/08/29 23:20:39 initializes
John 2015/08/31 16:26:39 Done.
88 /// Because as stated above, some operands have zero Variables, and therefore
89 /// initializing Var = CurrentOperand->Variable(0) would lead to an assertion.
90 /// Init2 is also required to initialize the control variables used in Cond2.
91 /// Therefore, we use the obscure comma operator to initialize Var, and the
92 /// control variables. The declaration
93 ///
94 /// Variable *Var = (j = 0, NumVars = CurrentOperand.NumVars, nullptr)
95 ///
96 /// achieves that.
97 ///
98 /// 4) Cond2 is where we lose all hopes of having a self-documenting
99 /// implementation. The stop condition for the inner loop is simply
100 ///
101 /// j < NumVars
102 ///
103 /// But there is one more thing we need to do before jumping to the iterators
Jim Stichnoth 2015/08/29 23:20:39 iterator's
John 2015/08/31 16:26:40 Done.
104 /// body: we need to initialize Var with the current variable, but only if the
105 /// loop has not terminated. So we implemented Cond2 in a way that it would
106 /// make
Jim Stichnoth 2015/08/29 23:20:39 weird line breaks
John 2015/08/31 16:26:39 Done.
107 /// Var point to the current Variable, but only if there were more variables.
108 /// So
109 /// Cond2 became:
110 ///
111 /// j < NumVars && (Var = CurrentOperand.Var[j])
112 ///
113 /// which is not quite right. Cond2 would evalute to false if
114 /// CurrentOperand.Var[j] == nullptr. Even though that should never happen in
115 /// Subzero, assuming this is always true is dangerous and could lead to
Jim Stichnoth 2015/08/29 23:20:39 It is in fact safe to assume that in Subzero. But
John 2015/08/31 16:26:39 Acknowledged.
116 /// problems
117 /// in the future. So we abused the comma operator one more time here:
118 ///
119 /// j < NumVars && ((Var = CurrentOperand.Var[j]), true)
120 ///
121 /// this expression will evaluate to true if, and only if, j < NumVars.
122 ///
123 /// 5) Step2 increments the inner loop's control variable, as well as the
124 /// current variable index.
125 ///
126 /// We use Var -- which should be a valid C++ identifier -- to uniquefy names --
Jim Stichnoth 2015/08/29 23:20:39 I think uniquify is the more common spelling of th
John 2015/08/31 16:26:39 Done.
127 /// e.g., i##Var instead of simply i because we want users to be able to use the
128 /// iterator for cross-products involving instructions' variables.
129 #define FOREACH_VAR_IN_INST(Var, Instr) \
130 for (SizeT ___I##Var##___ = 0, ___##Var##Index##___ = 0, \
Jim Stichnoth 2015/08/29 23:20:39 I looked more closely at C++ reserved identifiers,
John 2015/08/31 16:26:39 Done.
Jim Stichnoth 2015/08/31 18:22:21 Not quite. You're not allowed to start the identi
ascull 2015/08/31 18:33:52 http://en.cppreference.com/w/cpp/language/identifi
131 ___SrcSize##Var##___ = (Instr).getSrcSize(), ___J##Var##___ = 0, \
132 ___NumVars##Var##___ = 0; \
133 ___I##Var##___ < ___SrcSize##Var##___; ++___I##Var##___) \
134 for (Variable *Var = (___J##Var##___ = 0, \
135 ___NumVars##Var##___ = \
136 (Instr).getSrc(___I##Var##___)->getNumVars(), \
137 nullptr); \
138 ___J##Var##___ < ___NumVars##Var##___ && \
139 ((Var = (Instr).getSrc(___I##Var##___)->getVar(___J##Var##___)), \
140 true); \
141 ++___J##Var##___, ++___##Var##Index___)
142
143 #define IndexOfVarInInst(Var) ((const SizeT)___##Var##Index##___)
Jim Stichnoth 2015/08/29 23:20:39 I wonder if we could find good names for the three
John 2015/08/31 16:26:39 I am not a huge fan of prefixes/suffixes as I find
Jim Stichnoth 2015/08/31 18:22:21 Sick. :)
144 #define IndexOfVarOperandInInst(Var) ((const SizeT)___I##Var##___)
145
146 #endif // SUBZERO_SRC_ICEINSTVARITER_H
OLDNEW
« src/IceCfg.cpp ('K') | « src/IceInst.cpp ('k') | src/IceOperand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698