4 import openpower
.oppc
.pc_ast
as pc_ast
5 import openpower
.oppc
.pc_util
as pc_util
6 import openpower
.oppc
.pc_pseudocode
as pc_pseudocode
9 class Transient(pc_ast
.Node
):
10 def __init__(self
, value
="UINT64_C(0)", bits
="(uint8_t)OPPC_XLEN"):
14 return super().__init
__()
17 return f
"oppc_transient(&(struct oppc_value){{}}, {self.__value}, {self.__bits})"
20 class CCall(pc_ast
.Dataclass
):
26 class CodeVisitor(pc_util
.Visitor
):
27 def __init__(self
, name
, root
):
29 self
.__header
= object()
30 self
.__footer
= object()
31 self
.__code
= collections
.defaultdict(lambda: pc_util
.Code())
32 self
.__decls
= collections
.defaultdict(list)
33 self
.__regfetch
= collections
.defaultdict(list)
34 self
.__regstore
= collections
.defaultdict(list)
35 self
.__pseudocode
= pc_pseudocode
.PseudocodeVisitor(root
=root
)
37 super().__init
__(root
=root
)
39 self
.__code
[self
.__header
].emit(stmt
="void")
40 self
.__code
[self
.__header
].emit(stmt
=f
"oppc_{name}(void) {{")
41 with self
.__code
[self
.__header
]:
42 for decl
in self
.__decls
:
43 self
.__code
[self
.__header
].emit(stmt
=f
"struct oppc_value {decl};")
44 self
.__code
[self
.__footer
].emit(stmt
=f
"}}")
47 yield from self
.__code
[self
.__header
]
48 yield from self
.__code
[self
.__root
]
49 yield from self
.__code
[self
.__footer
]
51 def __getitem__(self
, node
):
52 return self
.__code
[node
]
54 def transient(self
, node
,
56 bits
="(uint8_t)OPPC_XLEN"):
57 transient
= Transient(value
=value
, bits
=bits
)
58 self
.traverse(root
=transient
)
61 def ccall(self
, node
, name
, code
, stmt
=False):
65 if not isinstance(level
, int):
66 raise ValueError(level
)
67 if not isinstance(stmt
, str):
68 raise ValueError(stmt
)
71 return tuple(map(validate
, item
))
73 code
= tuple(map(validate
, code
))
74 ccall
= CCall(name
=name
, code
=code
, stmt
=stmt
)
75 self
.traverse(root
=ccall
)
78 def ternary(self
, node
):
80 self
[node
].emit(stmt
="(")
82 for (level
, stmt
) in self
[node
.test
]:
83 self
[node
].emit(stmt
=stmt
, level
=level
)
84 self
[node
].emit(stmt
="?")
85 for (level
, stmt
) in self
[node
.body
]:
86 self
[node
].emit(stmt
=stmt
, level
=level
)
87 self
[node
].emit(stmt
=":")
88 for (level
, stmt
) in self
[node
.orelse
]:
89 self
[node
].emit(stmt
=stmt
, level
=level
)
90 self
[node
].emit(stmt
=")")
92 @contextlib.contextmanager
93 def pseudocode(self
, node
):
94 for (level
, stmt
) in self
.__pseudocode
[node
]:
95 self
[node
].emit(stmt
=f
"/* {stmt} */", level
=level
)
98 @pc_util.Hook(pc_ast
.Scope
)
99 def Scope(self
, node
):
103 for (level
, stmt
) in self
[subnode
]:
104 self
[node
].emit(stmt
=stmt
, level
=level
)
106 @pc_util.Hook(pc_ast
.AssignExpr
, pc_ast
.AssignIEAExpr
)
107 def AssignExpr(self
, node
):
109 if isinstance(node
.lvalue
, (pc_ast
.GPR
, pc_ast
.FPR
)):
110 self
.__regstore
[str(node
.lvalue
)].append(node
.lvalue
)
111 if isinstance(node
.rvalue
, (pc_ast
.GPR
, pc_ast
.FPR
)):
112 self
.__regfetch
[str(node
.rvalue
)].append(node
.rvalue
)
114 if isinstance(node
.rvalue
, pc_ast
.IfExpr
):
115 self
.ternary(node
=node
.rvalue
)
117 if isinstance(node
.lvalue
, pc_ast
.SubscriptExpr
):
118 ccall
= self
.ccall(name
="oppc_subscript_assign", node
=node
, stmt
=True, code
=[
119 self
[node
.lvalue
.subject
],
120 self
[node
.lvalue
.index
],
123 elif isinstance(node
.lvalue
, pc_ast
.RangeSubscriptExpr
):
124 ccall
= self
.ccall(name
="oppc_range_subscript_assign", node
=node
, stmt
=True, code
=[
125 self
[node
.lvalue
.subject
],
126 self
[node
.lvalue
.start
],
127 self
[node
.lvalue
.end
],
131 ccall
= self
.ccall(name
="oppc_assign", stmt
=True, node
=node
, code
=[
135 with self
.pseudocode(node
=node
):
136 for (level
, stmt
) in self
[ccall
]:
137 self
[node
].emit(stmt
=stmt
, level
=level
)
139 @pc_util.Hook(pc_ast
.BinaryExpr
)
140 def BinaryExpr(self
, node
):
142 if isinstance(node
.left
, (pc_ast
.GPR
, pc_ast
.FPR
)):
143 self
.__regfetch
[str(node
.left
)].append(node
.left
)
144 if isinstance(node
.right
, (pc_ast
.GPR
, pc_ast
.FPR
)):
145 self
.__regfetch
[str(node
.right
)].append(node
.left
)
148 pc_ast
.Lt
, pc_ast
.Le
,
149 pc_ast
.Eq
, pc_ast
.NotEq
,
150 pc_ast
.Ge
, pc_ast
.Gt
,
152 if isinstance(node
.left
, pc_ast
.IfExpr
):
153 self
.ternary(node
=node
.left
)
154 if isinstance(node
.right
, pc_ast
.IfExpr
):
155 self
.ternary(node
=node
.right
)
157 if isinstance(node
.op
, comparison
):
158 ccall
= self
.ccall(name
=str(self
[node
.op
]), node
=node
, code
=[
163 transient
= self
.transient(node
=node
)
164 ccall
= self
.ccall(name
=str(self
[node
.op
]), node
=node
, code
=[
169 with self
.pseudocode(node
=node
):
170 for (level
, stmt
) in self
[ccall
]:
171 self
[node
].emit(stmt
=stmt
, level
=level
)
173 @pc_util.Hook(pc_ast
.UnaryExpr
)
174 def UnaryExpr(self
, node
):
176 if isinstance(node
.value
, pc_ast
.IfExpr
):
177 self
.ternary(node
=node
.value
)
178 ccall
= self
.ccall(name
=str(self
[node
.op
]), node
=node
, code
=[
181 with self
.pseudocode(node
=node
):
182 for (level
, stmt
) in self
[ccall
]:
183 self
[node
].emit(stmt
=stmt
, level
=level
)
186 pc_ast
.Not
, pc_ast
.Add
, pc_ast
.Sub
,
187 pc_ast
.Mul
, pc_ast
.Div
, pc_ast
.Mod
,
188 pc_ast
.Lt
, pc_ast
.Le
,
189 pc_ast
.Eq
, pc_ast
.NotEq
,
190 pc_ast
.Ge
, pc_ast
.Gt
,
191 pc_ast
.LShift
, pc_ast
.RShift
,
192 pc_ast
.BitAnd
, pc_ast
.BitOr
, pc_ast
.BitXor
,
197 pc_ast
.Not
: "oppc_not",
198 pc_ast
.Add
: "oppc_add",
199 pc_ast
.Sub
: "oppc_sub",
200 pc_ast
.Mul
: "oppc_mul",
201 pc_ast
.Div
: "oppc_div",
202 pc_ast
.Mod
: "oppc_mod",
203 pc_ast
.Lt
: "oppc_lt",
204 pc_ast
.Le
: "oppc_le",
205 pc_ast
.Eq
: "oppc_eq",
206 pc_ast
.NotEq
: "oppc_noteq",
207 pc_ast
.Ge
: "oppc_ge",
208 pc_ast
.Gt
: "oppc_gt",
209 pc_ast
.LShift
: "oppc_lshift",
210 pc_ast
.RShift
: "oppc_rshift",
211 pc_ast
.BitAnd
: "oppc_and",
212 pc_ast
.BitOr
: "oppc_or",
213 pc_ast
.BitXor
: "oppc_xor",
215 self
[node
].emit(stmt
=op
)
217 @pc_util.Hook(pc_ast
.BinLiteral
, pc_ast
.DecLiteral
, pc_ast
.HexLiteral
)
218 def Integer(self
, node
):
222 if isinstance(node
, pc_ast
.BinLiteral
):
223 bits
= f
"UINT8_C({str(len(value[2:]))})"
224 value
= int(value
, 2)
225 elif isinstance(node
, pc_ast
.HexLiteral
):
226 bits
= f
"UINT8_C({str(len(value[2:]) * 4)})"
227 value
= int(value
, 16)
229 bits
= "(uint8_t)OPPC_XLEN"
232 if (value
> ((2**64) - 1)):
233 raise NotImplementedError()
234 value
= f
"UINT64_C({fmt(value)})"
235 transient
= self
.transient(node
=node
, value
=value
, bits
=bits
)
236 with self
.pseudocode(node
=node
):
237 for (level
, stmt
) in self
[transient
]:
238 self
[node
].emit(stmt
=stmt
, level
=level
)
240 @pc_util.Hook(Transient
)
241 def Transient(self
, node
):
243 self
[node
].emit(stmt
=str(node
))
246 def CCall(self
, node
):
248 end
= (";" if node
.stmt
else "")
249 if len(node
.code
) == 0:
250 self
[node
].emit(stmt
=f
"{str(node.name)}(){end}")
252 self
[node
].emit(stmt
=f
"{str(node.name)}(")
254 (*head
, tail
) = node
.code
256 for (level
, stmt
) in code
:
257 self
[node
].emit(stmt
=stmt
, level
=level
)
258 (level
, stmt
) = self
[node
][-1]
260 stmt
.startswith("/*") or
261 stmt
.endswith((",", "(", "{", "*/"))):
263 self
[node
][-1] = (level
, stmt
)
264 for (level
, stmt
) in tail
:
265 self
[node
].emit(stmt
=stmt
, level
=level
)
266 self
[node
].emit(stmt
=f
"){end}")
268 @pc_util.Hook(pc_ast
.GPR
)
271 with self
.pseudocode(node
=node
):
272 self
[node
].emit(stmt
=f
"&OPPC_GPR[OPPC_GPR_{str(node)}]")
274 @pc_util.Hook(pc_ast
.FPR
)
277 with self
.pseudocode(node
=node
):
278 self
[node
].emit(stmt
=f
"&OPPC_FPR[OPPC_FPR_{str(node)}]")
280 @pc_util.Hook(pc_ast
.RepeatExpr
)
281 def RepeatExpr(self
, node
):
283 transient
= self
.transient(node
=node
)
284 ccall
= self
.ccall(name
="oppc_repeat", node
=node
, code
=[
289 for (level
, stmt
) in self
[ccall
]:
290 self
[node
].emit(stmt
=stmt
, level
=level
)
292 @pc_util.Hook(pc_ast
.XLEN
)
293 def XLEN(self
, node
):
295 (value
, bits
) = ("OPPC_XLEN", "(uint8_t)OPPC_XLEN")
296 transient
= self
.transient(node
=node
, value
=value
, bits
=bits
)
297 with self
.pseudocode(node
=node
):
298 for (level
, stmt
) in self
[transient
]:
299 self
[node
].emit(stmt
=stmt
, level
=level
)
301 @pc_util.Hook(pc_ast
.SubscriptExpr
)
302 def SubscriptExpr(self
, node
):
304 ccall
= self
.ccall(name
="oppc_subscript", node
=node
, code
=[
308 for (level
, stmt
) in self
[ccall
]:
309 self
[node
].emit(stmt
=stmt
, level
=level
)
311 @pc_util.Hook(pc_ast
.RangeSubscriptExpr
)
312 def RangeSubscriptExpr(self
, node
):
314 ccall
= self
.ccall(name
="oppc_subscript", node
=node
, code
=[
319 for (level
, stmt
) in self
[ccall
]:
320 self
[node
].emit(stmt
=stmt
, level
=level
)
322 @pc_util.Hook(pc_ast
.ForExpr
)
323 def ForExpr(self
, node
):
326 enter
= pc_ast
.AssignExpr(
327 lvalue
=node
.subject
.clone(),
328 rvalue
=node
.start
.clone(),
330 match
= pc_ast
.BinaryExpr(
331 left
=node
.subject
.clone(),
333 right
=node
.end
.clone(),
335 leave
= pc_ast
.AssignExpr(
336 lvalue
=node
.subject
.clone(),
337 rvalue
=pc_ast
.BinaryExpr(
338 left
=node
.subject
.clone(),
340 right
=node
.end
.clone(),
343 with self
.pseudocode(node
=node
):
344 (level
, stmt
) = self
[node
][0]
346 self
[node
].emit(stmt
=stmt
, level
=level
)
347 self
[node
].emit(stmt
="for (")
350 for subnode
in (enter
, match
, leave
):
351 self
.__pseudocode
.traverse(root
=subnode
)
352 self
.traverse(root
=subnode
)
353 for (level
, stmt
) in self
[subnode
]:
354 self
[node
].emit(stmt
=stmt
, level
=level
)
355 (level
, stmt
) = self
[node
][-1]
358 elif subnode
is leave
:
360 self
[node
][-1] = (level
, stmt
)
361 (level
, stmt
) = self
[node
][0]
362 self
[node
].emit(stmt
=stmt
, level
=level
)
363 self
[node
].emit(stmt
=") {")
364 for (level
, stmt
) in self
[node
.body
]:
365 self
[node
].emit(stmt
=stmt
, level
=level
)
366 self
[node
].emit(stmt
="}")
368 @pc_util.Hook(pc_ast
.WhileExpr
)
369 def WhileExpr(self
, node
):
371 self
[node
].emit(stmt
="while (")
374 for (level
, stmt
) in self
[node
.test
]:
375 self
[node
].emit(stmt
=stmt
, level
=level
)
376 self
[node
].emit(") {")
377 for (level
, stmt
) in self
[node
.body
]:
378 self
[node
].emit(stmt
=stmt
, level
=level
)
380 self
[node
].emit(stmt
="} else {")
381 for (level
, stmt
) in self
[node
.orelse
]:
382 self
[node
].emit(stmt
=stmt
, level
=level
)
383 self
[node
].emit(stmt
="}")
385 @pc_util.Hook(pc_ast
.IfExpr
)
386 def IfExpr(self
, node
):
388 self
[node
].emit(stmt
="if (")
390 for (level
, stmt
) in self
[node
.test
]:
391 self
[node
].emit(stmt
=stmt
, level
=level
)
392 self
[node
].emit(stmt
=") {")
393 for (level
, stmt
) in self
[node
.body
]:
394 self
[node
].emit(stmt
=stmt
, level
=level
)
396 self
[node
].emit(stmt
="} else {")
397 for (level
, stmt
) in self
[node
.orelse
]:
398 self
[node
].emit(stmt
=stmt
, level
=level
)
399 self
[node
].emit(stmt
="}")
401 @pc_util.Hook(pc_ast
.Call
.Name
)
402 def CallName(self
, node
):
404 self
[node
].emit(stmt
=str(node
))
406 @pc_util.Hook(pc_ast
.Call
.Arguments
)
407 def CallArguments(self
, node
):
410 if isinstance(subnode
, (pc_ast
.GPR
, pc_ast
.FPR
)):
411 self
.__regfetch
[str(subnode
)].append(subnode
)
413 @pc_util.Hook(pc_ast
.Call
)
414 def Call(self
, node
):
416 code
= tuple(map(lambda arg
: self
[arg
], node
.args
))
417 ccall
= self
.ccall(name
=str(node
.name
), node
=node
, code
=code
)
418 for (level
, stmt
) in self
[ccall
]:
419 self
[node
].emit(stmt
=stmt
, level
=level
)
421 @pc_util.Hook(pc_ast
.Symbol
)
422 def Symbol(self
, node
):
424 self
.__decls
[str(node
)].append(node
)
425 with self
.pseudocode(node
=node
):
426 self
[node
].emit(stmt
=f
"&{str(node)}")
428 @pc_util.Hook(pc_ast
.Node
)
429 def Node(self
, node
):
430 raise NotImplementedError(type(node
))
433 def code(name
, root
):
434 yield from CodeVisitor(name
=name
, root
=root
)