Example #1
0
def p_primary_expression_12(p):
    '''primary_expression : MALLOC '(' argument_expression_list ')' '''
    nb =  p[3]['code']
    if not m.symbols.modifiers(last_var_seen).startswith('**'):
        m.error("cannot allocate memory for non pointer variable {0}".format(last_var_seen))

    var_tmp = m.new_reg()
    m.symbols.add(var_tmp, m.symbols.primary_type(last_var_seen), m.symbols.modifiers(last_var_seen))
    tmp1 = "{0} = getelementptr {1} null, i32 1\t\t;malloc sizeof".format(m.symbols.var(var_tmp), m.symbols.type(var_tmp))
    size = m.new_reg()
    m.symbols.add(size, m._type_int)
    tmp2 = "{0} = ptrtoint {1} {2} to i32\t\t;malloc sizeof".format(m.symbols.var(size), m.symbols.type(var_tmp), m.symbols.var(var_tmp))
    p[3]['code'] =''
    res = cg.binary_operation(p[3], {'code': '', 'id': size}, '*')
    p[0] = {}
    p[0]['id'] = m.new_reg()
    m.symbols.add(p[0]['id'], m.symbols.primary_type('malloc'), m.symbols.modifiers('malloc'))
    l = "{0} = call {1} @malloc({2} {3})".format(m.symbols.var(p[0]['id']),
        m.symbols.return_type('malloc'), m.symbols.type(res['id']), m.symbols.var(res['id']))

    index = m.reserve_alloc()
    l2 = "call void @..set({0} {1}, {2})\t\t;malloc size".format(m._type_int, index, nb)

    m.symbols.set_allocated(p[0]['id'], index)

    p[0]['code'] = (p[3]['alloc'] +  cg.indent(tmp1) + cg.indent(tmp2)
        + res['code'] + cg.indent(l) + cg.indent(l2))
Example #2
0
def getelementptr(id, index, comment=""):
    if m.symbols.is_array(id) :
        var = m.new_reg()
        tmp = ""
        m.symbols.add(var, m.symbols.primary_type(id), "*", m.symbols.size(id)[:-1]) #TODO FIX HERE
        l = "{0} = getelementptr inbounds {1} {2}, i32 0, i64 {3}\t\t;getelementptr {4}".format(m.symbols.var(var),
            m.symbols.type(id), m.symbols.var(id), index, comment)
    else :
        new, tmp = load(id, comment)
        var = m.new_reg()
        m.symbols.add(var, m.symbols.primary_type(id), m.symbols.modifiers(id, 1))
        if m.symbols.is_allocated(id):
            m.symbols.set_allocated(var, m.symbols.allocated(id))
        l = "{0} = getelementptr inbounds {1} {2}, i64 {3}\t\t;getelementptr {4}".format(m.symbols.var(var),
            m.symbols.type(new), m.symbols.var(new), index, comment)
    return var, tmp + indent(l)
Example #3
0
def p_primary_expression_7(p):
    '''primary_expression : MAP '(' postfix_expression ',' postfix_expression ')' '''
    if m.symbols.is_function(p[3]['id']):
        type1 = m.symbols.args(p[3]['id'])[0]
        type2 = m.symbols.primary_type(p[3]['id'], src=True)
        if type1 not in [m._type_int, m._type_float] or type2 not in [m._type_int, m._type_float]:
            m.error('map type unsuported {0}, {1}'.format(type1, type2))
    else:
        m.error('map first argument must be a function, or a function pointer')

    if m.symbols.is_function(p[3]['id']) and not m.symbols.modifiers(p[3]['id']) :
        var, tmp = cg.cast(p[3], m._type_ptr+'*')
        func = m.new_reg()
        m.symbols.add(func, m._type_ptr, '**')
        tmp1 = "{0} = alloca {1}".format(m.symbols.var(func), m.symbols.dereference(func))
        tmp2 = "store {0} {1}, {2} {3}".format(m.symbols.type(var),
            m.symbols.var(var), m.symbols.type(func), m.symbols.var(func))
        funcl = tmp + cg.indent(tmp1) + cg.indent(tmp2)
    else :
        func = p[3]['id']
        funcl =''

    if m.symbols.is_array(p[5]['id']) :
        tab, tabl = cg.getelementptr(p[5]['id'], 0, 'argument_expression_list')
    else:
        tab = p[5]['id']
        tabl = ''

    p[0] = {}
    p[0]['id'] = m.new_reg()
    size = cg.length(p[5])
    if 'const' in size:
        tab_size = size['const']
    else:
        tab_size = "{0} {1}".format(m.symbols.type(size['id']), m.symbols.var(size['id']))


    m.symbols.add(p[0]['id'], type2, '*')
    l = "{0} = call {2}* (i8**, {1}*, i32)* @..{1}.{2}.map({3} {4}, {5} {6}, {7})".format(
        m.symbols.var(p[0]['id']), type1, type2, m.symbols.type(func), m.symbols.var(func),
        m.symbols.type(tab), m.symbols.var(tab), tab_size)

    m.symbols.set_allocated(p[0]['id'], m.last_alloc())
    p[0]['code'] = funcl + tabl + size['code'] + cg.indent(l)
