def basetype2(): # basetype = builtin-type # builtin-type = "int2" if not is_typename2(): raise asmd.ManncError( '変数の定義が型名からはじまりません。 100' ) if consume_tk( TK.INT2 ): return asmd.Type2( kind = TYP.INT2, size = 4, align = 4, is_complete = True, base = 0, array_len = 0, members = 0, return_ty = 0 ) else : raise asmd.ManncError( 'サポートしていない型です' )
def stmt_while(): if not consume( '(' ): raise asmd.ManncError('while の後は ( が必要です') node = asmd.NodeWHILE() node.kind = ND.WHILE node.expr = expr() if not consume( ')' ) : raise asmd.ManncError('while の ''('' 後は '')'' が必要です') node.block = stmt() return node
def stmt_if(): #print('#IF') if not consume( '(' ) : raise asmd.ManncError('if の後は ( が必要です') node = asmd.NodeIF() node.kind = ND.IF node.expr = expr() if not consume( ')' ) : raise asmd.ManncError('if の ''('' 後は '')'' が必要です') node.truebl = stmt() if consume_tk( TK.ELSE ) : node.elsebl = stmt() return node
def getgvar(): if asmd.tkn[0].str != 'int' and asmd.tkn[0].str != 'char': raise asmd.ManncError( '変数の定義が型名からはじまりません。 1' ) # # 型 # if consume_tk( TK.INT ) : thistype = asmd.myType() if consume( '*' ) : # intへのポインタ型 thistype.ty = TYP.PTR thistype.ptr_to = asmd.myType() thistype.ptr_to.ty = TYP.INT else: # int型 thistype.ty = TYP.INT elif consume_tk( TK.CHAR ) : if consume( '*' ) : # charへのポインタ型 thistype.ty = TYP.PTR thistype.ptr_to = asmd.myType() thistype.ptr_to.ty = TYP.CHAR else: # char型 thistype.ty = TYP.CHAR elif consume_tk( TK.STRUCT ) : pass else: raise asmd.ManncError( '変数の定義が型名からはじまりません。2 {0}'.format(asmd.tkn[0].str ) ) if asmd.tkn[0].str in asmd.glvars_t: raise asmd.ManncError( 'グローバル変数が二重で宣言されています' ) asmd.glvars_t[ asmd.tkn[0].str ] = thistype del asmd.tkn[0] if consume( '=' ) : #グローバル変数の初期化 raise asmd.ManncError( 'グローバル変数の初期化は未実装' ) pass if not consume( ';' ): raise asmd.ManncError( 'グローバル変数が ; で終了していません。{0}'.format( asmd.tkn[0].str ) ) return
def stmt_switch(): if not consume( '(' ): raise asmd.ManncError('switch の後は ( が必要です') node = asmd.NodeSWITCH() node.kind = ND.SWITCH node.expr = expr() if not consume( ')' ) : raise asmd.ManncError('switch の ''('' 後は '')'' が必要です') sw = asmd.current_switch asmd.current_switch = node node.block = stmt() asmd.current_switch = sw return node
def expect( op ): #print(" # expect {0}".format( op ) ) if asmd.tkn[0].kind != TK.RESERVED or asmd.tkn[0].str != op: raise asmd.ManncError( "'{0}'ではありません".format(op) ) #sys.exit() del asmd.tkn[0] return True
def declarator2(): # declarator = ident if not asmd.tkn[0].kind : raise asmd.ManncError( '型名の後に変数名がありません' ) name = asmd.tkn[0].str del asmd.tkn[0] return( 0, name ) # 型と名前(ident)を返す
def unary(): #print("# unary") #sizeof if consume_tk( TK.SIZEOF ): node = unary() if node.type == TYP.INT: return new_node_num( 8 ) else : return new_node_num( 8 ) if consume( '+' ): lnode = new_node_num( 0 ) node = new_node( ND.ADD, lnode, primary() ) return node if consume( '-' ): lnode = new_node_num( 0 ) node = new_node( ND.SUB, lnode, primary() ) return node if asmd.tkn[1].str == '[': #配列の場合 newnode = new_node( ND.DEREF, 0, 0 ) #newnode.type = TYP.ARRAY newnode.lhs = new_node( ND.PTR_ADD, 0, 0 ) newnode.lhs.lhs = primary() newnode.lhs.type = newnode.lhs.lhs.type del asmd.tkn[0] # [ を削除する newnode.lhs.rhs = expr() if not consume( ']' ): raise asmd.ManncError('配列が]で閉じられていません{0}'.format(asmd.tkn[0].str) ) return newnode # アドレス(ポインタ)用演算子 if consume( '*' ): print('#ND.DEREF') node = new_node( ND.DEREF, unary(), 0 ) if node.lhs.kind == ND.ADD: node.lhs.kind = ND.PTR_ADD node.type = node.lhs.type #node = new_node( ND.DEREF, 0, 0 ) #node.lhs = new_node( ND.PTR_ADD, unary(), 0 ) #node.type = node.lhs.type #node.lhs.type = node.lhs.type print("#DEREF pins" ) asmd.pins( node ) asmd.pins( node.lhs ) return node if consume( '&' ): print('#ND.ADDR') node = new_node( ND.ADDR, unary(), 0 ) return node return primary()
def tk_char(): nonlocal ch nonlocal offset nonlocal offset f.seek(offset) offset += 1 chb = f.read(1) ch = chb.decode('utf-8') if ch == '\\': # エスケープ f.seek(offset) offset += 1 chb = f.read(1) ch = chb.decode('utf-8') if ch == 'n': # 改行文字 newtkn = asmd.Token() newtkn.kind = TK.NUM newtkn.val = 10 asmd.tkn.append(newtkn) else: raise asmd.ManncError('文字の特殊文字は改行だけ') else: #f.seek( offset ) #offset += 1 #chb = f.read(1) #ch = chb.decode('utf-8') # 文字を数値に変換 newtkn = asmd.Token() newtkn.kind = TK.NUM newtkn.val = ord(ch) asmd.tkn.append(newtkn) #print("<{0}>".format(newtkn.val)) # 閉じクォート f.seek(offset) offset += 1 chb = f.read(1) ch = chb.decode('utf-8') if ch != '\'': raise asmd.ManncError('文字は一文字だけ')
def expect_number(): #print('# expect_number tknknd {0}'.format(asmd.tkn[0].kind )) if asmd.tkn[0].kind != TK.NUM: raise asmd.ManncError("数ではありません {0}".format(asmd.tkn[0].str)) #sys.exit() #print('# valval {0}'.format(asmd.tkn[0].val ) ) val = asmd.tkn[0].val del asmd.tkn[0] return val
def program() : while asmd.tkn[0].kind != TK.EOF: # グローバル変数? 関数定義? if asmd.tkn[0].str != 'int' and asmd.tkn[0].str != 'char': raise asmd.ManncError( '関数、変数の定義が型名からはじまりません。{0}'.format( asmd.tkn[0].str ) ) if asmd.tkn[1].str == '*' : if asmd.tkn[2].kind != TK.IDENT: raise asmd.ManncError( '型名の後ろが識別子ではありません' ) if asmd.tkn[3].str == '(': #ポインタを返す関数 asmd.code.append( funcdef() ) else: #グローバルのポインタ変数 getgvar2() else: if asmd.tkn[1].kind != TK.IDENT: raise asmd.ManncError( '型名の後ろが識別子ではありません' ) if asmd.tkn[2].str == '(': #ポインタ以外を返す関数 asmd.code.append( funcdef() ) else: #グローバルのポインタ以外の変数 getgvar2()
def stmt_case(): print("#CASE") if asmd.current_switch == 0: raise asmd.ManncError('stray case') val = expect_number() print("#VAL {0}".format(val)) expect( ':' ) node = asmd.NodeCASE() node.kind = ND.CASE node.block = stmt() node.val = val node.case_next = asmd.current_switch.case_next asmd.current_switch.case_next = node return node
def gen_lval(node): print("# gen_lval START") #asmd.pins( node ) print("#in {0}(): if node.kind == {1}".format( inspect.currentframe().f_back.f_code.co_name, node.kind)) if node.type == TYP.ARRAY: print("#in {0}(): if node.kind == {1}".format( inspect.currentframe().f_back.f_code.co_name, node.kind)) return if node.kind == ND.LVAR: print("#in {0}(): if node.kind == {1}".format( inspect.currentframe().f_back.f_code.co_name, node.kind)) var = node.str if var in asmd.glvars_t: # グローバル変数の左辺値 print("\tpush offset {0}".format(var)) return # グローバル変数でないときにローカル変数とみなす #if len(node.lvars2) > 0 : #return print('#here {0}'.format(var)) offset = asmd.lvars[var].offset print('#gen_lval var={0} offset={1}'.format(var, offset)) print('\tmov rax, rbp') print('\tsub rax, {0}'.format(offset)) print('#raxtest 6') print('\tpush rax') return if node.kind == ND.DEREF: print("#in {0}(): if node.kind == {1}".format( inspect.currentframe().f_back.f_code.co_name, node.kind)) gen(node.lhs) return raise asmd.ManncError('代入の左辺値が変数ではありません')
def stmt_continue(): if not consume( ';' ): raise asmd.ManncError('continue の後は ; が必要です') node = asmd.Node() node.kind = ND.CONTINUE return node
def funcdef(): global locals2 newnode = asmd.NodeFUNCDEF() if asmd.tkn[0].kind == TK.INT: newnode.type = asmd.TypeType( kind = TYP.INT, size = 4, align = 4, array_len = 0, base = 0, function = 0 ) elif asmd.tkn[0].kind == TK.CHAR: newnode.type = asmd.TypeType( kind = TYP.CHAR, size = 1, align = 1, array_len = 0, base = 0, function = 0 ) else: raise asmd.ManncError( '関数の定義が型名からはじまりません。' ) del asmd.tkn[0] if asmd.tkn[0].kind != TK.IDENT: raise asmd.ManncError( '関数の定義ではありません' ) newnode.kind = ND.FUNCDEF newnode.name = asmd.tkn[0].str del asmd.tkn[0] newnode.offset = 0 if not consume( '(' ): raise asmd.ManncError('関数パラメータの定義がおかしいです A') while True : if consume( ')' ): # 引数のない関数 break; ############## ( thistype, vname ) = type.declaration( 'PARA' ) #asmd.glvars_t[ name ] = t ############## newnode.paranum += 1 #vname = asmd.tkn[0].str # 関数引数のローカル変数用左辺値 if vname in newnode.lvars : # パラメータの変数名が重複する場合は考慮しない pass else : newnode.lvars_t[ vname ] = thistype newnode.para.append( vname ) newnode.lvars[ vname ] = asmd.MYVar() newnode.lvars[ vname ].name = vname newnode.lvars[ vname ].type = thistype newnode.lvars[ vname ].offset = asmd.align_to( newnode.offset, thistype.align ) newnode.lvars[ vname ].offset += newnode.lvars[ vname ].type.size newnode.offset += newnode.lvars_t[ vname ].size #newnode.offset = newnode.lvarst[ vname ].offset #del asmd.tkn[0] if consume( ')' ): # 引数のない関数 break; if not consume( ',' ): raise asmd.ManncError('関数パラメータの定義がおかしいです C') sys.exit() # パラメータ読み込み終わり # 関数の実行部分は BLOCK で書き換えられる? # BLOCKにしないと、genする時にうまく生成できない? asmd.offset = newnode.offset asmd.lvars_t = copy.deepcopy( newnode.lvars_t ) asmd.lvars = copy.deepcopy( newnode.lvars ) newnode.block = stmt() newnode.lvars = copy.deepcopy( asmd.lvars ) #newnode.lvars2 = copy.deepcopy( locals2 ) newnode.lvars2 = locals2 asmd.pins(newnode) if newnode.lvars2 != 0 : print('#0921') for item in newnode.lvars2.values(): print("#name={0}".format(item)) print("#ty.kind={0}".format(item.ty.kind)) print("#ty.kind ={0}".format(item.ty.kind)) print("#ty.size ={0}".format(item.ty.size)) print("#ty.align ={0}".format(item.ty.align)) print("#ty.is_complete ={0}".format(item.ty.is_complete)) print("#ty.base ={0}".format(item.ty.base)) print("#ty.array_len ={0}".format(item.ty.array_len)) print("#ty.members ={0}".format(item.ty.members)) print("#ty.return_ty ={0}".format(item.ty.return_ty)) newnode.lvars_t = copy.deepcopy( asmd.lvars_t ) newnode.offset = asmd.offset return newnode
def primary_IDENT() : #print('######TK_IDENT') if saki( '(', 1 ): newnode = asmd.NodeFUNCCALL() newnode.kind = ND.FUNC newnode.name = asmd.tkn[0].str del asmd.tkn[0] del asmd.tkn[0] # # 関数呼び出しの場合 # if consume( ')' ): return newnode while True : para = expr(); newnode.para.append( para ) if consume( ')' ) : break if not consume( ',' ): raise asmd.ManncError('関数呼び出し方が不正です' ) # sys.exit() return newnode else : # # 変数(左辺値)の場合 # if asmd.tkn[0].str in asmd.glvars_t: #グローバル変数として宣言されている場合 newnode = asmd.Node() newnode.kind = ND.LVAR newnode.str = asmd.tkn[0].str newnode.size = asmd.glvars_t[ asmd.tkn[0].str ].size newnode.type = asmd.glvars_t[ asmd.tkn[0].str ] del asmd.tkn[0] return newnode # リファクタリング用 if asmd.tkn[0].str in locals2.keys(): print('#0922test{0}'.format( asmd.tkn[0].str) ) newnode = asmd.Node() newnode.kind = ND.LVAR2 newnode.name2 = asmd.tkn[0].str #Nodeに変数名は必要ない? newnode.size = locals2[ asmd.tkn[0].str ].ty.size newnode.offset = locals2[ asmd.tkn[0].str ].offset newnode.type = locals2[ asmd.tkn[0].str ] del asmd.tkn[0] return newnode if not asmd.tkn[0].str in asmd.lvars : raise asmd.ManncError('宣言されていない変数を使用しようとしています<{0}><{1}>'.format(asmd.tkn[0].str, asmd.lvars ) ) #配列ではない場合 newnode = asmd.Node() newnode.kind = ND.LVAR newnode.str = asmd.tkn[0].str newnode.size = asmd.lvars_t[ asmd.tkn[0].str ].size newnode.offset = asmd.lvars[ asmd.tkn[0].str ] newnode.type = asmd.lvars_t[ asmd.tkn[0].str ] del asmd.tkn[0] return newnode
def stmt(): #print("# stmt") # # 関数内関数 # # declaration の最終目標↓ # declaration = basetype declarator type-suffix ("=" lvar-initializer)? ";" # | basetype ";" def stmt_declaration2(): # declaration = basetype declarator ";" ty = basetype2() ( dummy, name ) = declarator2() #if not consume( ';' ) : #raise asmd.ManncError('宣言文 の後は ; が必要です') return new_lvar2( name, ty ) def stmt_switch(): if not consume( '(' ): raise asmd.ManncError('switch の後は ( が必要です') node = asmd.NodeSWITCH() node.kind = ND.SWITCH node.expr = expr() if not consume( ')' ) : raise asmd.ManncError('switch の ''('' 後は '')'' が必要です') sw = asmd.current_switch asmd.current_switch = node node.block = stmt() asmd.current_switch = sw return node def stmt_case(): print("#CASE") if asmd.current_switch == 0: raise asmd.ManncError('stray case') val = expect_number() print("#VAL {0}".format(val)) expect( ':' ) node = asmd.NodeCASE() node.kind = ND.CASE node.block = stmt() node.val = val node.case_next = asmd.current_switch.case_next asmd.current_switch.case_next = node return node def stmt_break(): if not consume( ';' ): raise asmd.ManncError('break の後は ; が必要です') node = asmd.Node() node.kind = ND.BREAK return node def stmt_continue(): if not consume( ';' ): raise asmd.ManncError('continue の後は ; が必要です') node = asmd.Node() node.kind = ND.CONTINUE return node def stmt_while(): if not consume( '(' ): raise asmd.ManncError('while の後は ( が必要です') node = asmd.NodeWHILE() node.kind = ND.WHILE node.expr = expr() if not consume( ')' ) : raise asmd.ManncError('while の ''('' 後は '')'' が必要です') node.block = stmt() return node def stmt_if(): #print('#IF') if not consume( '(' ) : raise asmd.ManncError('if の後は ( が必要です') node = asmd.NodeIF() node.kind = ND.IF node.expr = expr() if not consume( ')' ) : raise asmd.ManncError('if の ''('' 後は '')'' が必要です') node.truebl = stmt() if consume_tk( TK.ELSE ) : node.elsebl = stmt() return node # # 関数内関数 おわり # if consume( ';' ) : node = asmd.Node() node.kind = ND.NOP return node if consume( '{' ) : #print('#print BLOCK start') node = asmd.NodeBLOCK() node.kind = ND.BLOCK if consume( '}' ): return node while True: newstmt = stmt() node.stmts.append( newstmt ) if consume( '}' ): break; return node # 変数の宣言文の場合 if asmd.tkn[0].kind in ( TK.INT, TK.CHAR ): tknkind = asmd.tkn[0].kind ( thistype, vname ) = type.declaration( 'NOTPARA' ) print('#var dec') print('#{0}'.format(vname)) thistype.myself() if thistype.base != 0 : thistype.base.myself() asmd.lvars_t[ vname ] = thistype asmd.offset = asmd.align_to( asmd.offset, thistype.align ) asmd.offset += asmd.lvars_t[ vname ].size asmd.lvars[ vname ] = asmd.MYVar() asmd.lvars[ vname ].offset = asmd.offset print('#offset aaaaa') print('#offset {0}'.format( asmd.offset ) ) print('#lvars {0}'.format( asmd.lvars[ vname ].offset ) ) #print('#lvars_t {0}'.format( asmd.lvars_t[ vname ].offset ) ) #del asmd.tkn[0] return 0 if is_typename2(): return stmt_declaration2() if consume_tk( TK.SWITCH ): return stmt_switch() if consume_tk( TK.CASE ): return stmt_case() if consume_tk( TK.CONTINUE ): return stmt_continue() if consume_tk( TK.BREAK ): return stmt_break() if consume_tk( TK.WHILE ): return stmt_while() if consume_tk( TK.IF ): return stmt_if() if consume_tk( TK.RETURN ) : node = asmd.Node() node.kind = ND.RETURN node.lhs = expr() else : node = expr() if consume( ';' ): return node else: raise asmd.ManncError(';ではないトークンです{0}'.format(asmd.tkn[0].str))
def gen(node): global seq global if_num global while_num global break_num global switch_num global lvars2 while_num_tmp = 0 print("# gen START") #asmd.pins( node ) if node == 0: return if node.kind == ND.NOP: print("#NOP") return if node.kind == ND.STRING: print("\tpush offset .L.strings.{0}".format(node.val)) print('\tpop rax') print('\tmov rax, [rax]') print('\tpush rax') return # NodeKind が変数の場合 リファクタリング用 if node.kind == ND.LVAR2: print("#0922 x ") gen_lval2(node) # 配列の場合のみアドレスが指す先をメモリから読み込む処理を # 飛ばす条件分岐を追加する必要がある todo load(node.size) return # NodeKind が変数の場合 if node.kind == ND.LVAR: gen_lval(node) # 配列の場合のみアドレスが指す先をメモリから読み込む処理を if node.type.kind != TYP.ARRAY: load(node.size) return # NodeKind が代入の場合 if node.kind == ND.ASSIGN: gen_lval(node.lhs) gen(node.rhs) store(node.lhs.size) return # NodeKind が代入の場合 リファクタリング if node.kind == ND.ASSIGN2: print("#0922 ASSIGN2") print("#lhs") asmd.pins(node.lhs) print("#rhs") asmd.pins(node.rhs) gen_lval2(node.lhs) gen(node.rhs) store(node.lhs.size) return # Nodekind が '*' の場合 if node.kind == ND.DEREF: print('#test001') #asmd.pins( node ) #asmd.pins( node.lhs ) #asmd.pins( node.lhs.lhs ) #asmd.pins( node.lhs.rhs ) gen(node.lhs) #load( node.lhs.type.size ) #asmd.pins( node ) if node.lhs.type != TYP.ARRAY: print("#in {0}:{1}".format( os.path.basename( inspect.currentframe().f_back.f_code.co_filename), inspect.currentframe().f_back.f_lineno)) print('#test002') #load( 4 ) load(node.lhs.type.base.size) return # Nodekind が '&' の場合 if node.kind == ND.ADDR: print("# gen ND.ADDRF") gen_lval(node.lhs) return if node.kind == ND.FUNCDEF: lvars2 = node.lvars2 node.myself() # 関数の名前=ラベル print("{0}:".format(node.name)) # プロローグ print('#プロローグ') print('\tpush rbp') print('\tmov rbp, rsp') print('\tsub rsp, {0}'.format(node.offset)) # レジスタの中身をパラメータにコピーする para_i = 0 #para_reg64 = [ "rdi", "rsi", "rdx", "rcx" ]; #para_reg32 = [ "edi", "esi", "edx", "ecx" ]; #para_reg8 = [ "dil", "sil", "dl", "cl" ]; while para_i < node.paranum: print("#para{0}".format(para_i)) print("#para{0}".format(node.para[para_i])) print("\tmov rax, rbp\n") #print("#DDDDEBUG {0}".format( node.para[para_i] ) ) print("\tsub rax, {0}\n".format( node.lvars[node.para[para_i]].offset)) if node.lvars_t[node.para[para_i]].size == 8: print("\tmov [rax], {0}\n".format(para_reg64[para_i])) elif node.lvars_t[node.para[para_i]].size == 4: print("\tmov [rax], {0}\n".format(para_reg32[para_i])) elif node.lvars_t[node.para[para_i]].size == 1: print("\tmov [rax], {0}\n".format(para_reg8[para_i])) else: raise asmd.ManncError('代入のサイズがおかしい') para_i += 1 asmd.lvars = node.lvars.copy() asmd.lvars_t = node.lvars_t.copy() # 関数本体(ブロック)を出力する gen(node.block) #エピローグ #最後の式の結果がRAXに残っているのでそれが返り値になる print('#エピローグ') print('\tpop rax') print('\tmov rsp, rbp') print('\tpop rbp') return # NodeKind が FUNC の場合 if node.kind == ND.FUNC: print('#FUNC') pcnt = 0 for para in node.para: gen(para) if pcnt == 0: print("\tpop rdi\n") elif pcnt == 1: print("\tpop rsi\n") elif pcnt == 2: print("\tpop rdx\n") elif pcnt == 3: print("\tpop rcx\n") else: raise asmd.ManncError('関数の引数は4つまで') #sys.exit() pcnt += 1 print(" mov rax, rsp") print(" and rax, 15") print(" jnz .L.call.{0}".format(seq)) print(" mov rax, 0") #print(" call %s\n", node->funcname); print('\tcall {0}'.format(node.name)) print(" jmp .L.end.{0}".format(seq)) print(".L.call.{0}:".format(seq)) print(" sub rsp, 8") print(" mov rax, 0") #print(" call %s\n", node->funcname); print('\tcall {0}'.format(node.name)) print(" add rsp, 8") print(".L.end.{0}:".format(seq)) seq += 1 #print('\tcall {0}'.format(node.name) ) print('#raxtest 2') print('\tpush rax') return # NodeKindが、数値の場合 # スタックにその値をプッシュする if node.kind == ND.NUM: print("#in {0}(): if node.kind == {1}".format( inspect.currentframe().f_back.f_code.co_name, node.kind)) print('\tpush {0}'.format(node.val)) return if node.kind == ND.BLOCK: for stmt in node.stmts: gen(stmt) print('#raxtest 3') #print('\tpush rax') return if node.kind == ND.SWITCH: switch_num_tmp = switch_num switch_num += 1 break_num_tmp = break_num break_num = switch_num_tmp node.case_label = switch_num_tmp gen(node.expr) print("\tpop rax") n = node.case_next while n != 0: n.case_label = switch_num switch_num += 1 n.case_end_label = switch_num_tmp #print('\tpop rax') print('\tcmp rax, {0}'.format(n.val)) print('\tje .L.case.{0}'.format(n.case_label)) n = n.case_next if node.default_case: i = switch_num switch_num += 1 node.default_case.case_end_label = switch_num_tmp node.default_case.case_label = i print("\tjmp .L.case.{0}".format(i)) print("\tjmp .L.break.{0}".format(switch_num_tmp)) gen(node.block) print(".L.break.{0}:\n".format(switch_num_tmp)) break_num = break_num_tmp return #switch 終わり if node.kind == ND.CASE: print(".L.case.{0}:".format(node.case_label)) gen(node.block) return if node.kind == ND.WHILE: while_num_tmp = while_num break_num_tmp = break_num break_num = while_num while_num += 1 print('#whilegen') print(".Lbegin{0}:".format(while_num_tmp)) gen(node.expr) print('\tpop rax') print('\tcmp rax, 0') print("je .Lend{0}".format(while_num_tmp)) gen(node.block) print("jmp .Lbegin{0}".format(while_num_tmp)) print(".Lend{0}:".format(while_num_tmp)) ###print(".L.break.{0}:".format(break_num_tmp)) print(".L.break.{0}:".format(break_num)) print('#whilegen end') break_num = break_num_tmp return if node.kind == ND.CONTINUE: print("#continue") print("jmp .Lbegin{0}".format(while_num_tmp)) return if node.kind == ND.BREAK: print("#break") print("jmp .L.break.{0}".format(break_num)) return if node.kind == ND.IF: print('#ifgen') gen(node.expr) print('\tpop rax') print('\tcmp rax, 0') if_num_tmp1 = if_num if_num += 1 if_num_tmp2 = if_num if_num += 1 print('\tje .ELSE' + str(if_num_tmp1).zfill(3)) print('#ture gen') if not node.truebl == 0: gen(node.truebl) print('\tjmp .IFEND' + str(if_num_tmp2).zfill(3)) print('\t.ELSE' + str(if_num_tmp1).zfill(3) + ':') if not node.elsebl == 0: gen(node.elsebl) print('.IFEND' + str(if_num_tmp2).zfill(3) + ':') return # NodeKind が reurn の場合 if node.kind == ND.RETURN: print('#NDRETUN') gen(node.lhs) print('#NDRETURN エピローグ') print('\tpop rax') print('\tmov rsp, rbp') print('\tpop rbp') print('\tret') return # NodeKindが、二項演算子(四則演算、等号、不等号)の場合 # lhs がスタックトップ # rhs がその次 # pop してその二つを rdi と rax に入れる # 演算の結果は rax に入れてプッシュする print("#in {0}:{1}".format( os.path.basename(inspect.currentframe().f_back.f_code.co_filename), inspect.currentframe().f_back.f_lineno)) gen(node.lhs) gen(node.rhs) print('\tpop rdi') print('\tpop rax') if node.kind == ND.PTR_ADD: print("#in {0}:{1}".format( os.path.basename(inspect.currentframe().f_back.f_code.co_filename), inspect.currentframe().f_back.f_lineno)) print("# gen ND.PTR_ADDR") #ポインタの計算をする場合 #size = node.lhs.type.size #node.lhs.type.size = 4 print('\timul rdi, {0}'.format(node.lhs.type.base.size)) print('\tadd rax, rdi') elif node.kind == ND.ADD: print('\tadd rax, rdi') elif node.kind == ND.SUB: print('\tsub rax, rdi') elif node.kind == ND.MUL: print('\timul rax, rdi') elif node.kind == ND.DIV: print('\tcqo') print('\tidiv rax, rdi') elif node.kind == ND.EQU: print('\tcmp rax, rdi') print('sete al') print('movzb rax, al') elif node.kind == ND.NEQ: print('\tcmp rax, rdi') print('\tsetne al') print('\tmovzb rax, al') elif node.kind == ND.LT: print('\tcmp rax, rdi') print('\tsetl al') print('\tmovzb rax, al') elif node.kind == ND.LTE: print('\tcmp rax, rdi') print('\tsetle al') print('\tmovzb rax, al') print('#raxtesta5') print('\tpush rax') return
def stmt_break(): if not consume( ';' ): raise asmd.ManncError('break の後は ; が必要です') node = asmd.Node() node.kind = ND.BREAK return node
def tk_string(): nonlocal ch nonlocal offset #offset += 1 f.seek(offset) chb = f.read(1) ch = chb.decode('utf-8') tmpstr = '' # 文字リテラル読み込みループ開始 while True: if ch == '"': break #print('string={0}'.format(ch)) #文字列中のバックスペースはエスケープシーケンス if ch == '\\': offset += 1 f.seek(offset) chb = f.read(1) ch = chb.decode('utf-8') if ch == 'n': # 改行文字 ch = "\n" if ch.isdecimal(): # '\nnn は8進数のコード cnt8 = 1 num8 = 0 while ch.isdecimal() and cnt8 <= 3: if 0 <= int(ch) <= 7: num8 *= 8 num8 += int(ch) offset += 1 f.seek(offset) chb = f.read(1) ch = chb.decode('utf-8') cnt8 += 1 else: raise asmd.ManncError( 'リテラルのバックスラッシュの後ろの数値は0から7までです') tmpstr += chr(num8) continue tmpstr += ch offset += 1 f.seek(offset) chb = f.read(1) ch = chb.decode('utf-8') # 文字リテラル読み込みループ終了 #string_i 文字列の通し番号 label = ".L.LITERAL.{0}".format(asmd.string_i) asmd.strings[label] = tmpstr asmd.string_i += 1 newtkn = asmd.Token() newtkn.kind = TK.STRING newtkn.str = label # 変数名=ラベル asmd.tkn.append(newtkn) # ダブルクォーテーションを読み捨てる offset += 1 chb = f.read(1)
def declaration(mode): # # 変数の定義は int または char から始まる # if asmd.tkn[0].str == 'int': base = asmd.TypeType(TYP.INT, 4, 4, 0, 0, 0) elif asmd.tkn[0].str == 'char': base = asmd.TypeType(TYP.CHAR, 1, 1, 0, 0, 0) else: raise asmd.ManncError('変数の定義が型名からはじまりません。 t') del asmd.tkn[0] ptype = 0 if asmd.tkn[0].str == '*': # # ポインタ * が 1 個以上続く # ptype = asmd.TypeType(TYP.PTR, 8, 8, 0, 0, 0) lastp = ptype del asmd.tkn[0] while asmd.tkn[0].str == '*': print('loop') lastp.base = asmd.TypeType(TYP.PTR, 8, 8, 0, 0, 0) lastp = last.base del asmd.tkn[0] # * の後は IDENT のはず if asmd.tkn[0].kind != TK.IDENT: raise asmd.ManncError('変数の名前がありません {0}'.format(asmd.tkn[0].str)) # 変数の名前 vname = asmd.tkn[0].str del asmd.tkn[0] arrayt = 0 if asmd.tkn[0].str == '[': print('#declare arrayt') # # 配列の場合 # del asmd.tkn[0] if asmd.tkn[0].kind != TK.NUM: raise asmd.ManncError('配列の添え字が数値ではありません') # そえじの処理 arraylen = asmd.tkn[0].val arrayt = asmd.TypeType(TYP.ARRAY, base.size * arraylen, base.align, arraylen, 0, 0) lastp = arrayt.base arraysize = asmd.tkn[0].val del asmd.tkn[0] if asmd.tkn[0].str != ']': raise asmd.ManncError('配列の添え字の後ろに ] がありません') del asmd.tkn[0] # この関数が、通常の宣言部か、関数のパラメータで呼ばれたかで # 処理(区切り文字)を変える if mode == 'NOTPARA': if asmd.tkn[0].str != ';': raise asmd.ManncError('宣言の終わりが ; ではありません{0}'.format( asmd.tkn[0].str)) del asmd.tkn[0] if mode == 'PARA': if asmd.tkn[0].str != ',' and asmd.tkn[0].str != ')': raise asmd.ManncError('パラメータのおわり、区切りが , ) ではありません'.format( asmd.tkn[0].str)) #del しない if arrayt == 0 and ptype == 0: return (base, vname) if arrayt != 0: if ptype == 0: arrayt.base = base print('#declare arrayt') arrayt.myself() base.myself() return (arrayt, vname) else: arrayt.base = ptype lastp = base return (arrayt, vname) lastp.base = base return (ptype, vname)