xref: /aosp_15_r20/external/gemmlowp/meta/generators/cc_emitter.py (revision 5f39d1b313f0528e11bae88b3029b54b9e1033e7)
1*5f39d1b3SJooyung Han# Copyright 2016 The Gemmlowp Authors. All rights reserved.
2*5f39d1b3SJooyung Han#
3*5f39d1b3SJooyung Han# Licensed under the Apache License, Version 2.0 (the "License");
4*5f39d1b3SJooyung Han# you may not use this file except in compliance with the License.
5*5f39d1b3SJooyung Han# You may obtain a copy of the License at
6*5f39d1b3SJooyung Han#
7*5f39d1b3SJooyung Han#    http://www.apache.org/licenses/LICENSE-2.0
8*5f39d1b3SJooyung Han#
9*5f39d1b3SJooyung Han# Unless required by applicable law or agreed to in writing, software
10*5f39d1b3SJooyung Han# distributed under the License is distributed on an "AS IS" BASIS,
11*5f39d1b3SJooyung Han# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*5f39d1b3SJooyung Han# See the License for the specific language governing permissions and
13*5f39d1b3SJooyung Han# limitations under the License.
14*5f39d1b3SJooyung Han"""CC code emitter.
15*5f39d1b3SJooyung Han
16*5f39d1b3SJooyung HanUsed by generators to programatically prepare C++ code. Contains some simple
17*5f39d1b3SJooyung Hantools that allow generating nicely indented code and do basic correctness
18*5f39d1b3SJooyung Hanchecking.
19*5f39d1b3SJooyung Han"""
20*5f39d1b3SJooyung Han
21*5f39d1b3SJooyung Han
22*5f39d1b3SJooyung Hanclass Error(Exception):
23*5f39d1b3SJooyung Han  """Module level error."""
24*5f39d1b3SJooyung Han
25*5f39d1b3SJooyung Han
26*5f39d1b3SJooyung Hanclass NamespaceError(Error):
27*5f39d1b3SJooyung Han  """Invalid namespace operation."""
28*5f39d1b3SJooyung Han
29*5f39d1b3SJooyung Han
30*5f39d1b3SJooyung Hanclass HeaderError(Error):
31*5f39d1b3SJooyung Han  """Invalid cc header structure."""
32*5f39d1b3SJooyung Han
33*5f39d1b3SJooyung Han
34*5f39d1b3SJooyung Hanclass ClassError(Error):
35*5f39d1b3SJooyung Han  """Invalid class syntax."""
36*5f39d1b3SJooyung Han
37*5f39d1b3SJooyung Han
38*5f39d1b3SJooyung Hanclass CCEmitter(object):
39*5f39d1b3SJooyung Han  """Emits c++ code."""
40*5f39d1b3SJooyung Han
41*5f39d1b3SJooyung Han  def __init__(self, debug=False):
42*5f39d1b3SJooyung Han    self.indent = ''
43*5f39d1b3SJooyung Han    self.debug = debug
44*5f39d1b3SJooyung Han    self.namespaces = []
45*5f39d1b3SJooyung Han    self.classes = []
46*5f39d1b3SJooyung Han    self.header_name = None
47*5f39d1b3SJooyung Han
48*5f39d1b3SJooyung Han  def PushIndent(self):
49*5f39d1b3SJooyung Han    self.indent += '  '
50*5f39d1b3SJooyung Han
51*5f39d1b3SJooyung Han  def PopIndent(self):
52*5f39d1b3SJooyung Han    self.indent = self.indent[:-2]
53*5f39d1b3SJooyung Han
54*5f39d1b3SJooyung Han  def EmitIndented(self, what):
55*5f39d1b3SJooyung Han    print(self.indent + what)
56*5f39d1b3SJooyung Han
57*5f39d1b3SJooyung Han  def EmitNewline(self):
58*5f39d1b3SJooyung Han    print('')
59*5f39d1b3SJooyung Han
60*5f39d1b3SJooyung Han  def EmitPreprocessor1(self, op, param):
61*5f39d1b3SJooyung Han    print('#%s %s' % (op, param))
62*5f39d1b3SJooyung Han
63*5f39d1b3SJooyung Han  def EmitPreprocessor(self, op):
64*5f39d1b3SJooyung Han    print('#%s' % op)
65*5f39d1b3SJooyung Han
66*5f39d1b3SJooyung Han  def EmitInclude(self, include):
67*5f39d1b3SJooyung Han    self.EmitPreprocessor1('include', include)
68*5f39d1b3SJooyung Han
69*5f39d1b3SJooyung Han  def EmitAssign(self, variable, value):
70*5f39d1b3SJooyung Han    self.EmitBinaryOp(variable, '=', value)
71*5f39d1b3SJooyung Han
72*5f39d1b3SJooyung Han  def EmitAssignIncrement(self, variable, value):
73*5f39d1b3SJooyung Han    self.EmitBinaryOp(variable, '+=', value)
74*5f39d1b3SJooyung Han
75*5f39d1b3SJooyung Han  def EmitBinaryOp(self, operand_1, op, operand_2):
76*5f39d1b3SJooyung Han    self.EmitCode('%s %s %s' % (operand_1, op, operand_2))
77*5f39d1b3SJooyung Han
78*5f39d1b3SJooyung Han  def EmitCall(self, function, params=None):
79*5f39d1b3SJooyung Han    if not params:
80*5f39d1b3SJooyung Han      params = []
81*5f39d1b3SJooyung Han    self.EmitCode('%s(%s)' % (function, ', '.join(map(str, params))))
82*5f39d1b3SJooyung Han
83*5f39d1b3SJooyung Han  def EmitCode(self, code):
84*5f39d1b3SJooyung Han    self.EmitIndented('%s;' % code)
85*5f39d1b3SJooyung Han
86*5f39d1b3SJooyung Han  def EmitCodeNoSemicolon(self, code):
87*5f39d1b3SJooyung Han    self.EmitIndented('%s' % code)
88*5f39d1b3SJooyung Han
89*5f39d1b3SJooyung Han  def EmitDeclare(self, decl_type, name, value):
90*5f39d1b3SJooyung Han    self.EmitAssign('%s %s' % (decl_type, name), value)
91*5f39d1b3SJooyung Han
92*5f39d1b3SJooyung Han  def EmitAssert(self, assert_expression):
93*5f39d1b3SJooyung Han    if self.debug:
94*5f39d1b3SJooyung Han      self.EmitCall1('assert', assert_expression)
95*5f39d1b3SJooyung Han
96*5f39d1b3SJooyung Han  def EmitHeaderBegin(self, header_name, includes=None):
97*5f39d1b3SJooyung Han    if includes is None:
98*5f39d1b3SJooyung Han      includes = []
99*5f39d1b3SJooyung Han    if self.header_name:
100*5f39d1b3SJooyung Han      raise HeaderError('Header already defined.')
101*5f39d1b3SJooyung Han    self.EmitPreprocessor1('ifndef', (header_name + '_H_').upper())
102*5f39d1b3SJooyung Han    self.EmitPreprocessor1('define', (header_name + '_H_').upper())
103*5f39d1b3SJooyung Han    self.EmitNewline()
104*5f39d1b3SJooyung Han    if includes:
105*5f39d1b3SJooyung Han      for include in includes:
106*5f39d1b3SJooyung Han        self.EmitInclude(include)
107*5f39d1b3SJooyung Han      self.EmitNewline()
108*5f39d1b3SJooyung Han    self.header_name = header_name
109*5f39d1b3SJooyung Han
110*5f39d1b3SJooyung Han  def EmitHeaderEnd(self):
111*5f39d1b3SJooyung Han    if not self.header_name:
112*5f39d1b3SJooyung Han      raise HeaderError('Header undefined.')
113*5f39d1b3SJooyung Han    self.EmitPreprocessor1('endif',
114*5f39d1b3SJooyung Han                           ' // %s' % (self.header_name + '_H_').upper())
115*5f39d1b3SJooyung Han    self.header_name = None
116*5f39d1b3SJooyung Han
117*5f39d1b3SJooyung Han  def EmitMemberFunctionBegin(self, class_name, class_template_params,
118*5f39d1b3SJooyung Han                              class_specializations, function_name,
119*5f39d1b3SJooyung Han                              function_params, return_type):
120*5f39d1b3SJooyung Han    """Emit member function of a template/specialized class."""
121*5f39d1b3SJooyung Han    if class_template_params or class_specializations:
122*5f39d1b3SJooyung Han      self.EmitIndented('template<%s>' % ', '.join(class_template_params))
123*5f39d1b3SJooyung Han
124*5f39d1b3SJooyung Han    if class_specializations:
125*5f39d1b3SJooyung Han      class_name += '<%s>' % ', '.join(map(str, class_specializations))
126*5f39d1b3SJooyung Han
127*5f39d1b3SJooyung Han    self.EmitIndented('%s %s::%s(%s) {' % (
128*5f39d1b3SJooyung Han        return_type, class_name, function_name,
129*5f39d1b3SJooyung Han        ', '.join(['%s %s' % (t, n) for (t, n) in function_params])))
130*5f39d1b3SJooyung Han    self.PushIndent()
131*5f39d1b3SJooyung Han
132*5f39d1b3SJooyung Han  def EmitFunctionBegin(self, function_name, params, return_type):
133*5f39d1b3SJooyung Han    self.EmitIndented('%s %s(%s) {' %
134*5f39d1b3SJooyung Han                      (return_type, function_name,
135*5f39d1b3SJooyung Han                       ', '.join(['%s %s' % (t, n) for (t, n) in params])))
136*5f39d1b3SJooyung Han    self.PushIndent()
137*5f39d1b3SJooyung Han
138*5f39d1b3SJooyung Han  def EmitFunctionEnd(self):
139*5f39d1b3SJooyung Han    self.PopIndent()
140*5f39d1b3SJooyung Han    self.EmitIndented('}')
141*5f39d1b3SJooyung Han    self.EmitNewline()
142*5f39d1b3SJooyung Han
143*5f39d1b3SJooyung Han  def EmitClassBegin(self, class_name, template_params, specializations,
144*5f39d1b3SJooyung Han                     base_classes):
145*5f39d1b3SJooyung Han    """Emit class block header."""
146*5f39d1b3SJooyung Han    self.classes.append(class_name)
147*5f39d1b3SJooyung Han    if template_params or specializations:
148*5f39d1b3SJooyung Han      self.EmitIndented('template<%s>' % ', '.join(template_params))
149*5f39d1b3SJooyung Han
150*5f39d1b3SJooyung Han    class_name_extended = class_name
151*5f39d1b3SJooyung Han    if specializations:
152*5f39d1b3SJooyung Han      class_name_extended += '<%s>' % ', '.join(map(str, specializations))
153*5f39d1b3SJooyung Han    if base_classes:
154*5f39d1b3SJooyung Han      class_name_extended += ' : ' + ', '.join(base_classes)
155*5f39d1b3SJooyung Han    self.EmitIndented('class %s {' % class_name_extended)
156*5f39d1b3SJooyung Han    self.PushIndent()
157*5f39d1b3SJooyung Han
158*5f39d1b3SJooyung Han  def EmitClassEnd(self):
159*5f39d1b3SJooyung Han    if not self.classes:
160*5f39d1b3SJooyung Han      raise ClassError('No class on stack.')
161*5f39d1b3SJooyung Han    self.classes.pop()
162*5f39d1b3SJooyung Han    self.PopIndent()
163*5f39d1b3SJooyung Han    self.EmitIndented('};')
164*5f39d1b3SJooyung Han    self.EmitNewline()
165*5f39d1b3SJooyung Han
166*5f39d1b3SJooyung Han  def EmitAccessModifier(self, modifier):
167*5f39d1b3SJooyung Han    if not self.classes:
168*5f39d1b3SJooyung Han      raise ClassError('No class on stack.')
169*5f39d1b3SJooyung Han    self.PopIndent()
170*5f39d1b3SJooyung Han    self.EmitIndented(' %s:' % modifier)
171*5f39d1b3SJooyung Han    self.PushIndent()
172*5f39d1b3SJooyung Han
173*5f39d1b3SJooyung Han  def EmitNamespaceBegin(self, namespace):
174*5f39d1b3SJooyung Han    self.EmitCodeNoSemicolon('namespace %s {' % namespace)
175*5f39d1b3SJooyung Han    self.namespaces.append(namespace)
176*5f39d1b3SJooyung Han
177*5f39d1b3SJooyung Han  def EmitNamespaceEnd(self):
178*5f39d1b3SJooyung Han    if not self.namespaces:
179*5f39d1b3SJooyung Han      raise NamespaceError('No namespace on stack.')
180*5f39d1b3SJooyung Han    self.EmitCodeNoSemicolon('}  // namespace %s' % self.namespaces.pop())
181*5f39d1b3SJooyung Han
182*5f39d1b3SJooyung Han  def EmitComment(self, comment):
183*5f39d1b3SJooyung Han    self.EmitIndented('// ' + comment)
184*5f39d1b3SJooyung Han
185*5f39d1b3SJooyung Han  def EmitOpenBracket(self, pre_bracket=None):
186*5f39d1b3SJooyung Han    if pre_bracket:
187*5f39d1b3SJooyung Han      self.EmitIndented('%s {' % pre_bracket)
188*5f39d1b3SJooyung Han    else:
189*5f39d1b3SJooyung Han      self.EmitIndented('{')
190*5f39d1b3SJooyung Han    self.PushIndent()
191*5f39d1b3SJooyung Han
192*5f39d1b3SJooyung Han  def EmitCloseBracket(self):
193*5f39d1b3SJooyung Han    self.PopIndent()
194*5f39d1b3SJooyung Han    self.EmitIndented('}')
195*5f39d1b3SJooyung Han
196*5f39d1b3SJooyung Han  def EmitSwitch(self, switch):
197*5f39d1b3SJooyung Han    self.EmitOpenBracket('switch (%s)' % switch)
198*5f39d1b3SJooyung Han
199*5f39d1b3SJooyung Han  def EmitSwitchEnd(self):
200*5f39d1b3SJooyung Han    self.EmitCloseBracket()
201*5f39d1b3SJooyung Han
202*5f39d1b3SJooyung Han  def EmitCase(self, value):
203*5f39d1b3SJooyung Han    self.EmitCodeNoSemicolon('case %s:' % value)
204*5f39d1b3SJooyung Han
205*5f39d1b3SJooyung Han  def EmitBreak(self):
206*5f39d1b3SJooyung Han    self.EmitCode('break')
207*5f39d1b3SJooyung Han
208*5f39d1b3SJooyung Han  def EmitIf(self, condition):
209*5f39d1b3SJooyung Han    self.EmitOpenBracket('if (%s)' % condition)
210*5f39d1b3SJooyung Han
211*5f39d1b3SJooyung Han  def EmitElse(self):
212*5f39d1b3SJooyung Han    self.PopIndent()
213*5f39d1b3SJooyung Han    self.EmitCodeNoSemicolon('} else {')
214*5f39d1b3SJooyung Han    self.PushIndent()
215*5f39d1b3SJooyung Han
216*5f39d1b3SJooyung Han  def EmitEndif(self):
217*5f39d1b3SJooyung Han    self.EmitCloseBracket()
218*5f39d1b3SJooyung Han
219*5f39d1b3SJooyung Han  def Scope(self, scope, value):
220*5f39d1b3SJooyung Han    return '%s::%s' % (scope, value)
221