Example #4
0
def load(id, comment=""):
    var = m.new_reg()
    if m.symbols.is_array(id):
        m.symbols.add(var, m.symbols.primary_type(id), m.symbols.modifiers(id, 1), m.symbols.size(id))
    else:
        m.symbols.add(var, m.symbols.primary_type(id), m.symbols.modifiers(id, 1))
        if m.symbols.is_allocated(id):
            m.symbols.set_allocated(var, m.symbols.allocated(id))
    l = "{0} = load {1} {2}\t\t;load {3}".format(m.symbols.var(var), m.symbols.type(id), m.symbols.var(id), comment)
    return var, indent(l)
Example #5
0
def p_primary_expression_13(p):
    '''primary_expression : FREE '(' argument_expression_list ')' '''
    var_tmp = m.new_reg()
    #print p[3]
    m.symbols.add(var_tmp, m._type_int)
    l = "{0} = call i32 ({1}, ...)* bitcast (i32 (...)* @free to i32 ({1}, ...)*)({1} {2})".format(m.symbols.var(var_tmp),
        m.symbols.type(p[3]['id']), m.symbols.var(p[3]['id']))

    #print m.symbols
    if m.symbols.is_allocated(p[3]['id']):
        m.release_alloc(m.symbols.allocated(p[3]['id']))
    else:
        m.error("invalid free on unalocated variable")
    p[0] = {}
    p[0]['code'] = p[3]['alloc'] + cg.indent(l)
Example #6
0
def length(var):
    res = {}
    if m.symbols.is_array(var['id']):
        res['type'] = m._type_int
        res['val'] = m.symbols.size(var['id'])[-1]
        res['const'] = "{0} {1}".format(res['type'], res['val'])
        res['code'] = ''
    elif m.symbols.is_allocated(var['id']):
        res['id'] = m.new_reg()
        m.symbols.add(res['id'], m._type_int)
        l = "{0} = call i32 @..get(i32 {1})\t\t;len".format(m.symbols.var(res['id']), m.symbols.allocated(var['id']))
        res['code'] = var['code'] + indent(l)
    else:
        m.error("{0} has no len()".format(var['id']))

    return res
Example #7
0
def p_postfix_expression_2(p):
    '''postfix_expression : postfix_expression '[' expression ']' '''
    p[0] = {}
    if 'const' in p[3]:
        index = p[3]['val']
        l1 = ''
    else:
        tmp_var, tmp = cg.load(p[3]['id'], "postfix_expression")
        var_id = m.new_reg()
        m.symbols.add(var_id, 'i64')
        l1 = "{0} = sext {1} {2} to {3}".format(m.symbols.var(var_id), m.symbols.type(tmp_var), m.symbols.var(tmp_var), m.symbols.primary_type(var_id))
        l1 = tmp + cg.indent(l1)
        index = m.symbols.var(var_id)

    p[0]['id'], l2 = cg.getelementptr(p[1]['id'], index)
    p[0]['code'] = p[1]['code'] + l1 + l2
Example #8
0
def compare(var, l_if, l_else):
    if 'const' in var:
        new = "i1 {0}".format(int(bool(int(var['val']))))
        tmp=''
    else:
        if m.symbols.is_pointer(var['id']):
            new, tmp = load(var['id'], "compare")
            new2 = m.new_reg()
            m.symbols.add(new2, m._type_bool, m.symbols.modifiers(new, 1))
            if m.symbols.primary_type(new) == m._type_float:
                tmp2 = "{0} = fcmp une {1} {2}, 0.000000e+00".format(m.symbols.var(new2), m.symbols.type(new), m.symbols.var(new))
            else:
                tmp2 = "{0} = icmp ne {1} {2}, 0".format(m.symbols.var(new2), m.symbols.type(new), m.symbols.var(new))
            tmp = tmp + indent(tmp2)
            id = new2
        else:
            id, tmp = var['id'], ''

        new = "{0} {1}".format(m.symbols.type(id), m.symbols.var(id))

    l = "br {0}, label %{1}, label %{2}".format(new, l_if, l_else)
    return tmp + indent(l)
