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))
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)
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)
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)
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)
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
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
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)
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)
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
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