ST_FUNC void arm_init_types(void) { float_type.t = VT_FLOAT; double_type.t = VT_DOUBLE; func_float_type.t = VT_FUNC; func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD); func_double_type.t = VT_FUNC; func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD); }
static struct sym_info *get_or_create_sym(const char *symbol) { unsigned int pos; struct sym_info *sym = sym_get(symbol); if (sym == NULL) { pos = hash_string(symbol) % SYMTAB_SIZE; sym = sym_push(&symtab[pos], symbol, NULL, 0, NULL_EXPR, "", SYM_BIND_DEFAULT); sym->defined = 0; } return sym; }
/* generate function prolog of type 't' */ void gfunc_prolog(int t) { int addr, u, func_call; Sym *sym; char buf[1024]; init_outfile(); /* XXX: pass function name to gfunc_prolog */ il_type_to_str(buf, sizeof(buf), t, funcname); fprintf(il_outfile, ".method static %s il managed\n", buf); fprintf(il_outfile, "{\n"); /* XXX: cannot do better now */ fprintf(il_outfile, " .maxstack %d\n", NB_REGS); fprintf(il_outfile, " .locals (int32, int32, int32, int32, int32, int32, int32, int32)\n"); if (!strcmp(funcname, "main")) fprintf(il_outfile, " .entrypoint\n"); sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT); func_call = sym->r; addr = ARG_BASE; /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->t; func_var = (sym->c == FUNC_ELLIPSIS); if ((func_vt & VT_BTYPE) == VT_STRUCT) { func_vc = addr; addr++; } /* define parameters */ while ((sym = sym->next) != NULL) { u = sym->t; sym_push(sym->v & ~SYM_FIELD, u, VT_LOCAL | lvalue_type(sym->type.t), addr); addr++; } }
// Generate function prolog of type 't' void gfunc_prolog(CType *func_type) { int addr, align, size, func_call, fastcall_nb_regs; int param_index, param_addr; uint8_t *fastcall_regs_ptr; Sym *sym; CType *type; #ifdef DEBUG_BRANCH printf("compile %s\n", func_name); #endif reset_code_buf(); gbranch(CodeStart); sym = func_type->ref; func_naked = FUNC_NAKED(sym->r); func_call = FUNC_CALL(sym->r); addr = 8; loc = 0; regs_used = 0; if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) { fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1; fastcall_regs_ptr = fastcall_regs; } else if (func_call == FUNC_FASTCALLW) { fastcall_nb_regs = 2; fastcall_regs_ptr = fastcallw_regs; } else { fastcall_nb_regs = 0; fastcall_regs_ptr = NULL; } param_index = 0; // If the function returns a structure, then add an implicit pointer parameter func_vt = sym->type; if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { // TODO: fastcall case? func_vc = addr; addr += 4; param_index++; } // Define parameters while ((sym = sym->next) != NULL) { type = &sym->type; size = type_size(type, &align); size = (size + 3) & ~3; if (param_index < fastcall_nb_regs) { // Save FASTCALL register if (!func_naked) { loc -= 4; o(0x89); // movl gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc); param_addr = loc; } } else { param_addr = addr; addr += size; } sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, param_addr); param_index++; } // pascal type call? func_ret_sub = 0; if (func_call == FUNC_STDCALL) func_ret_sub = addr - 8; func_noargs = (addr == 8); }
/* generate function prolog of type 't' */ void gfunc_prolog(CType *func_type) { int addr, align, size, func_call, fastcall_nb_regs; int param_index, param_addr; uint8_t *fastcall_regs_ptr; Sym *sym; CType *type; sym = func_type->ref; func_call = FUNC_CALL(sym->r); addr = 8; loc = 0; if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) { fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1; fastcall_regs_ptr = fastcall_regs; } else if (func_call == FUNC_FASTCALLW) { fastcall_nb_regs = 2; fastcall_regs_ptr = fastcallw_regs; } else { fastcall_nb_regs = 0; fastcall_regs_ptr = NULL; } param_index = 0; ind += FUNC_PROLOG_SIZE; func_sub_sp_offset = ind; /* if the function returns a structure, then add an implicit pointer parameter */ func_vt = sym->type; if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { /* XXX: fastcall case ? */ func_vc = addr; addr += 4; param_index++; } /* define parameters */ while ((sym = sym->next) != NULL) { type = &sym->type; size = type_size(type, &align); size = (size + 3) & ~3; #ifdef FUNC_STRUCT_PARAM_AS_PTR /* structs are passed as pointer */ if ((type->t & VT_BTYPE) == VT_STRUCT) { size = 4; } #endif if (param_index < fastcall_nb_regs) { /* save FASTCALL register */ loc -= 4; o(0x89); /* movl */ gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc); param_addr = loc; } else { param_addr = addr; addr += size; } sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | lvalue_type(type->t), param_addr); param_index++; } func_ret_sub = 0; /* pascal type call ? */ if (func_call == FUNC_STDCALL) func_ret_sub = addr - 8; /* leave some room for bound checking code */ if (tcc_state->do_bounds_check) { oad(0xb8, 0); /* lbound section pointer */ oad(0xb8, 0); /* call to function */ func_bound_offset = lbounds_section->data_offset; } }
/* compile the C file opened in 'file'. Return non zero if errors. */ static int tcc_compile(TCCState *s1) { Sym *define_start; #ifdef INC_DEBUG printf ("%s: **** new file\n", file->filename); #endif preprocess_init (s1); funcname = ""; /* define some often used types */ int8_type.t = VT_INT8; int16_type.t = VT_INT16; int32_type.t = VT_INT32; int64_type.t = VT_INT64; char_pointer_type.t = VT_INT8; mk_pointer (&char_pointer_type); if (tcc_state->bits != 64) { size_type.t = VT_INT32; } else { size_type.t = VT_INT64; } func_old_type.t = VT_FUNC; func_old_type.ref = sym_push (SYM_FIELD, &int32_type, FUNC_CDECL, FUNC_OLD); // FIXME: Should depend on the target options too #ifdef TCC_TARGET_ARM arm_init_types (); #endif #if 0 /* define 'void *alloca(unsigned int)' builtin function */ { Sym *s1; p = anon_sym++; sym = sym_push (p, mk_pointer (VT_VOID), FUNC_CDECL, FUNC_NEW); s1 = sym_push (SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0); s1->next = NULL; sym->next = s1; sym_push (TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0); } #endif define_start = define_stack; nocode_wanted = 1; if (setjmp (s1->error_jmp_buf) == 0) { s1->nb_errors = 0; s1->error_set_jmp_enabled = 1; ch = file->buf_ptr[0]; tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM; // pvtop = vtop; next (); decl (VT_CONST); if (tok != TOK_EOF) { expect ("declaration"); } #if 0 if (pvtop != vtop) { fprintf (stderr, "internal compiler error:" " vstack leak? (%d)", vtop - pvtop); } #endif } s1->error_set_jmp_enabled = 0; /* reset define stack, but leave -Dsymbols (may be incorrect if they are undefined) */ free_defines (define_start); sym_pop (&global_stack, NULL); sym_pop (&local_stack, NULL); return s1->nb_errors != 0? -1: 0; }