Example #9
0
def p_primary_expression_9(p):
    '''primary_expression : IDENTIFIER '(' ')'
                          | IDENTIFIER '(' argument_expression_list ')' '''

    if p[1] not in m.symbols :
        m.error("use of undeclared function '{0}'".format(p[1]))
        p[1] = 'empty_func'
    p[0] = {}
    if len(p) == 5:
        #TODO check type
        code = p[3]['alloc']
        args = p[3]['code']
    else :
        code = ''
        args = ''
    #print m.symbols
    type = m.symbols.return_type(p[1])
    if m.symbols.has_ellipsis(p[1]):
        type = "{0} {1}".format(type, m.symbols.reference(p[1]))

    p[0]['id'] = m.new_reg()
    m.symbols.add(p[0]['id'], m.symbols.return_type(p[1]))
    l = "{0} = call {1} @{2}({3})".format(m.symbols.var(p[0]['id']), type, p[1], args)
    p[0]['code'] = code + cg.indent(l)
Example #10
0
def cast(src, type, comment=""):
    var = {}
    if 'const' in src:
        if type in [m._type_int, m._type_char, m._type_bool]:
            var['val'] = int(src['val'])
        elif type == m._type_float:
            var['val'] = float(src['val'])

        var['type'] = type
        var['code'] = src['code']
        var['const'] = "{0} {1}".format(var['type'], var['val'])
        l = ''
    else:
        op = None
        if (type[len(m.symbols.modifiers(src['id'])):] == m.symbols.modifiers(src['id'])) or (m.symbols.is_pointer(src['id']) and not type.endswith('*')):#type == m.symbols.type(src['id']) or m.symbols.is_pointer(src['id']):
            new, l1 = load(src['id'], 'cast '+comment)
        elif  m.symbols.is_pointer(src['id']) and type.endswith('*'):
            if m.symbols.primary_type(src['id']) != m._type_ptr and m.symbols.is_function(src['id']) or not src['code']:
                new, l1 = load(src['id'], 'cast '+comment)
            else:
                new, l1 = src['id'], ''
        else:
            new, l1 = src['id'], ''

        if m.symbols.type(new) == m._type_ptr+'*' and type.endswith('*'):
            op = 'bitcast'
        elif m.symbols.is_function(new) and type == m._type_ptr+'*':
            op = 'bitcast'
        elif m.symbols.is_pointer(new) and type.endswith('*'):
            op = 'bitcast'
        elif m.symbols.primary_type(new) == m._type_float and type in [m._type_int, m._type_char]:
            op = 'fptosi'
        elif m.symbols.primary_type(new) in [m._type_int, m._type_char] and type == m._type_float:
            op = 'sitofp'
        elif m.symbols.primary_type(new) == m._type_bool and type == m._type_int:
            op = 'zext'
        elif m.symbols.primary_type(new) == m._type_char and type == m._type_int:
            op = 'sext'
        elif m.symbols.primary_type(new) == m._type_int and type == m._type_char:
            op = 'trunc'

        if op is None:
            m.error("Invalid cast from {0} to {1}".format(m.symbols.primary_type(new), type))

        var = m.new_reg()
        m.symbols.add(var, type.split('*')[0], type.count('*')*'*')
        if m.symbols.is_allocated(new):
            m.symbols.set_allocated(var, m.symbols.allocated(new))


        if m.symbols.is_function(new):
            m.symbols.set_args(var, m.symbols.args(new), m.symbols.has_ellipsis(new), primary=m.symbols.primary_type(src['id']))
            args = [] + m.symbols.args(new)
            if m.symbols.has_ellipsis(new):
                args.append('...')
            tmp = ', '.join(args)
            new_type = "{0} ({1})*".format(m.symbols.return_type(new), tmp)
        else:
            new_type = m.symbols.type(new)

        # print m.symbols

        l2 = "{0} = {1} {2} {3} to {4}\t\t;cast {5}".format(m.symbols.var(var), op, new_type, m.symbols.var(new), type, comment)
        l = l1 + indent(l2)

    return var,l
