def p_link_id(p): ''' link_id : | LBRACKET NUMBER INTERVAL NUMBER RBRACKET ''' ident = latest_id_name(p) scope = symtab.scope() size = 0 ptr_offset = 0 if len(p) == 6: i_from = p[2] i_to = p[4] size = i_to - i_from + 1 ptr_offset = i_from assert scope == Scope.GLOBAL or scope == Scope.LOCAL if scope == Scope.GLOBAL: val = Factor(scope, name=ident, size=size, ptr_offset=ptr_offset) if scope == Scope.LOCAL: val = Factor(scope, name=ident, val=codegen.register(), size=size, ptr_offset=ptr_offset) codegen.push_factor(val)
def p_term(p): ''' term : factor | term MULT factor | term DIV factor ''' if len(p) < 3: return arg2 = codegen.pop_factor() arg1 = codegen.pop_factor() retval = Factor(Scope.LOCAL, val=codegen.register()) operator = p[2] assert operator == '*' or operator == 'div' # 定数伝搬 if optimization['constant_folding'] and \ arg1.scope == Scope.CONSTANT and arg2.scope == Scope.CONSTANT: val = arg1.val * arg2.val \ if operator == '*' else arg1.val / arg2.val codegen.push_factor(Factor(Scope.CONSTANT, val=val)) return LLVMCodeClass = llvmcodes.LLVMCodeMul \ if p[2] == '*' else llvmcodes.LLVMCodeDiv codegen.push_code(LLVMCodeClass(arg1, arg2, retval)) codegen.push_factor(retval)
def _parse_variable(v): symbol = symtab.lookup(v) scope = symbol.scope if scope == Scope.GLOBAL: return Factor(scope, name=v, size=symbol.size, ptr_offset=symbol.ptr_offset) if scope == Scope.LOCAL: return Factor(scope, val=symbol.register, size=symbol.size, ptr_offset=symbol.ptr_offset) raise ValueError()
def p_while_condition(p): ''' while_condition : ''' label_index = codegen.pop_label_stack(keep=True) cond = codegen.pop_factor() l1 = Factor(Scope.LOCAL, val=f"while.body.{label_index}") l2 = Factor(Scope.LOCAL, val=f"while.end.{label_index}") codegen.push_code(llvmcodes.LLVMCodeBrCond(cond, l1, l2)) codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"while.body.{label_index}"))
def p_if_condition(p): ''' if_condition : ''' label_index = codegen.label_index() cond = codegen.pop_factor() l1 = Factor(Scope.LOCAL, val=f"if.true.{label_index}") l2 = Factor(Scope.LOCAL, val=f"if.else.{label_index}") codegen.push_code(llvmcodes.LLVMCodeBrCond(cond, l1, l2)) codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"if.true.{label_index}"))
def parse_variable(v, index=None): var = _parse_variable(v) if index is not None: symbol = symtab.lookup(v) index_var = Factor(Scope.LOCAL, val=codegen.register()) retval = Factor(Scope.LOCAL, val=codegen.register()) codegen.push_code(llvmcodes.LLVMCodeSub(index, Factor(Scope.CONSTANT, val=symbol.ptr_offset), index_var)) codegen.push_code(llvmcodes.LLVMCodeGetPointer(retval, var, index_var, symbol.size)) return retval else: return var
def p_read_statement(p): ''' read_statement : READ LPAREN var_name RPAREN ''' val = codegen.pop_factor() # read_value_addr: i32* read で読み取った内容を持つアメモリ番地 read_value_addr = Factor(Scope.LOCAL, val=codegen.register()) retval = Factor(Scope.LOCAL, val=codegen.register()) read_value = Factor(Scope.LOCAL, val=codegen.register()) # read -> read_value_addr -> read_value codegen.push_code(llvmcodes.LLVMCodeAlloca(read_value_addr)) codegen.push_code(llvmcodes.LLVMCodeRead(read_value_addr, retval)) codegen.push_code(llvmcodes.LLVMCodeLoad(read_value, read_value_addr)) codegen.push_code(llvmcodes.LLVMCodeStore(read_value, val)) codegen.enable_read()
def p_var_decl_part(p): ''' var_decl_part : var_decl_list SEMICOLON | ''' if codegen.current_function.is_func: var = Factor(Scope.LOCAL, name=codegen.current_function.name, val=codegen.register()) symtab.insert(var.name, scope=Scope.LOCAL, register=var.val) codegen.push_code(llvmcodes.LLVMCodeAlloca(var))
def p_if_end(p): ''' if_end : ''' label_index = codegen.pop_label_stack() l1 = Factor(Scope.LOCAL, val=f"if.end.{label_index}") codegen.push_code(llvmcodes.LLVMCodeBrUncond(l1)) codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"if.end.{label_index}"))
def p_while_init(p): ''' while_init : ''' label_index = codegen.label_index() l_init = Factor(Scope.LOCAL, val=f"while.init.{label_index}") codegen.push_code(llvmcodes.LLVMCodeBrUncond(l_init)) codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"while.init.{label_index}"))
def p_proc_call_name(p): ''' proc_call_name : IDENT ''' ident = p[1] symbol = symtab.lookup(ident, [Scope.FUNC]) arg = Factor(symbol.scope, name=ident) codegen.push_factor(arg)
def p_write_statement(p): ''' write_statement : WRITE LPAREN expression RPAREN ''' arg = codegen.pop_factor() retval = Factor(Scope.LOCAL, val=codegen.register()) codegen.push_code(llvmcodes.LLVMCodeWrite(arg, retval)) codegen.enable_write()
def p_for_end(p): ''' for_end : ''' # statement 終了後は強制的に for.condition に戻して n < range_to を評価する label_index = codegen.pop_label_stack() l_cond = Factor(Scope.LOCAL, val=f"for.condition.{label_index}") codegen.push_code(llvmcodes.LLVMCodeBrUncond(l_cond)) codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"for.end.{label_index}"))
def p_finalize_function(p): ''' finalize_function : ''' if not codegen.current_function.is_func: codegen.push_code(llvmcodes.LLVMCodeProcReturn()) else: var = parse_variable(codegen.current_function.name) retval = Factor(Scope.LOCAL, val=codegen.register()) codegen.push_code(llvmcodes.LLVMCodeLoad(retval, var)) codegen.push_code(llvmcodes.LLVMCodeProcReturn(retval))
def p_factor(p): ''' factor : var_name | proc_call_name LPAREN arg_list RPAREN proc_call | NUMBER | LPAREN expression RPAREN ''' if len(p) != 2: return # NUMBER if p[1] is not None: val = Factor(Scope.CONSTANT, val=p[1]) codegen.push_factor(val) # var_name else: var = codegen.pop_factor() retval = Factor(Scope.LOCAL, val=codegen.register()) codegen.push_code(llvmcodes.LLVMCodeLoad(retval, var)) codegen.push_factor(retval)
def p_expression(p): ''' expression : term | PLUS term | MINUS term | expression PLUS term | expression MINUS term ''' if len(p) < 3: return if len(p) == 3: arg2 = codegen.pop_factor() arg1 = Factor(Scope.CONSTANT, val=0) else: arg2 = codegen.pop_factor() arg1 = codegen.pop_factor() operator = p[2] assert operator == '+' or operator == '-' # 定数伝搬 if optimization['constant_folding'] and \ arg1.scope == Scope.CONSTANT and arg2.scope == Scope.CONSTANT: val = arg1.val + arg2.val \ if operator == '+' else arg1.val - arg2.val codegen.push_factor(Factor(Scope.CONSTANT, val=val)) return LLVMCodeClass = llvmcodes.LLVMCodeAdd \ if operator == '+' else llvmcodes.LLVMCodeSub retval = Factor(Scope.LOCAL, val=codegen.register()) codegen.push_code(LLVMCodeClass(arg1, arg2, retval)) codegen.push_factor(retval)
def p_condition(p): ''' condition : expression EQ expression | expression NEQ expression | expression LT expression | expression LE expression | expression GT expression | expression GE expression ''' arg2 = codegen.pop_factor() arg1 = codegen.pop_factor() retval = Factor(Scope.LOCAL, val=codegen.register()) ope = llvmcodes.CmpType.from_str(p[2]) codegen.push_code(llvmcodes.LLVMCodeIcmp(ope, arg1, arg2, retval)) codegen.push_factor(retval)
def p_link_args(p): ''' link_args : ''' args = codegen.pop_all_factor() codegen.current_function.args_cnt = len(args) for arg in args: arg_var = Factor(scope=Scope.LOCAL, val=codegen.register()) symtab.insert(arg.name, scope=Scope.LOCAL, register=arg_var.val) codegen.push_code(llvmcodes.LLVMCodeAlloca(arg_var)) codegen.push_code(llvmcodes.LLVMCodeStore(arg.replace(val=arg.val - 1), arg_var)) # 記号表の関数の引数の数を更新する func = symtab.lookup(codegen.current_function.name, [Scope.FUNC]) symtab.update_args_cnt(func, cnt=len(args))
def p_proc_call(p): ''' proc_call : ''' factors = codegen.pop_all_factor() found_func = [i for i, f in enumerate(factors) if f.scope == Scope.FUNC] if not len(found_func) > 0: raise RuntimeError("呼び出された関数が見つかりませんでした") func_index = found_func[0] # 関係ない部分は戻す for f in factors[:func_index]: codegen.push_factor(f) func = factors[func_index] args = factors[func_index + 1:] retval = Factor(Scope.LOCAL, val=codegen.register()) # 引数に対応した関数があるかチェック symtab.lookup(func.name, [Scope.FUNC], args_cnt = len(args)) codegen.push_code(llvmcodes.LLVMCodeCallProc(func, args, retval)) codegen.push_factor(retval)
def p_for_init(p): ''' for_init : ''' # for n:= 2 to 100 # ↓ # for ident := range_from to range_to ident = latest_id_name(p) range_to = codegen.pop_factor() range_from = codegen.pop_factor() var = parse_variable(ident) label_index = codegen.label_index() # n := 2 codegen.push_code(llvmcodes.LLVMCodeStore(range_from, var)) # 初期化時は無条件で statement に移動 l_body = Factor(Scope.LOCAL, val=f"for.body.{label_index}") codegen.push_code(llvmcodes.LLVMCodeBrUncond(l_body)) # statement が終わったあとに戻ってくる for.condition のポイントを作成 codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"for.condition.{label_index}")) # n++ ## n をレジスタに読み込み reg_ident = Factor(Scope.LOCAL, val=codegen.register()) codegen.push_code(llvmcodes.LLVMCodeLoad(reg_ident, var)) ## n + 1 one = Factor(Scope.CONSTANT, val=1) reg_ident_increased = Factor(Scope.LOCAL, val=codegen.register()) codegen.push_code(llvmcodes.LLVMCodeAdd(reg_ident, one, reg_ident_increased)) ## レジスタの内容を n に戻す codegen.push_code(llvmcodes.LLVMCodeStore(reg_ident_increased, var)) # n が range_from に到達したかのチェック ## n <= range_to cond = Factor(Scope.LOCAL, val=codegen.register()) codegen.push_code(llvmcodes.LLVMCodeIcmp(llvmcodes.CmpType.SLE, reg_ident_increased, range_to, cond)) l_end = Factor(Scope.LOCAL, val=f"for.end.{label_index}") codegen.push_code(llvmcodes.LLVMCodeBrCond(cond, l_body, l_end)) codegen.push_code(llvmcodes.LLVMCodeRegisterLabel(f"for.body.{label_index}"))