oppc/code: support subscript exprs
[openpower-isa.git] / src / openpower / oppc / pc_code.py
1 import collections
2
3 import openpower.oppc.pc_ast as pc_ast
4 import openpower.oppc.pc_util as pc_util
5
6
7 class CodeVisitor(pc_util.Visitor):
8 def __init__(self, name, root):
9 self.__root = root
10 self.__header = object()
11 self.__footer = object()
12 self.__code = collections.defaultdict(lambda: pc_util.Code())
13 self.__decls = collections.defaultdict(list)
14 self.__regfetch = collections.defaultdict(list)
15 self.__regstore = collections.defaultdict(list)
16
17 super().__init__(root=root)
18
19 self.__code[self.__header].emit("void")
20 self.__code[self.__header].emit(f"oppc_{name}(void) {{")
21 with self.__code[self.__header]:
22 for decl in self.__decls:
23 self.__code[self.__header].emit(f"uint64_t {decl};")
24 self.__code[self.__footer].emit(f"}}")
25
26 def __iter__(self):
27 yield from self.__code[self.__header]
28 yield from self.__code[self.__root]
29 yield from self.__code[self.__footer]
30
31 def __getitem__(self, node):
32 return self.__code[node]
33
34 @pc_util.Hook(pc_ast.Scope)
35 def Scope(self, node):
36 yield node
37 with self[node]:
38 for subnode in node:
39 for (level, stmt) in self[subnode]:
40 self[node].emit(stmt=stmt, level=level)
41
42 @pc_util.Hook(pc_ast.AssignExpr, pc_ast.AssignIEAExpr)
43 def AssignExpr(self, node):
44 yield node
45 if isinstance(node.lvalue, (pc_ast.GPR, pc_ast.FPR)):
46 self.__regstore[str(node.lvalue)].append(node.lvalue)
47 if isinstance(node.rvalue, (pc_ast.GPR, pc_ast.FPR)):
48 self.__regfetch[str(node.rvalue)].append(node.rvalue)
49
50 stmt = " ".join([
51 str(self[node.lvalue]),
52 "=",
53 str(self[node.rvalue]),
54 ])
55 self[node].emit(stmt=f"{stmt};")
56
57 @pc_util.Hook(pc_ast.BinaryExpr)
58 def BinaryExpr(self, node):
59 yield node
60 if isinstance(node.left, (pc_ast.GPR, pc_ast.FPR)):
61 self.__regfetch[str(node.left)].append(node.left)
62 if isinstance(node.right, (pc_ast.GPR, pc_ast.FPR)):
63 self.__regfetch[str(node.right)].append(node.left)
64 special = (
65 pc_ast.MulS,
66 pc_ast.MulU,
67 pc_ast.DivT,
68 pc_ast.Sqrt,
69 pc_ast.BitConcat
70 )
71 if isinstance(node.op, special):
72 raise NotImplementedError(node)
73 stmt = " ".join([
74 str(self[node.left]),
75 str(self[node.op]),
76 str(self[node.right]),
77 ])
78 self[node].emit(stmt=f"({stmt})")
79
80 @pc_util.Hook(pc_ast.UnaryExpr)
81 def UnaryExpr(self, node):
82 yield node
83 stmt = "".join([
84 str(self[node.op]),
85 f"({str(self[node.value])})",
86 ])
87 self[node].emit(stmt=stmt)
88
89 @pc_util.Hook(
90 pc_ast.Not, pc_ast.Add, pc_ast.Sub,
91 pc_ast.Mul, pc_ast.Div, pc_ast.Mod,
92 pc_ast.Lt, pc_ast.Le,
93 pc_ast.Eq, pc_ast.NotEq,
94 pc_ast.Ge, pc_ast.Gt,
95 pc_ast.LShift, pc_ast.RShift,
96 pc_ast.BitAnd, pc_ast.BitOr, pc_ast.BitXor,
97 )
98 def Op(self, node):
99 yield node
100 op = {
101 pc_ast.Not: "~",
102 pc_ast.Add: "+",
103 pc_ast.Sub: "-",
104 pc_ast.Mul: "*",
105 pc_ast.Div: "/",
106 pc_ast.Mod: "%",
107 pc_ast.Lt: "<",
108 pc_ast.Le: "<=",
109 pc_ast.Eq: "==",
110 pc_ast.NotEq: "!=",
111 pc_ast.Ge: ">=",
112 pc_ast.Gt: ">",
113 pc_ast.LShift: "<<",
114 pc_ast.RShift: "<<",
115 pc_ast.BitAnd: "&",
116 pc_ast.BitOr: "|",
117 pc_ast.BitXor: "^",
118 }[node.__class__]
119 self[node].emit(stmt=op)
120
121 @pc_util.Hook(pc_ast.BinLiteral, pc_ast.DecLiteral, pc_ast.HexLiteral)
122 def Integer(self, node):
123 yield node
124 if isinstance(node, pc_ast.BinLiteral):
125 base = 2
126 elif isinstance(node, pc_ast.DecLiteral):
127 base = 10
128 elif isinstance(node, pc_ast.HexLiteral):
129 base = 16
130 else:
131 raise ValueError(node)
132 self[node].emit(stmt=f"UINT64_C({hex(int(node, base))})")
133
134 @pc_util.Hook(pc_ast.GPR)
135 def GPR(self, node):
136 yield node
137 self[node].emit(stmt=f"ctx->gpr[OPPC_GPR_{str(node)}]")
138
139 @pc_util.Hook(pc_ast.FPR)
140 def FPR(self, node):
141 yield node
142 self[node].emit(stmt=f"ctx->fpr[OPPC_FPR_{str(node)}]")
143
144 @pc_util.Hook(pc_ast.RepeatExpr)
145 def RepeatExpr(self, node):
146 yield node
147 subject = str(self[node.subject])
148 times = str(self[node.times])
149 self[node].emit(f"oppc_repeat({subject}, {times})")
150
151 @pc_util.Hook(pc_ast.XLEN)
152 def XLEN(self, node):
153 yield node
154 self[node].emit(f"ctx->XLEN")
155
156 @pc_util.Hook(pc_ast.SubscriptExpr)
157 def SubscriptExpr(self, node):
158 yield node
159 index = str(self[node.index])
160 subject = str(self[node.subject])
161 self[node].emit(f"oppc_subscript({subject}, {index})")
162
163 @pc_util.Hook(pc_ast.RangeSubscriptExpr)
164 def RangeSubscriptExpr(self, node):
165 yield node
166 start = str(self[node.start])
167 end = str(self[node.end])
168 subject = str(self[node.subject])
169 self[node].emit(f"oppc_range_subscript({subject}, {start}, {end})")
170
171 @pc_util.Hook(pc_ast.Call.Name)
172 def CallName(self, node):
173 yield node
174
175 @pc_util.Hook(pc_ast.Call.Arguments)
176 def CallArguments(self, node):
177 yield node
178 for subnode in node:
179 if isinstance(subnode, (pc_ast.GPR, pc_ast.FPR)):
180 self.__regfetch[str(subnode)].append(subnode)
181
182 @pc_util.Hook(pc_ast.Symbol)
183 def Symbol(self, node):
184 yield node
185 self.__decls[str(node)].append(node)
186 self[node].emit(stmt=str(node))
187
188 @pc_util.Hook(pc_ast.Node)
189 def Node(self, node):
190 raise NotImplementedError(type(node))
191
192
193 def code(name, root):
194 yield from CodeVisitor(name=name, root=root)