Example #11
0
def binary_operation(left, right, operator):
    res = {}
    if 'const' in left and 'const' in right:
        res['type'] = m.type_table(left['type'], right['type'], operator)
        if res['type'] is None:
            print('error: invalid operation')

        if operator == '<':
            res['val'] = int(left['val'] < right['val'])
        elif operator == '>':
            res['val'] = int(left['val'] > right['val'])
        elif operator == '<=':
            res['val'] = int(left['val'] <= right['val'])
        elif operator == '>=':
            res['val'] = int(left['val'] >= right['val'])
        elif operator == '==':
            res['val'] = int(left['val'] == right['val'])
        elif operator == '!=':
            res['val'] = int(left['val'] != right['val'])
        elif operator == '+':
            res['val'] = left['val'] + right['val']
        elif operator == '-':
            res['val'] = left['val'] - right['val']
        elif operator == '*':
            res['val'] = left['val'] * right['val']
        elif operator == '/':
            res['val'] = left['val'] / right['val']

        res['const'] = "{0} {1}".format(res['type'], res['val'])
        res['code'] = ''

    else:
        if 'const' in left:
            type1 = left['type']
            var1 = left
            c1 = ''
        else:
            if m.symbols.is_pointer(left['id']):
                type1 = m.symbols.dereference(left['id'])
                var1, c1 = load(left['id'], 'relational_expression')
                var1 = {'id' : var1}
            else:
                type1 = m.symbols.type(left['id'])
                var1 = left
                c1 = ''

        if 'const' in right:
            type2= right['type']
            var2 = right
            c2 = ''
        else:
            if m.symbols.is_pointer(right['id']):
                type2 = m.symbols.dereference(right['id'])
                var2, c2 = load(right['id'], 'relational_expression')
                var2 = {'id' : var2}
            else:
                type2 = m.symbols.type(right['id'])
                var2 = right
                c2 = ''

        res_type = m.type_table(type1, type2, operator)
        if res_type is None:
            if operator in ['+', '-', '*', '/']:
                m.error('invalid operation {0}'.format(operator))
            else:
                m.error('invalid comparaison {0}'.format(operator))

        if operator in ['+', '-', '*', '/']:
            tmp = ''
            if type1 != res_type:
                var1, tmp = cast(var1, res_type, 'relational_expression')
                if not 'const' in var1:
                    var1 = {'id': var1}
            if type2 != res_type:
                var2, tmp = cast(var2, res_type, 'relational_expression')
                if not 'const' in var2:
                    var2 = {'id': var2}

            if 'const' in var1:
                var1 = var1['val']
            else:
                var1 = m.symbols.var(var1['id'])
            if 'const' in var2:
                var2 = var2['val']
            else:
                var2 = m.symbols.var(var2['id'])

            if operator == '+':
                op = 'add'
            elif operator == '-':
                op = 'sub'
            elif operator == '*':
                op = 'mul'
            elif operator == '/':
                op = 'div'

            op = 'f'+op if res_type == m._type_float else op
            if op == 'div':
                op = 'udiv'

            res['id'] = m.new_reg()
            m.symbols.add(res['id'], res_type)
            l = "{0} = {1} {2} {3}, {4}".format(m.symbols.var(res['id']), op, res_type, var1, var2)
            res['code'] = left['code'] + right['code'] + c1 + c2 + tmp + indent(l)

        else:
            if 'const' in var1:
                var1 = var1['val']
            else:
                var1 = m.symbols.var(var1['id'])
            if 'const' in var2:
                var2 = var2['val']
            else:
                var2 = m.symbols.var(var2['id'])

            if operator == '<':
                cmp = 'lt'
            elif operator == '>':
                cmp = 'gt'
            elif operator == '<=':
                cmp = 'le'
            elif operator == '>=':
                cmp = 'ge'
            elif operator == '==':
                cmp = 'eq'
            elif operator == '!=':
                cmp = 'ne'

            if res_type == m._type_float:
                op = "fcmp"
                cmp = "o"+cmp
            elif cmp not in ['ne', 'eq']:
                op = "icmp"
                cmp = "s"+cmp
            else :
                op = "icmp"

            res['id'] = m.new_reg()
            m.symbols.add(res['id'], res_type)
            l = "{0} = {1} {2} {3} {4}, {5}".format(m.symbols.var(res['id']), op, cmp, type1, var1, var2)
            res['code'] = left['code'] + right['code'] + c1 + c2 + indent(l)
    return res