コード例 #1
0
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)
コード例 #2
0
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)
コード例 #3
0
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()
コード例 #4
0
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}"))
コード例 #5
0
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}"))
コード例 #6
0
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
コード例 #7
0
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()
コード例 #8
0
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))
コード例 #9
0
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}"))
コード例 #10
0
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}"))
コード例 #11
0
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)
コード例 #12
0
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()
コード例 #13
0
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}"))
コード例 #14
0
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))
コード例 #15
0
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)
コード例 #16
0
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)
コード例 #17
0
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)
コード例 #18
0
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))
コード例 #19
0
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)
コード例 #20
0
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}"))