xref: /aosp_15_r20/external/emboss/compiler/util/traverse_ir_test.py (revision 99e0aae7469b87d12f0ad23e61142c2d74c1ef70)
1*99e0aae7SDavid Rees# Copyright 2019 Google LLC
2*99e0aae7SDavid Rees#
3*99e0aae7SDavid Rees# Licensed under the Apache License, Version 2.0 (the "License");
4*99e0aae7SDavid Rees# you may not use this file except in compliance with the License.
5*99e0aae7SDavid Rees# You may obtain a copy of the License at
6*99e0aae7SDavid Rees#
7*99e0aae7SDavid Rees#     https://www.apache.org/licenses/LICENSE-2.0
8*99e0aae7SDavid Rees#
9*99e0aae7SDavid Rees# Unless required by applicable law or agreed to in writing, software
10*99e0aae7SDavid Rees# distributed under the License is distributed on an "AS IS" BASIS,
11*99e0aae7SDavid Rees# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*99e0aae7SDavid Rees# See the License for the specific language governing permissions and
13*99e0aae7SDavid Rees# limitations under the License.
14*99e0aae7SDavid Rees
15*99e0aae7SDavid Rees"""Tests for util.traverse_ir."""
16*99e0aae7SDavid Rees
17*99e0aae7SDavid Reesimport collections
18*99e0aae7SDavid Rees
19*99e0aae7SDavid Reesimport unittest
20*99e0aae7SDavid Rees
21*99e0aae7SDavid Reesfrom compiler.util import ir_data
22*99e0aae7SDavid Reesfrom compiler.util import ir_data_utils
23*99e0aae7SDavid Reesfrom compiler.util import traverse_ir
24*99e0aae7SDavid Rees
25*99e0aae7SDavid Rees_EXAMPLE_IR = ir_data_utils.IrDataSerializer.from_json(ir_data.EmbossIr, """{
26*99e0aae7SDavid Rees"module": [
27*99e0aae7SDavid Rees  {
28*99e0aae7SDavid Rees    "type": [
29*99e0aae7SDavid Rees      {
30*99e0aae7SDavid Rees        "structure": {
31*99e0aae7SDavid Rees          "field": [
32*99e0aae7SDavid Rees            {
33*99e0aae7SDavid Rees              "location": {
34*99e0aae7SDavid Rees                "start": { "constant": { "value": "0" } },
35*99e0aae7SDavid Rees                "size": { "constant": { "value": "8" } }
36*99e0aae7SDavid Rees              },
37*99e0aae7SDavid Rees              "type": {
38*99e0aae7SDavid Rees                "atomic_type": {
39*99e0aae7SDavid Rees                  "reference": {
40*99e0aae7SDavid Rees                    "canonical_name": {
41*99e0aae7SDavid Rees                      "module_file": "",
42*99e0aae7SDavid Rees                      "object_path": ["UInt"]
43*99e0aae7SDavid Rees                    }
44*99e0aae7SDavid Rees                  }
45*99e0aae7SDavid Rees                }
46*99e0aae7SDavid Rees              },
47*99e0aae7SDavid Rees              "name": { "name": { "text": "field1" } }
48*99e0aae7SDavid Rees            },
49*99e0aae7SDavid Rees            {
50*99e0aae7SDavid Rees              "location": {
51*99e0aae7SDavid Rees                "start": { "constant": { "value": "8" } },
52*99e0aae7SDavid Rees                "size": { "constant": { "value": "16" } }
53*99e0aae7SDavid Rees              },
54*99e0aae7SDavid Rees              "type": {
55*99e0aae7SDavid Rees                "array_type": {
56*99e0aae7SDavid Rees                  "base_type": {
57*99e0aae7SDavid Rees                    "atomic_type": {
58*99e0aae7SDavid Rees                      "reference": {
59*99e0aae7SDavid Rees                        "canonical_name": {
60*99e0aae7SDavid Rees                          "module_file": "",
61*99e0aae7SDavid Rees                          "object_path": ["UInt"]
62*99e0aae7SDavid Rees                        }
63*99e0aae7SDavid Rees                      }
64*99e0aae7SDavid Rees                    }
65*99e0aae7SDavid Rees                  },
66*99e0aae7SDavid Rees                  "element_count": { "constant": { "value": "8" } }
67*99e0aae7SDavid Rees                }
68*99e0aae7SDavid Rees              },
69*99e0aae7SDavid Rees              "name": { "name": { "text": "field2" } }
70*99e0aae7SDavid Rees            }
71*99e0aae7SDavid Rees          ]
72*99e0aae7SDavid Rees        },
73*99e0aae7SDavid Rees        "name": { "name": { "text": "Foo" } },
74*99e0aae7SDavid Rees        "subtype": [
75*99e0aae7SDavid Rees          {
76*99e0aae7SDavid Rees            "structure": {
77*99e0aae7SDavid Rees              "field": [
78*99e0aae7SDavid Rees                {
79*99e0aae7SDavid Rees                  "location": {
80*99e0aae7SDavid Rees                    "start": { "constant": { "value": "24" } },
81*99e0aae7SDavid Rees                    "size": { "constant": { "value": "32" } }
82*99e0aae7SDavid Rees                  },
83*99e0aae7SDavid Rees                  "type": {
84*99e0aae7SDavid Rees                    "atomic_type": {
85*99e0aae7SDavid Rees                      "reference": {
86*99e0aae7SDavid Rees                        "canonical_name": {
87*99e0aae7SDavid Rees                          "module_file": "",
88*99e0aae7SDavid Rees                          "object_path": ["UInt"]
89*99e0aae7SDavid Rees                        }
90*99e0aae7SDavid Rees                      }
91*99e0aae7SDavid Rees                    }
92*99e0aae7SDavid Rees                  },
93*99e0aae7SDavid Rees                  "name": { "name": { "text": "bar_field1" } }
94*99e0aae7SDavid Rees                },
95*99e0aae7SDavid Rees                {
96*99e0aae7SDavid Rees                  "location": {
97*99e0aae7SDavid Rees                    "start": { "constant": { "value": "32" } },
98*99e0aae7SDavid Rees                    "size": { "constant": { "value": "320" } }
99*99e0aae7SDavid Rees                  },
100*99e0aae7SDavid Rees                  "type": {
101*99e0aae7SDavid Rees                    "array_type": {
102*99e0aae7SDavid Rees                      "base_type": {
103*99e0aae7SDavid Rees                        "array_type": {
104*99e0aae7SDavid Rees                          "base_type": {
105*99e0aae7SDavid Rees                            "atomic_type": {
106*99e0aae7SDavid Rees                              "reference": {
107*99e0aae7SDavid Rees                                "canonical_name": {
108*99e0aae7SDavid Rees                                  "module_file": "",
109*99e0aae7SDavid Rees                                  "object_path": ["UInt"]
110*99e0aae7SDavid Rees                                }
111*99e0aae7SDavid Rees                              }
112*99e0aae7SDavid Rees                            }
113*99e0aae7SDavid Rees                          },
114*99e0aae7SDavid Rees                          "element_count": { "constant": { "value": "16" } }
115*99e0aae7SDavid Rees                        }
116*99e0aae7SDavid Rees                      },
117*99e0aae7SDavid Rees                      "automatic": { }
118*99e0aae7SDavid Rees                    }
119*99e0aae7SDavid Rees                  },
120*99e0aae7SDavid Rees                  "name": { "name": { "text": "bar_field2" } }
121*99e0aae7SDavid Rees                }
122*99e0aae7SDavid Rees              ]
123*99e0aae7SDavid Rees            },
124*99e0aae7SDavid Rees            "name": { "name": { "text": "Bar" } }
125*99e0aae7SDavid Rees          }
126*99e0aae7SDavid Rees        ]
127*99e0aae7SDavid Rees      },
128*99e0aae7SDavid Rees      {
129*99e0aae7SDavid Rees        "enumeration": {
130*99e0aae7SDavid Rees          "value": [
131*99e0aae7SDavid Rees            {
132*99e0aae7SDavid Rees              "name": { "name": { "text": "ONE" } },
133*99e0aae7SDavid Rees              "value": { "constant": { "value": "1" } }
134*99e0aae7SDavid Rees            },
135*99e0aae7SDavid Rees            {
136*99e0aae7SDavid Rees              "name": { "name": { "text": "TWO" } },
137*99e0aae7SDavid Rees              "value": {
138*99e0aae7SDavid Rees                "function": {
139*99e0aae7SDavid Rees                  "function": "ADDITION",
140*99e0aae7SDavid Rees                  "args": [
141*99e0aae7SDavid Rees                    { "constant": { "value": "1" } },
142*99e0aae7SDavid Rees                    { "constant": { "value": "1" } }
143*99e0aae7SDavid Rees                  ],
144*99e0aae7SDavid Rees                  "function_name": { "text": "+" }
145*99e0aae7SDavid Rees                }
146*99e0aae7SDavid Rees              }
147*99e0aae7SDavid Rees            }
148*99e0aae7SDavid Rees          ]
149*99e0aae7SDavid Rees        },
150*99e0aae7SDavid Rees        "name": { "name": { "text": "Bar" } }
151*99e0aae7SDavid Rees      }
152*99e0aae7SDavid Rees    ],
153*99e0aae7SDavid Rees    "source_file_name": "t.emb"
154*99e0aae7SDavid Rees  },
155*99e0aae7SDavid Rees  {
156*99e0aae7SDavid Rees    "type": [
157*99e0aae7SDavid Rees      {
158*99e0aae7SDavid Rees        "external": { },
159*99e0aae7SDavid Rees        "name": {
160*99e0aae7SDavid Rees          "name": { "text": "UInt" },
161*99e0aae7SDavid Rees          "canonical_name": { "module_file": "", "object_path": ["UInt"] }
162*99e0aae7SDavid Rees        },
163*99e0aae7SDavid Rees        "attribute": [
164*99e0aae7SDavid Rees          {
165*99e0aae7SDavid Rees            "name": { "text": "statically_sized" },
166*99e0aae7SDavid Rees            "value": { "expression": { "boolean_constant": { "value": true } } }
167*99e0aae7SDavid Rees          },
168*99e0aae7SDavid Rees          {
169*99e0aae7SDavid Rees            "name": { "text": "size_in_bits" },
170*99e0aae7SDavid Rees            "value": { "expression": { "constant": { "value": "64" } } }
171*99e0aae7SDavid Rees          }
172*99e0aae7SDavid Rees        ]
173*99e0aae7SDavid Rees      }
174*99e0aae7SDavid Rees    ],
175*99e0aae7SDavid Rees    "source_file_name": ""
176*99e0aae7SDavid Rees  }
177*99e0aae7SDavid Rees]
178*99e0aae7SDavid Rees}""")
179*99e0aae7SDavid Rees
180*99e0aae7SDavid Rees
181*99e0aae7SDavid Reesdef _count_entries(sequence):
182*99e0aae7SDavid Rees  counts = collections.Counter()
183*99e0aae7SDavid Rees  for entry in sequence:
184*99e0aae7SDavid Rees    counts[entry] += 1
185*99e0aae7SDavid Rees  return counts
186*99e0aae7SDavid Rees
187*99e0aae7SDavid Rees
188*99e0aae7SDavid Reesdef _record_constant(constant, constant_list):
189*99e0aae7SDavid Rees  constant_list.append(int(constant.value))
190*99e0aae7SDavid Rees
191*99e0aae7SDavid Rees
192*99e0aae7SDavid Reesdef _record_field_name_and_constant(constant, constant_list, field):
193*99e0aae7SDavid Rees  constant_list.append((field.name.name.text, int(constant.value)))
194*99e0aae7SDavid Rees
195*99e0aae7SDavid Rees
196*99e0aae7SDavid Reesdef _record_file_name_and_constant(constant, constant_list, source_file_name):
197*99e0aae7SDavid Rees  constant_list.append((source_file_name, int(constant.value)))
198*99e0aae7SDavid Rees
199*99e0aae7SDavid Rees
200*99e0aae7SDavid Reesdef _record_location_parameter_and_constant(constant, constant_list,
201*99e0aae7SDavid Rees                                            location=None):
202*99e0aae7SDavid Rees  constant_list.append((location, int(constant.value)))
203*99e0aae7SDavid Rees
204*99e0aae7SDavid Rees
205*99e0aae7SDavid Reesdef _record_kind_and_constant(constant, constant_list, type_definition):
206*99e0aae7SDavid Rees  if type_definition.HasField("enumeration"):
207*99e0aae7SDavid Rees    constant_list.append(("enumeration", int(constant.value)))
208*99e0aae7SDavid Rees  elif type_definition.HasField("structure"):
209*99e0aae7SDavid Rees    constant_list.append(("structure", int(constant.value)))
210*99e0aae7SDavid Rees  elif type_definition.HasField("external"):
211*99e0aae7SDavid Rees    constant_list.append(("external", int(constant.value)))
212*99e0aae7SDavid Rees  else:
213*99e0aae7SDavid Rees    assert False, "Shouldn't be here."
214*99e0aae7SDavid Rees
215*99e0aae7SDavid Rees
216*99e0aae7SDavid Reesclass TraverseIrTest(unittest.TestCase):
217*99e0aae7SDavid Rees
218*99e0aae7SDavid Rees  def test_filter_on_type(self):
219*99e0aae7SDavid Rees    constants = []
220*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
221*99e0aae7SDavid Rees        _EXAMPLE_IR, [ir_data.NumericConstant], _record_constant,
222*99e0aae7SDavid Rees        parameters={"constant_list": constants})
223*99e0aae7SDavid Rees    self.assertEqual(
224*99e0aae7SDavid Rees        _count_entries([0, 8, 8, 8, 16, 24, 32, 16, 32, 320, 1, 1, 1, 64]),
225*99e0aae7SDavid Rees        _count_entries(constants))
226*99e0aae7SDavid Rees
227*99e0aae7SDavid Rees  def test_filter_on_type_in_type(self):
228*99e0aae7SDavid Rees    constants = []
229*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
230*99e0aae7SDavid Rees        _EXAMPLE_IR,
231*99e0aae7SDavid Rees        [ir_data.Function, ir_data.Expression, ir_data.NumericConstant],
232*99e0aae7SDavid Rees        _record_constant,
233*99e0aae7SDavid Rees        parameters={"constant_list": constants})
234*99e0aae7SDavid Rees    self.assertEqual([1, 1], constants)
235*99e0aae7SDavid Rees
236*99e0aae7SDavid Rees  def test_filter_on_type_star_type(self):
237*99e0aae7SDavid Rees    struct_constants = []
238*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
239*99e0aae7SDavid Rees        _EXAMPLE_IR, [ir_data.Structure, ir_data.NumericConstant],
240*99e0aae7SDavid Rees        _record_constant,
241*99e0aae7SDavid Rees        parameters={"constant_list": struct_constants})
242*99e0aae7SDavid Rees    self.assertEqual(_count_entries([0, 8, 8, 8, 16, 24, 32, 16, 32, 320]),
243*99e0aae7SDavid Rees                     _count_entries(struct_constants))
244*99e0aae7SDavid Rees    enum_constants = []
245*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
246*99e0aae7SDavid Rees        _EXAMPLE_IR, [ir_data.Enum, ir_data.NumericConstant], _record_constant,
247*99e0aae7SDavid Rees        parameters={"constant_list": enum_constants})
248*99e0aae7SDavid Rees    self.assertEqual(_count_entries([1, 1, 1]), _count_entries(enum_constants))
249*99e0aae7SDavid Rees
250*99e0aae7SDavid Rees  def test_filter_on_not_type(self):
251*99e0aae7SDavid Rees    notstruct_constants = []
252*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
253*99e0aae7SDavid Rees        _EXAMPLE_IR, [ir_data.NumericConstant], _record_constant,
254*99e0aae7SDavid Rees        skip_descendants_of=(ir_data.Structure,),
255*99e0aae7SDavid Rees        parameters={"constant_list": notstruct_constants})
256*99e0aae7SDavid Rees    self.assertEqual(_count_entries([1, 1, 1, 64]),
257*99e0aae7SDavid Rees                     _count_entries(notstruct_constants))
258*99e0aae7SDavid Rees
259*99e0aae7SDavid Rees  def test_field_is_populated(self):
260*99e0aae7SDavid Rees    constants = []
261*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
262*99e0aae7SDavid Rees        _EXAMPLE_IR, [ir_data.Field, ir_data.NumericConstant],
263*99e0aae7SDavid Rees        _record_field_name_and_constant,
264*99e0aae7SDavid Rees        parameters={"constant_list": constants})
265*99e0aae7SDavid Rees    self.assertEqual(_count_entries([
266*99e0aae7SDavid Rees        ("field1", 0), ("field1", 8), ("field2", 8), ("field2", 8),
267*99e0aae7SDavid Rees        ("field2", 16), ("bar_field1", 24), ("bar_field1", 32),
268*99e0aae7SDavid Rees        ("bar_field2", 16), ("bar_field2", 32), ("bar_field2", 320)
269*99e0aae7SDavid Rees    ]), _count_entries(constants))
270*99e0aae7SDavid Rees
271*99e0aae7SDavid Rees  def test_file_name_is_populated(self):
272*99e0aae7SDavid Rees    constants = []
273*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
274*99e0aae7SDavid Rees        _EXAMPLE_IR, [ir_data.NumericConstant], _record_file_name_and_constant,
275*99e0aae7SDavid Rees        parameters={"constant_list": constants})
276*99e0aae7SDavid Rees    self.assertEqual(_count_entries([
277*99e0aae7SDavid Rees        ("t.emb", 0), ("t.emb", 8), ("t.emb", 8), ("t.emb", 8), ("t.emb", 16),
278*99e0aae7SDavid Rees        ("t.emb", 24), ("t.emb", 32), ("t.emb", 16), ("t.emb", 32),
279*99e0aae7SDavid Rees        ("t.emb", 320), ("t.emb", 1), ("t.emb", 1), ("t.emb", 1), ("", 64)
280*99e0aae7SDavid Rees    ]), _count_entries(constants))
281*99e0aae7SDavid Rees
282*99e0aae7SDavid Rees  def test_type_definition_is_populated(self):
283*99e0aae7SDavid Rees    constants = []
284*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
285*99e0aae7SDavid Rees        _EXAMPLE_IR, [ir_data.NumericConstant], _record_kind_and_constant,
286*99e0aae7SDavid Rees        parameters={"constant_list": constants})
287*99e0aae7SDavid Rees    self.assertEqual(_count_entries([
288*99e0aae7SDavid Rees        ("structure", 0), ("structure", 8), ("structure", 8), ("structure", 8),
289*99e0aae7SDavid Rees        ("structure", 16), ("structure", 24), ("structure", 32),
290*99e0aae7SDavid Rees        ("structure", 16), ("structure", 32), ("structure", 320),
291*99e0aae7SDavid Rees        ("enumeration", 1), ("enumeration", 1), ("enumeration", 1),
292*99e0aae7SDavid Rees        ("external", 64)
293*99e0aae7SDavid Rees    ]), _count_entries(constants))
294*99e0aae7SDavid Rees
295*99e0aae7SDavid Rees  def test_keyword_args_dict_in_action(self):
296*99e0aae7SDavid Rees    call_counts = {"populated": 0, "not": 0}
297*99e0aae7SDavid Rees
298*99e0aae7SDavid Rees    def check_field_is_populated(node, **kwargs):
299*99e0aae7SDavid Rees      del node  # Unused.
300*99e0aae7SDavid Rees      self.assertTrue(kwargs["field"])
301*99e0aae7SDavid Rees      call_counts["populated"] += 1
302*99e0aae7SDavid Rees
303*99e0aae7SDavid Rees    def check_field_is_not_populated(node, **kwargs):
304*99e0aae7SDavid Rees      del node  # Unused.
305*99e0aae7SDavid Rees      self.assertFalse("field" in kwargs)
306*99e0aae7SDavid Rees      call_counts["not"] += 1
307*99e0aae7SDavid Rees
308*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
309*99e0aae7SDavid Rees        _EXAMPLE_IR, [ir_data.Field, ir_data.Type], check_field_is_populated)
310*99e0aae7SDavid Rees    self.assertEqual(7, call_counts["populated"])
311*99e0aae7SDavid Rees
312*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
313*99e0aae7SDavid Rees        _EXAMPLE_IR, [ir_data.Enum, ir_data.EnumValue],
314*99e0aae7SDavid Rees        check_field_is_not_populated)
315*99e0aae7SDavid Rees    self.assertEqual(2, call_counts["not"])
316*99e0aae7SDavid Rees
317*99e0aae7SDavid Rees  def test_pass_only_to_sub_nodes(self):
318*99e0aae7SDavid Rees    constants = []
319*99e0aae7SDavid Rees
320*99e0aae7SDavid Rees    def pass_location_down(field):
321*99e0aae7SDavid Rees      return {
322*99e0aae7SDavid Rees          "location": (int(field.location.start.constant.value),
323*99e0aae7SDavid Rees                       int(field.location.size.constant.value))
324*99e0aae7SDavid Rees      }
325*99e0aae7SDavid Rees
326*99e0aae7SDavid Rees    traverse_ir.fast_traverse_ir_top_down(
327*99e0aae7SDavid Rees        _EXAMPLE_IR, [ir_data.NumericConstant],
328*99e0aae7SDavid Rees        _record_location_parameter_and_constant,
329*99e0aae7SDavid Rees        incidental_actions={ir_data.Field: pass_location_down},
330*99e0aae7SDavid Rees        parameters={"constant_list": constants, "location": None})
331*99e0aae7SDavid Rees    self.assertEqual(_count_entries([
332*99e0aae7SDavid Rees        ((0, 8), 0), ((0, 8), 8), ((8, 16), 8), ((8, 16), 8), ((8, 16), 16),
333*99e0aae7SDavid Rees        ((24, 32), 24), ((24, 32), 32), ((32, 320), 16), ((32, 320), 32),
334*99e0aae7SDavid Rees        ((32, 320), 320), (None, 1), (None, 1), (None, 1), (None, 64)
335*99e0aae7SDavid Rees    ]), _count_entries(constants))
336*99e0aae7SDavid Rees
337*99e0aae7SDavid Rees
338*99e0aae7SDavid Reesif __name__ == "__main__":
339*99e0aae7SDavid Rees  unittest.main()
340