def gencode(self, env, opt): size = env.calcTypeSize(self.typ, self.init) init = [0] * size if isinstance(self.init, AST): init[0] = self.init.eval() elif isinstance(self.init, list): for i, elem in enumerate(self.init): init[i] = self.init[i].eval() env.addStatic(m.Symbol(self.symbolname, self.typ, init)) return env
def gencode(self, env, opt): env.calcTypeSize(self.typ, self.init) var = env.addLocal(m.Symbol(self.symbolname, self.typ)) if self.init is None: return m.Insts() elif isinstance(self.init, list): codes = [] for i, elem in enumerate(self.init): codes.extend(elem.gencode(env, newopt(opt, 1)).bytecodes) codes.append(var.genAddrCode()) codes.append(m.Inst(opc.PUSH, i)) codes.append(m.Inst(opc.ADDI, self.nullarg)) codes.append(m.Inst(opc.STOREP, self.nullarg)) return m.Insts(m.Type(), codes) else: codes = self.init.gencode(env, newopt(opt, 1)).bytecodes codes.append(m.Inst(opc.STOREL, var.id)) return m.Insts(m.Type(), codes)
def projectAST(ast, s=0): if (ast is None): return None elif isinstance(ast, c_ast.ArrayDecl): return projectAST(ast.type, s).setLength(projectAST(ast.dim, s)) #MEMO dim_quals unused elif isinstance(ast, c_ast.ArrayRef): # [name*, subscript*] return node.Indirect( a2t(ast), node.Add(a2t(ast), projectAST(ast.name, s), projectAST(ast.subscript, s))) elif isinstance(ast, c_ast.Assignment): # [op, lvalue*, rvalue*] if ast.op == '=': return node.Assign(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s)) elif ast.op == '+=': return node.Assign( a2t(ast), projectAST(ast.lvalue, s), node.Add(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s))) elif ast.op == '-=': return node.Assign( a2t(ast), projectAST(ast.lvalue, s), node.Sub(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s))) elif ast.op == '*=': return node.Assign( a2t(ast), projectAST(ast.lvalue, s), node.Mul(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s))) elif ast.op == '/=': return node.Assign( a2t(ast), projectAST(ast.lvalue, s), node.Div(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s))) elif ast.op == '%=': return node.Assign( a2t(ast), projectAST(ast.lvalue, s), node.Mod(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s))) elif ast.op == '<<=': return node.Assign( a2t(ast), projectAST(ast.lvalue, s), node.LShift(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s))) elif ast.op == '>>=': return node.Assign( a2t(ast), projectAST(ast.lvalue, s), node.RShift(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s))) elif ast.op == '&=': return node.Assign( a2t(ast), projectAST(ast.lvalue, s), node.And(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s))) elif ast.op == '|=': return node.Assign( a2t(ast), projectAST(ast.lvalue, s), node.Or(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s))) elif ast.op == '^=': return node.Assign( a2t(ast), projectAST(ast.lvalue, s), node.Xor(a2t(ast), projectAST(ast.lvalue, s), projectAST(ast.rvalue, s))) else: g.r.addReport( m.Report('fatal', a2t(ast), f"unsupported assignment op '{ast.op}'")) return elif isinstance(ast, c_ast.BinaryOp): # [op, left* right*] if ast.op == '+': return node.Add(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '-': return node.Sub(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '*': return node.Mul(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '/': return node.Div(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '%': return node.Mod(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '<<': return node.LShift(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '>>': return node.RShift(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '&': return node.And(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '|': return node.Or(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '^': return node.Xor(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '<': return node.Lt(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '<=': return node.Lte(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '>': return node.Gt(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '>=': return node.Gte(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '==': return node.Eq(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '!=': return node.Neq(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '&&': return node.And(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) elif ast.op == '||': return node.Or(a2t(ast), projectAST(ast.left, s), projectAST(ast.right, s)) else: g.r.addReport( m.Report('fatal', a2t(ast), f"unsupported binary op '{ast.op}'")) return elif isinstance(ast, c_ast.Break): # [] return node.Break(a2t(ast)) elif isinstance(ast, c_ast.Case): # [expr*, stmts**] return [ projectAST(ast.expr, s), [projectAST(e, s + 1) for e in ast.stmts] ] elif isinstance(ast, c_ast.Cast): # [to_type*, expr*] return node.Cast(a2t(ast), projectAST(ast.to_type, s), projectAST(ast.expr, s)) elif isinstance(ast, c_ast.Compound): # [block_items**] if ast.block_items is None: return node.Block(a2t(ast), []) else: return node.Block(a2t(ast), [projectAST(e, s + 1) for e in ast.block_items]) elif isinstance(ast, c_ast.CompoundLiteral): #TODO [type*, init*] pass elif isinstance(ast, c_ast.Constant): # [type, value] if (ast.type == 'int'): return node.NumberI(a2t(ast), ast.value) elif (ast.type == 'float'): return node.NumberF(a2t(ast), ast.value) elif (ast.type == 'char'): ast.value = escapeString(ast.value) return node.NumberI( a2t(ast), int.from_bytes(ast.value[1].encode('utf-32be'), byteorder='big')) elif (ast.type == 'string'): ast.value = escapeString(ast.value) return node.String(a2t(ast), ast.value[1:-1]) g.r.addReport( m.Report( 'fatal', a2t(ast), f"unsupported constant type '{ast.type}' for value '{ast.value}'" )) elif isinstance(ast, c_ast.Continue): # [] return node.Continue(a2t(ast)) elif isinstance( ast, c_ast.Decl ): # [name, quals, storage, funcspec, type*, init*, bitsize*] if type(ast.type) in (c_ast.TypeDecl, c_ast.PtrDecl, c_ast.ArrayDecl): init = projectAST(ast.init, s) if isinstance(init, node.String): # 初期化がstirngだった場合、リストに展開 string = init.eval() li = list( map( lambda a: node.NumberI( a2t(ast), int.from_bytes(a.encode('utf-32be'), byteorder='big')), string)) li.append(node.NumberI(a2t(ast), 0)) init = li if (s == 0): return node.GlobalVar(a2t(ast), ast.name, projectAST(ast.type, s), init) else: return node.LocalVar(a2t(ast), ast.name, projectAST(ast.type, s), init) elif isinstance(ast.type, c_ast.FuncDecl): # 関数定義 decl = projectAST(ast.type, s) return node.Func(a2t(ast), decl['type'].name, decl['type'], decl['args'], None) else: return projectAST(ast.type, s) elif isinstance(ast, c_ast.DeclList): #TODO [decls**] pass elif isinstance(ast, c_ast.Default): # [stmts**] return ['default', [projectAST(e, s + 1) for e in ast.stmts]] elif isinstance(ast, c_ast.DoWhile): # [cond*, stmt*] return node.DoWhile(a2t(ast), projectAST(ast.stmt, s), projectAST(ast.cond, s)) elif isinstance(ast, c_ast.EllipsisParam): #TODO [] pass elif isinstance(ast, c_ast.EmptyStatement): #TODO [] pass elif isinstance(ast, c_ast.Enum): # [name, values*] if ast.values is None: # is type define return m.Type(ast.name).setHint('enum') else: # is enum define return node.Enum(a2t(ast), ast.name, projectAST(ast.values, s)) elif isinstance(ast, c_ast.Enumerator): # [name, value*] if ast.value is None: return (ast.name, None) else: if isinstance(ast.value, c_ast.Constant): return (ast.name, int(ast.value.value)) elif isinstance(ast.value, c_ast.UnaryOp): return (ast.name, -int(ast.value.expr.value)) else: g.r.addReport( m.Report('fatal', a2t(ast), f"enum must be \'int\'")) elif isinstance(ast, c_ast.EnumeratorList): # [enumerators**] itr = 0 typ = m.Type('enum') for elem in ast.enumerators: tmp = projectAST(elem, s) if tmp[1] is None: typ.addMember((tmp[0], itr)) itr += 1 else: typ.addMember(tmp) itr = tmp[1] + 1 return typ elif isinstance(ast, c_ast.ExprList): #[exprs**] return [projectAST(e, s) for e in ast.exprs] elif isinstance(ast, c_ast.FileAST): return node.Program(a2t(ast), [projectAST(e, s) for e in ast.ext]) elif isinstance(ast, c_ast.For): # [init*, cond*, next*, stmt*] return node.For(a2t(ast), projectAST(ast.init, s), projectAST(ast.cond, s), projectAST(ast.next, s), projectAST(ast.stmt, s)) elif isinstance(ast, c_ast.FuncCall): # [name*, args*] return node.Funccall(a2t(ast), ast.name.name, projectAST(ast.args, s)) elif isinstance(ast, c_ast.FuncDecl): # [args*, type*] return { "args": projectAST(ast.args, s) if ast.args is not None else [], "type": projectAST(ast.type, s) } elif isinstance(ast, c_ast.FuncDef): # [args*, type*] return projectAST(ast.decl, s).setBody(projectAST(ast.body, s)) elif isinstance(ast, c_ast.Goto): # [name] return node.Goto(a2t(ast), ast.name) elif isinstance(ast, c_ast.ID): # [name] return node.Symbol(a2t(ast), ast.name) elif isinstance(ast, c_ast.IdentifierType): if len(ast.names) == 1: return m.Type(ast.names[0]) g.r.addReport( m.Report('fatal', a2t(ast), f"program error while processing IdentifierType")) elif isinstance(ast, c_ast.If): # [cond*, iftrue*, iffalse*] if ast.iffalse is None: return node.If(a2t(ast), projectAST(ast.cond, s), projectAST(ast.iftrue, s)) else: return node.Ifelse(a2t(ast), projectAST(ast.cond, s), projectAST(ast.iftrue, s), projectAST(ast.iffalse, s)) elif isinstance(ast, c_ast.InitList): # [exprs**] return [projectAST(e, s) for e in ast.exprs] #XXX elif isinstance(ast, c_ast.Label): # [name, stmt*] return node.Label(a2t(ast), ast.name, projectAST(ast.stmt)) elif isinstance(ast, c_ast.NamedInitializer): #TODO [name**, expr*] pass elif isinstance(ast, c_ast.ParamList): # [params**] tmp = [] for elem in ast.params: typ = projectAST(elem.type, s) tmp.append(m.Symbol(typ.name, typ)) return tmp elif isinstance(ast, c_ast.PtrDecl): return projectAST(ast.type, s).addQuals(ast.quals).addRefcount(1) elif isinstance(ast, c_ast.Raw): # [type*, opc, arg, exprs**] return node.Raw(a2t(ast), projectAST(ast.type, s), ast.opc[1:-1], int(ast.arg.value), [projectAST(e, s) for e in ast.exprs]) elif isinstance(ast, c_ast.Return): # [expr*] return node.Return(a2t(ast), projectAST(ast.expr, s)) elif isinstance(ast, c_ast.Struct): # [name, decls**] if ast.decls is None: return m.Type(ast.name).setHint('struct') else: typ = m.Type('struct') for elem in ast.decls: typ.addMember((elem.name, projectAST(elem.type))) return node.Struct(a2t(ast), ast.name, typ) elif isinstance(ast, c_ast.StructRef): # [name*, type, filed*] type unused if ast.type == '.': return node.Indirect( a2t(ast), node.FieldAccess( a2t(ast), node.Address(a2t(ast), projectAST(ast.name, s)), ast.field.name)) elif ast.type == '->': return node.Indirect( a2t(ast), node.FieldAccess(a2t(ast), projectAST(ast.name, s), ast.field.name)) else: g.r.addReport( m.Report('fatal', a2t(ast), f"unsupported field access type '{ast.type}'")) elif isinstance(ast, c_ast.Switch): # [cond*, stmt*] return node.Switch(a2t(ast), projectAST( ast.cond, s), [projectAST(e, s + 1) for e in ast.stmt.block_items]) elif isinstance(ast, c_ast.TernaryOp): # [cond*, ifture*, iffalse*] return node.Ternary(a2t(ast), projectAST(ast.cond, s), projectAST(ast.iftrue, s), projectAST(ast.iffalse, s)) elif isinstance(ast, c_ast.TypeDecl): typ = projectAST(ast.type, s) if isinstance(typ, m.Type): return typ.addQuals(ast.quals).setName(ast.declname) elif type(typ) in (node.Struct, node.Enum): return typ.typ else: return typ elif isinstance(ast, c_ast.Typedef): # [name, quals, storage, type*] typ = projectAST(ast.type, s) if isinstance(typ, node.Struct) or isinstance(typ, node.Enum): return node.Typedef(a2t(ast), ast.name, typ.typ.addQuals(ast.quals)) else: return node.Typedef(a2t(ast), ast.name, typ.addQuals(ast.quals)) elif isinstance(ast, c_ast.Typename): # [name, quals, type*] return projectAST(ast.type, s).addQuals(ast.quals) elif isinstance(ast, c_ast.UnaryOp): # [op, expr*] if ast.op == '!': return node.Inv(a2t(ast), projectAST(ast.expr, s)) elif ast.op == '+': return projectAST(ast.expr, s) elif ast.op == '-': return node.Minus(a2t(ast), projectAST(ast.expr, s)) elif ast.op == '++': return node.Pre_inc(a2t(ast), projectAST(ast.expr, s)) elif ast.op == '--': return node.Pre_dec(a2t(ast), projectAST(ast.expr, s)) elif ast.op == 'p++': return node.Post_inc(a2t(ast), projectAST(ast.expr, s)) elif ast.op == 'p--': return node.Post_dec(a2t(ast), projectAST(ast.expr, s)) elif ast.op == '*': return node.Indirect(a2t(ast), projectAST(ast.expr, s)) elif ast.op == '&': return node.Address(a2t(ast), projectAST(ast.expr, s)) elif ast.op == 'sizeof': return node.Sizeof(a2t(ast), projectAST(ast.expr, s)) else: g.r.addReport( m.Report('fatal', a2t(ast), f"unsupported unary op '{ast.op}'")) return elif isinstance(ast, c_ast.Union): #TODO [name, decls**] pass elif isinstance(ast, c_ast.While): # [cond*, stmt*] return node.While(a2t(ast), projectAST(ast.cond, s), projectAST(ast.stmt, s)) elif isinstance(ast, c_ast.Pragma): #TODO [string] pass else: g.r.addReport( m.Report('fatal', a2t(ast), f"{type(ast)} is not listed!")) return g.r.addReport( m.Report('fatal', a2t(ast), f"{type(ast)} is not yet implemented!"))
def gencode(self, env, opt): for elem in self.body: dumps = elem.gencode(env, newopt(opt, 0)) env.addStatic(m.Symbol("__MAGIC_RETADDR__", m.Type(), 0)) env.addStatic(m.Symbol("__MAGIC_RETFP__", m.Type(), 0)) return env