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 p_iteration_statement_1(p): '''iteration_statement : WHILE '(' expression ')' statement''' while_cmp_l, l_cmp = cg.label("while_cmp") while_body_l, l_body = cg.label("while_body") while_end_l, l_end = cg.label("while_end") p[0] = {} p[0]['alloc'] = p[5].get('alloc','') br_cmp = "br label %{}".format(while_cmp_l) cmp = cg.compare(p[3], while_body_l, while_end_l) p[0]['code'] = (cg.indent(br_cmp) + l_cmp + p[3]['code'] + cmp + l_body + p[5]['code'] + cg.indent(br_cmp) + cg.indent(l_end,0))
def p_selection_statement_2(p): '''selection_statement : IF '(' expression ')' statement ELSE statement''' if_l, l_if = cg.label("if") else_l, l_else = cg.label("else") endif_l, l_endif = cg.label("endif") p[0] = {} p[0]['alloc'] = p[5].get('alloc','') + p[7].get('alloc','') cmp = cg.compare(p[3]['id'], if_l, else_l) br_endif = "br label %{}".format(endif_l) p[0]['code'] = (p[3]['code'] + cmp + cg.indent(l_if, 0) + p[5]['code'] + cg.indent(br_endif) + l_else + p[7]['code'] + cg.indent(br_endif) + l_endif)
def p_iteration_statement_2(p): '''iteration_statement : DO statement WHILE '(' expression ')' ';' ''' while_body_l, l_body = cg.label("do_while_body") while_cmp_l, l_cmp = cg.label("do_while_cmp") while_end_l, l_end = cg.label("do_while_end") p[0] = {} p[0]['alloc'] = p[2].get('alloc','') br_body = "br label %{}".format(while_body_l) cmp = cg.compare(p[5], while_body_l, while_end_l) br_cmp = "br label %{}".format(while_cmp_l) p[0]['code'] = (cg.indent(br_body) + l_body + p[2]['code'] + cg.indent(br_cmp) + l_cmp + p[5]['code'] + cmp + l_end)
def p_jump_statement_2(p): '''jump_statement : RETURN expression ';' ''' # print m.symbols p[0] = {} if 'const' in p[2] : l = "ret {0} {1}".format(p[2]['type'], p[2]['val']) p[0]['code'] = cg.indent(l) elif not m.symbols.is_pointer(p[2]['id']) : l = "ret {0} {1}".format(m.symbols.type(p[2]['id']), m.symbols.var(p[2]['id'])) p[0]['code'] = p[2]['code'] + cg.indent(l) else : p[0]['id'], l1 = cg.load(p[2]['id'], "jump_statement") l2 = "ret {0} {1}".format(m.symbols.dereference(p[2]['id']), m.symbols.var(p[0]['id'])) p[0]['code'] = p[2]['code'] + l1 + cg.indent(l2) m.new_label()
def p_function_definition_1(p): '''function_definition : type_specifier declarator new_scope compound_statement leave_scope''' m._register_count = 0 m.symbols.set_args(p[2]['code'][0], p[2]['types'], p[2]['ellipsis']) m.symbols.set_type(p[2]['code'][0], p[1]['code']) m.symbols.set_local(p[2]['code'][0], False) arg_list = [] for arg in p[2]['args']: arg_list.append("{0} {1}".format(m.symbols.type(arg + m.suffix), m.symbols.var(arg + m.suffix))) m.symbols.remove(arg) m.symbols.remove(arg + m.suffix) if p[2]['ellipsis']: arg_list.append('...') args = ', '.join(arg_list) if m.symbols.return_type(p[2]['code'][0]) == m._type_void: tmp = cg.indent("ret void") else: tmp = '' p[0] = {} p[0]['code'] ="\ndefine {0} @{1} ({2}) {{\n{3}{4}{5}{6}}}\n".format(m.symbols.return_type(p[2]['code'][0]), p[2]['code'][0], args, p[2]['init'], p[4]['alloc'], p[4]['code'], tmp)
def p_declarator_2(p): '''declarator : direct_declarator''' p[0] = {} p[0] = p[1] modif = '' if m.symbols.level() == 1 else '*' if m.symbols.level() == 1 and not 'func' in p[0]: #function arguments are copied p[0]['code'] = [p[1]['code']] arg_id = p[0]['code'][0] + m.suffix m.symbols.add(arg_id, last_type_seen, '') m.symbols.add(p[0]['code'][0], last_type_seen, '*') l1 = "{0} = alloca {1}".format(m.symbols.var(p[0]['code'][0]), m.symbols.dereference(p[0]['code'][0])) l2 = cg.assign({'id' : arg_id}, p[0]['code'][0], 'declarator function arg') p[0]['init'] = cg.indent(l1) + l2 p[0]['modif'] = [''] else: p[0]['code'] = [p[1]['code']] p[0]['modif'] = [modif] if 'size' in p[1]: if 'declared' in p[1]: m.symbols.set_size(p[0]['code'][0], p[1]['size']) else: m.symbols.add(p[0]['code'][0], last_type_seen, p[0]['modif'][0], p[1]['size']) else: if not 'declared' in p[1]: m.symbols.add(p[0]['code'][0], last_type_seen, p[0]['modif'][0]) global last_var_seen last_var_seen = p[0]['code'][0]
def p_iteration_statement_3(p): '''iteration_statement : FOR new_scope '(' expression_statement expression_statement expression ')' statement | FOR new_scope '(' declaration expression_statement expression ')' statement''' for_cmp, l_cmp = cg.label("for_cmp") for_incr, l_incr = cg.label("for_incr") for_body, l_body = cg.label("for_body") for_end, l_end = cg.label("for_end") p[0] = {} p[0]['alloc'] = p[4].get('alloc','') p[0]['alloc'] += p[8].get('alloc', '') br_cmp = "br label %{}".format(for_cmp) br_incr = "br label %{}".format(for_incr) cmp = cg.compare(p[5], for_body, for_end) p[0]['code'] = (p[4]['code'] + cg.indent(br_cmp) + l_cmp + p[5]['code'] + cmp + l_incr + p[6]['code'] + cg.indent(br_cmp) + l_body + p[8]['code'] + cg.indent(br_incr) + l_end) m.symbols.leave_scope()
def p_selection_statement_1(p): '''selection_statement : IF '(' expression ')' statement''' if_l, l_if = cg.label("if") endif_l, l_endif = cg.label("endif") p[0] = {} p[0]['alloc'] = p[5].get('alloc','') cmp = cg.compare(p[3], if_l, endif_l) l3 = "br label %{}".format(endif_l) p[0]['code'] = p[3]['code'] + cmp + l_if + p[5]['code'] + cg.indent(l3) + l_endif
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 p_declaration_1(p): '''declaration : type_specifier init_declarator_list ';' ''' p[0] = {} p[0]['code'] = '' p[0]['alloc'] = '' for i in range(len(p[2]['code'])): l = "{0} = alloca {1}".format(m.symbols.var(p[2]['code'][i]), m.symbols.dereference(p[2]['code'][i])) p[0]['alloc'] += cg.indent(l) for i in range(len(p[2]['code'])): if p[2]['assignement'][i]: p[0]['code'] += p[2]['assignement'][i]['code'] p[0]['code'] += cg.assign(p[2]['assignement'][i], p[2]['code'][i], 'declaration')
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 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 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 p_jump_statement_1(p): '''jump_statement : RETURN ';' ''' p[0] = {} p[0]['code'] = cg.indent("ret void") m.new_label()