Further strip down tcc
This commit is contained in:
parent
94b74d446f
commit
c5d1e40ebe
30 changed files with 723 additions and 1881 deletions
|
@ -1,6 +1,7 @@
|
|||
noinst_LIBRARIES = libtcc.a
|
||||
libtcc_a_SOURCES = libtcc.c option.c path.c memory.c tccpp.c tccgen.c \
|
||||
tccasm.c tccelf.c \
|
||||
i386/gen.c i386/link.c \
|
||||
i386/asm.c tcccoff.c
|
||||
libtcc_a_SOURCES = libtcc.c option.c path.c io.c memory.c \
|
||||
cc/tccpp.c cc/tccgen.c \
|
||||
cc/tccasm.c tccelf.c \
|
||||
cc/i386/gen.c cc/i386/link.c \
|
||||
cc/i386/asm.c tcccoff.c
|
||||
libtcc_a_CPPFLAGS = -I$(top_srcdir) -I$(srcdir) -I$(srcdir)/include
|
275
libtcc/cc/cc.h
Normal file
275
libtcc/cc/cc.h
Normal file
|
@ -0,0 +1,275 @@
|
|||
#ifndef TCC_CC_H
|
||||
# define TCC_CC_H
|
||||
|
||||
# include <tcc.h>
|
||||
|
||||
/* ------------ tccpp.c ------------ */
|
||||
|
||||
extern struct BufferedFile *file;
|
||||
extern int tok;
|
||||
extern CValue tokc;
|
||||
extern const int *macro_ptr;
|
||||
extern int parse_flags;
|
||||
extern int tok_flags;
|
||||
extern CString tokcstr; /* current parsed string, if any */
|
||||
|
||||
/* display benchmark infos */
|
||||
extern int tok_ident;
|
||||
extern TokenSym **table_ident;
|
||||
extern int pp_expr;
|
||||
|
||||
#define TOK_FLAG_BOL 0x0001 /* beginning of line before */
|
||||
#define TOK_FLAG_BOF 0x0002 /* beginning of file before */
|
||||
#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
|
||||
|
||||
#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
|
||||
#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
|
||||
#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
|
||||
token. line feed is also
|
||||
returned at eof */
|
||||
#define PARSE_FLAG_ASM_FILE 0x0008 /* we processing an asm file: '#' can be used for line comment, etc. */
|
||||
#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
|
||||
#define PARSE_FLAG_ACCEPT_STRAYS 0x0020 /* next() returns '\\' token */
|
||||
#define PARSE_FLAG_TOK_STR 0x0040 /* return parsed strings instead of TOK_PPSTR */
|
||||
|
||||
/* isidnum_table flags: */
|
||||
#define IS_SPC 1
|
||||
#define IS_ID 2
|
||||
#define IS_NUM 4
|
||||
|
||||
enum line_macro_output_format {
|
||||
LINE_MACRO_OUTPUT_FORMAT_GCC,
|
||||
LINE_MACRO_OUTPUT_FORMAT_NONE,
|
||||
LINE_MACRO_OUTPUT_FORMAT_STD,
|
||||
LINE_MACRO_OUTPUT_FORMAT_P10 = 11
|
||||
};
|
||||
|
||||
TokenSym *tok_alloc(const char *str, int len);
|
||||
int tok_alloc_const(const char *str);
|
||||
const char *get_tok_str(int v, CValue *cv);
|
||||
void begin_macro(TokenString *str, int alloc);
|
||||
void end_macro(void);
|
||||
int set_idnum(int c, int val);
|
||||
void tok_str_new(TokenString *s);
|
||||
TokenString *tok_str_alloc(void);
|
||||
void tok_str_free(TokenString *s);
|
||||
void tok_str_free_str(int *str);
|
||||
void tok_str_add(TokenString *s, int t);
|
||||
void tok_str_add_tok(TokenString *s);
|
||||
void define_push(int v, int macro_type, int *str, Sym *first_arg);
|
||||
void define_undef(Sym *s);
|
||||
Sym *define_find(int v);
|
||||
void free_defines(Sym *b);
|
||||
void parse_define(void);
|
||||
void skip_to_eol(int warn);
|
||||
void preprocess(int is_bof);
|
||||
void next(void);
|
||||
void unget_tok(int last_tok);
|
||||
void preprocess_start(TCCState *s1, int filetype);
|
||||
void preprocess_end(TCCState *s1);
|
||||
void tccpp_new(TCCState *s);
|
||||
void tccpp_delete(TCCState *s);
|
||||
void tccpp_putfile(const char *filename);
|
||||
int tcc_preprocess(TCCState *s1);
|
||||
void skip(int c);
|
||||
__attribute__((noreturn)) void expect(const char *msg);
|
||||
void pp_error(CString *cs);
|
||||
|
||||
|
||||
/* space excluding newline */
|
||||
static inline int is_space(int ch) {
|
||||
return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
|
||||
}
|
||||
static inline int isid(int c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||
}
|
||||
static inline int isnum(int c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
static inline int isoct(int c) {
|
||||
return c >= '0' && c <= '7';
|
||||
}
|
||||
|
||||
/* ------------ tccgen.c ------------ */
|
||||
|
||||
#define SYM_POOL_NB (8192 / sizeof(Sym))
|
||||
|
||||
extern Sym *global_stack;
|
||||
extern Sym *local_stack;
|
||||
extern Sym *local_label_stack;
|
||||
extern Sym *global_label_stack;
|
||||
extern Sym *define_stack;
|
||||
extern CType int_type, func_old_type, char_pointer_type;
|
||||
extern SValue *vtop;
|
||||
extern int rsym, anon_sym, ind, loc;
|
||||
extern char debug_modes;
|
||||
|
||||
extern int nocode_wanted; /* true if no code generation wanted for an expression */
|
||||
extern int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
||||
extern CType func_vt; /* current function return type (used by return instruction) */
|
||||
extern int func_var; /* true if current function is variadic */
|
||||
extern int func_vc;
|
||||
extern int func_ind;
|
||||
extern const char *funcname;
|
||||
|
||||
void tccgen_init(TCCState *s1);
|
||||
int tccgen_compile(TCCState *s1);
|
||||
void tccgen_finish(TCCState *s1);
|
||||
void check_vstack(void);
|
||||
|
||||
int is_float(int t);
|
||||
int ieee_finite(double d);
|
||||
int exact_log2p1(int i);
|
||||
void test_lvalue(void);
|
||||
|
||||
ElfSym *elfsym(Sym *);
|
||||
void update_storage(Sym *sym);
|
||||
void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
|
||||
void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
|
||||
#if PTR_SIZE == 4
|
||||
void greloc(Section *s, Sym *sym, unsigned long offset, int type);
|
||||
#endif
|
||||
void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
||||
|
||||
void sym_free(Sym *sym);
|
||||
Sym *sym_push(int v, CType *type, int r, int c);
|
||||
void sym_pop(Sym **ptop, Sym *b, int keep);
|
||||
Sym *sym_push2(Sym **ps, int v, int t, int c);
|
||||
Sym *sym_find2(Sym *s, int v);
|
||||
Sym *sym_find(int v);
|
||||
Sym *label_find(int v);
|
||||
Sym *label_push(Sym **ptop, int v, int flags);
|
||||
void label_pop(Sym **ptop, Sym *slast, int keep);
|
||||
Sym *struct_find(int v);
|
||||
|
||||
Sym *global_identifier_push(int v, int t, int c);
|
||||
Sym *external_global_sym(int v, CType *type);
|
||||
Sym *external_helper_sym(int v);
|
||||
void vpush_helper_func(int v);
|
||||
void vset(CType *type, int r, int v);
|
||||
void vset_VT_CMP(int op);
|
||||
void vpushi(int v);
|
||||
void vpushv(SValue *v);
|
||||
void vpushsym(CType *type, Sym *sym);
|
||||
void vswap(void);
|
||||
void vrott(int n);
|
||||
void vrotb(int n);
|
||||
void vrev(int n);
|
||||
void vpop(void);
|
||||
#if PTR_SIZE == 4
|
||||
void lexpand(void);
|
||||
#endif
|
||||
void save_reg(int r);
|
||||
void save_reg_upstack(int r, int n);
|
||||
int get_reg(int rc);
|
||||
void save_regs(int n);
|
||||
void gaddrof(void);
|
||||
int gv(int rc);
|
||||
void gv2(int rc1, int rc2);
|
||||
void gen_op(int op);
|
||||
int type_size(CType *type, int *a);
|
||||
void mk_pointer(CType *type);
|
||||
void vstore(void);
|
||||
void inc(int post, int c);
|
||||
CString* parse_mult_str(const char *msg);
|
||||
CString* parse_asm_str(void);
|
||||
void indir(void);
|
||||
void unary(void);
|
||||
void gexpr(void);
|
||||
int expr_const(void);
|
||||
|
||||
/* ------------ xxx-link.c ------------ */
|
||||
|
||||
#if !defined ELF_OBJ_ONLY
|
||||
int code_reloc (int reloc_type);
|
||||
#define NEED_RELOC_TYPE
|
||||
|
||||
#endif
|
||||
|
||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
|
||||
|
||||
|
||||
/* ------------ xxx-gen.c ------------ */
|
||||
extern const char * const target_machine_defs;
|
||||
extern const int reg_classes[NB_REGS];
|
||||
|
||||
void gsym_addr(int t, int a);
|
||||
void gsym(int t);
|
||||
void load(int r, SValue *sv);
|
||||
void store(int r, SValue *v);
|
||||
int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
|
||||
void gfunc_call(int nb_args);
|
||||
void gfunc_prolog(Sym *func_sym);
|
||||
void gfunc_epilog(void);
|
||||
void gen_fill_nops(int);
|
||||
int gjmp(int t);
|
||||
void gjmp_addr(int a);
|
||||
int gjmp_cond(int op, int t);
|
||||
int gjmp_append(int n, int t);
|
||||
void gen_opi(int op);
|
||||
void gen_opf(int op);
|
||||
void gen_cvt_ftoi(int t);
|
||||
void gen_cvt_itof(void);
|
||||
void gen_cvt_ftof(void);
|
||||
void ggoto(void);
|
||||
void o(unsigned int c);
|
||||
void gen_vla_sp_save(int addr);
|
||||
void gen_vla_sp_restore(int addr);
|
||||
void gen_vla_alloc(CType *type, int align);
|
||||
|
||||
static inline uint16_t read16le(unsigned char *p) {
|
||||
return p[0] | (uint16_t)p[1] << 8;
|
||||
}
|
||||
static inline void write16le(unsigned char *p, uint16_t x) {
|
||||
p[0] = x & 255; p[1] = x >> 8 & 255;
|
||||
}
|
||||
static inline uint32_t read32le(unsigned char *p) {
|
||||
return read16le(p) | (uint32_t)read16le(p + 2) << 16;
|
||||
}
|
||||
static inline void write32le(unsigned char *p, uint32_t x) {
|
||||
write16le(p, x); write16le(p + 2, x >> 16);
|
||||
}
|
||||
static inline void add32le(unsigned char *p, int32_t x) {
|
||||
write32le(p, read32le(p) + x);
|
||||
}
|
||||
static inline uint64_t read64le(unsigned char *p) {
|
||||
return read32le(p) | (uint64_t)read32le(p + 4) << 32;
|
||||
}
|
||||
static inline void write64le(unsigned char *p, uint64_t x) {
|
||||
write32le(p, x); write32le(p + 4, x >> 32);
|
||||
}
|
||||
static inline void add64le(unsigned char *p, int64_t x) {
|
||||
write64le(p, read64le(p) + x);
|
||||
}
|
||||
|
||||
/* ------------ i386-gen.c ------------ */
|
||||
void g(int c);
|
||||
void gen_le16(int c);
|
||||
void gen_le32(int c);
|
||||
|
||||
void gen_addr32(int r, Sym *sym, int c);
|
||||
void gen_addrpc32(int r, Sym *sym, int c);
|
||||
void gen_cvt_csti(int t);
|
||||
|
||||
/* ------------ tccasm.c ------------ */
|
||||
void asm_instr(TCCState *s1);
|
||||
void asm_global_instr(TCCState *s1);
|
||||
int tcc_assemble(TCCState *s1, int do_preprocess);
|
||||
int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
|
||||
Sym* get_asm_sym(TCCState *s1, int name, Sym *csym);
|
||||
void asm_expr(TCCState *s1, ExprValue *pe);
|
||||
int asm_int_expr(TCCState *s1);
|
||||
|
||||
/* ------------ i386-asm.c ------------ */
|
||||
void gen_expr32(ExprValue *pe);
|
||||
void asm_opcode(TCCState *s1, int opcode);
|
||||
int asm_parse_regvar(int t);
|
||||
void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
|
||||
void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
|
||||
void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
|
||||
void asm_clobber(uint8_t *clobber_regs, const char *str);
|
||||
|
||||
#define ST_ASM_SET 0x04
|
||||
|
||||
|
||||
#endif /* !TCC_CC_H */
|
|
@ -25,7 +25,9 @@
|
|||
|
||||
#define USING_GLOBALS
|
||||
#include "tcc.h"
|
||||
#include "token.h"
|
||||
#define USING_GLOBALS
|
||||
#include "cc/cc.h"
|
||||
#include "cC/token.h"
|
||||
|
||||
#define MAX_OPERANDS 3
|
||||
|
||||
|
@ -1268,7 +1270,7 @@ void subst_asm_operand(CString *add_str,
|
|||
in the C symbol table when later looking up
|
||||
this name. So enter them now into the asm label
|
||||
list when we still know the symbol. */
|
||||
get_asm_sym(tok_alloc_const(name), sv->sym);
|
||||
get_asm_sym(tcc_state, tok_alloc_const(name), sv->sym);
|
||||
}
|
||||
if (tcc_state->leading_underscore)
|
||||
cstr_ccat(add_str, '_');
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
#define USING_GLOBALS
|
||||
#include <tcc.h>
|
||||
#include "token.h"
|
||||
#include "cc/token.h"
|
||||
#define USING_GLOBALS
|
||||
#include "cc/cc.h"
|
||||
|
||||
const char * const target_machine_defs =
|
||||
"__i386__\0"
|
|
@ -1,4 +1,5 @@
|
|||
#include <tcc.h>
|
||||
#include "cc/cc.h"
|
||||
|
||||
#ifdef NEED_RELOC_TYPE
|
||||
/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
|
||||
|
@ -9,10 +10,6 @@ int code_reloc (int reloc_type)
|
|||
case R_386_RELATIVE:
|
||||
case R_386_16:
|
||||
case R_386_32:
|
||||
case R_386_GOTPC:
|
||||
case R_386_GOTOFF:
|
||||
case R_386_GOT32:
|
||||
case R_386_GOT32X:
|
||||
case R_386_GLOB_DAT:
|
||||
case R_386_COPY:
|
||||
case R_386_TLS_GD:
|
||||
|
@ -23,126 +20,12 @@ int code_reloc (int reloc_type)
|
|||
|
||||
case R_386_PC16:
|
||||
case R_386_PC32:
|
||||
case R_386_PLT32:
|
||||
case R_386_JMP_SLOT:
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns an enumerator to describe whether and when the relocation needs a
|
||||
GOT and/or PLT entry to be created. See tcc.h for a description of the
|
||||
different values. */
|
||||
int gotplt_entry_type (int reloc_type)
|
||||
{
|
||||
switch (reloc_type) {
|
||||
case R_386_RELATIVE:
|
||||
case R_386_16:
|
||||
case R_386_GLOB_DAT:
|
||||
case R_386_JMP_SLOT:
|
||||
case R_386_COPY:
|
||||
return NO_GOTPLT_ENTRY;
|
||||
|
||||
case R_386_32:
|
||||
/* This relocations shouldn't normally need GOT or PLT
|
||||
slots if it weren't for simplicity in the code generator.
|
||||
See our caller for comments. */
|
||||
return AUTO_GOTPLT_ENTRY;
|
||||
|
||||
case R_386_PC16:
|
||||
case R_386_PC32:
|
||||
return AUTO_GOTPLT_ENTRY;
|
||||
|
||||
case R_386_GOTPC:
|
||||
case R_386_GOTOFF:
|
||||
return BUILD_GOT_ONLY;
|
||||
|
||||
case R_386_GOT32:
|
||||
case R_386_GOT32X:
|
||||
case R_386_PLT32:
|
||||
case R_386_TLS_GD:
|
||||
case R_386_TLS_LDM:
|
||||
case R_386_TLS_LDO_32:
|
||||
case R_386_TLS_LE:
|
||||
return ALWAYS_GOTPLT_ENTRY;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef NEED_BUILD_GOT
|
||||
unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
|
||||
{
|
||||
Section *plt = s1->plt;
|
||||
uint8_t *p;
|
||||
int modrm;
|
||||
unsigned plt_offset, relofs;
|
||||
|
||||
modrm = 0x25;
|
||||
|
||||
/* empty PLT: create PLT0 entry that pushes the library identifier
|
||||
(GOT + PTR_SIZE) and jumps to ld.so resolution routine
|
||||
(GOT + 2 * PTR_SIZE) */
|
||||
if (plt->data_offset == 0) {
|
||||
p = section_ptr_add(plt, 16);
|
||||
p[0] = 0xff; /* pushl got + PTR_SIZE */
|
||||
p[1] = modrm + 0x10;
|
||||
write32le(p + 2, PTR_SIZE);
|
||||
p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
|
||||
p[7] = modrm;
|
||||
write32le(p + 8, PTR_SIZE * 2);
|
||||
}
|
||||
plt_offset = plt->data_offset;
|
||||
|
||||
/* The PLT slot refers to the relocation entry it needs via offset.
|
||||
The reloc entry is created below, so its offset is the current
|
||||
data_offset */
|
||||
relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
|
||||
|
||||
/* Jump to GOT entry where ld.so initially put the address of ip + 4 */
|
||||
p = section_ptr_add(plt, 16);
|
||||
p[0] = 0xff; /* jmp *(got + x) */
|
||||
p[1] = modrm;
|
||||
write32le(p + 2, got_offset);
|
||||
p[6] = 0x68; /* push $xxx */
|
||||
write32le(p + 7, relofs - sizeof (ElfW_Rel));
|
||||
p[11] = 0xe9; /* jmp plt_start */
|
||||
write32le(p + 12, -(plt->data_offset));
|
||||
return plt_offset;
|
||||
}
|
||||
|
||||
/* relocate the PLT: compute addresses and offsets in the PLT now that final
|
||||
address for PLT and GOT are known (see fill_program_header) */
|
||||
void relocate_plt(TCCState *s1)
|
||||
{
|
||||
uint8_t *p, *p_end;
|
||||
|
||||
if (!s1->plt)
|
||||
return;
|
||||
|
||||
p = s1->plt->data;
|
||||
p_end = p + s1->plt->data_offset;
|
||||
|
||||
if (p < p_end) {
|
||||
add32le(p + 2, s1->got->sh_addr);
|
||||
add32le(p + 8, s1->got->sh_addr);
|
||||
p += 16;
|
||||
while (p < p_end) {
|
||||
add32le(p + 2, s1->got->sh_addr);
|
||||
p += 16;
|
||||
}
|
||||
}
|
||||
|
||||
if (s1->plt->reloc) {
|
||||
ElfW_Rel *rel;
|
||||
int x = s1->plt->sh_addr + 16 + 6;
|
||||
p = s1->got->data;
|
||||
for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
|
||||
write32le(p + rel->r_offset, x);
|
||||
x += 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
|
||||
|
@ -158,24 +41,10 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||
case R_386_PC32:
|
||||
add32le(ptr, val - addr);
|
||||
return;
|
||||
case R_386_PLT32:
|
||||
add32le(ptr, val - addr);
|
||||
return;
|
||||
case R_386_GLOB_DAT:
|
||||
case R_386_JMP_SLOT:
|
||||
write32le(ptr, val);
|
||||
return;
|
||||
case R_386_GOTPC:
|
||||
add32le(ptr, s1->got->sh_addr - addr);
|
||||
return;
|
||||
case R_386_GOTOFF:
|
||||
add32le(ptr, val - s1->got->sh_addr);
|
||||
return;
|
||||
case R_386_GOT32:
|
||||
case R_386_GOT32X:
|
||||
/* we load the got offset */
|
||||
add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
|
||||
return;
|
||||
case R_386_16:
|
||||
if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
|
||||
output_file:
|
||||
|
@ -220,7 +89,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||
|
||||
memcpy(ptr-3, replace, sizeof(replace));
|
||||
rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
|
||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||
sym = &((ElfW(Sym) *)s1->symtab_section->data)[sym_index];
|
||||
sec = s1->sections[sym->st_shndx];
|
||||
x = sym->st_value - sec->sh_addr - sec->data_offset;
|
||||
add32le(ptr + 5, -x);
|
||||
|
@ -259,7 +128,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t
|
|||
Section *sec;
|
||||
int32_t x;
|
||||
|
||||
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
|
||||
sym = &((ElfW(Sym) *)s1->symtab_section->data)[sym_index];
|
||||
sec = s1->sections[sym->st_shndx];
|
||||
x = val - sec->sh_addr - sec->data_offset;
|
||||
add32le(ptr, x);
|
|
@ -17,16 +17,23 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "libtcc.h"
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define USING_GLOBALS
|
||||
#include "tcc.h"
|
||||
#include "utils/string.h"
|
||||
#include "token.h"
|
||||
#include "cc/cc.h"
|
||||
|
||||
#undef tcc_error
|
||||
#undef _tcc_error
|
||||
#define tcc_error _tcc_error
|
||||
#undef tcc_warning
|
||||
#define tcc_warning _tcc_warning
|
||||
|
||||
static Section *last_text_section; /* to handle .previous asm directive */
|
||||
static int asmgoto_n;
|
||||
|
@ -53,11 +60,11 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, in
|
|||
the global C symbol table to track ASM names as well, so we need to
|
||||
transform those into ones that don't conflict with a C name,
|
||||
so prepend a '.' for them, but force the ELF asm name to be set. */
|
||||
static int asm2cname(int v, int *addeddot)
|
||||
static int asm2cname(TCCState *s1, int v, int *addeddot)
|
||||
{
|
||||
const char *name;
|
||||
*addeddot = 0;
|
||||
if (!tcc_state->leading_underscore)
|
||||
if (!s1->leading_underscore)
|
||||
return v;
|
||||
name = get_tok_str(v, NULL);
|
||||
if (!name)
|
||||
|
@ -73,20 +80,20 @@ static int asm2cname(int v, int *addeddot)
|
|||
return v;
|
||||
}
|
||||
|
||||
static Sym *asm_label_find(int v)
|
||||
static Sym *asm_label_find(TCCState *s1, int v)
|
||||
{
|
||||
Sym *sym;
|
||||
int addeddot;
|
||||
v = asm2cname(v, &addeddot);
|
||||
v = asm2cname(s1, v, &addeddot);
|
||||
sym = sym_find(v);
|
||||
while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC))
|
||||
sym = sym->prev_tok;
|
||||
return sym;
|
||||
}
|
||||
|
||||
static Sym *asm_label_push(int v)
|
||||
static Sym *asm_label_push(TCCState *s1, int v)
|
||||
{
|
||||
int addeddot, v2 = asm2cname(v, &addeddot);
|
||||
int addeddot, v2 = asm2cname(s1, v, &addeddot);
|
||||
/* We always add VT_EXTERN, for sym definition that's tentative
|
||||
(for .set, removed for real defs), for mere references it's correct
|
||||
as is. */
|
||||
|
@ -106,11 +113,11 @@ static Sym *asm_label_push(int v)
|
|||
are anonymous in C, in this case CSYM can be used to transfer
|
||||
all information from that symbol to the (possibly newly created)
|
||||
asm symbol. */
|
||||
Sym* get_asm_sym(int name, Sym *csym)
|
||||
Sym* get_asm_sym(TCCState *s1, int name, Sym *csym)
|
||||
{
|
||||
Sym *sym = asm_label_find(name);
|
||||
Sym *sym = asm_label_find(s1, name);
|
||||
if (!sym) {
|
||||
sym = asm_label_push(name);
|
||||
sym = asm_label_push(s1, name);
|
||||
if (csym)
|
||||
sym->c = csym->c;
|
||||
}
|
||||
|
@ -122,7 +129,7 @@ static Sym* asm_section_sym(TCCState *s1, Section *sec)
|
|||
char buf[100]; int label; Sym *sym;
|
||||
snprintf(buf, sizeof buf, "L.%s", sec->old_name);
|
||||
label = tok_alloc_const(buf);
|
||||
sym = asm_label_find(label);
|
||||
sym = asm_label_find(s1, label);
|
||||
return sym ? sym : asm_new_label1(s1, label, 1, sec->sh_num, 0);
|
||||
}
|
||||
|
||||
|
@ -143,7 +150,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
|||
if (*p == 'b' || *p == 'f') {
|
||||
/* backward or forward label */
|
||||
label = asm_get_local_label_name(s1, n);
|
||||
sym = asm_label_find(label);
|
||||
sym = asm_label_find(s1, label);
|
||||
if (*p == 'b') {
|
||||
/* backward : find the last corresponding defined label */
|
||||
if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF))
|
||||
|
@ -154,7 +161,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
|||
/* forward */
|
||||
if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
|
||||
/* if the last label is defined, then define a new one */
|
||||
sym = asm_label_push(label);
|
||||
sym = asm_label_push(s1, label);
|
||||
}
|
||||
}
|
||||
pe->v = 0;
|
||||
|
@ -199,7 +206,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
|||
break;
|
||||
case '.':
|
||||
pe->v = ind;
|
||||
pe->sym = asm_section_sym(s1, tcc_state->cur_text_section);
|
||||
pe->sym = asm_section_sym(s1, s1->cur_text_section);
|
||||
pe->pcrel = 0;
|
||||
next();
|
||||
break;
|
||||
|
@ -207,7 +214,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
|
|||
if (tok >= TOK_IDENT) {
|
||||
ElfSym *esym;
|
||||
/* label case : if the label was not found, add one */
|
||||
sym = get_asm_sym(tok, NULL);
|
||||
sym = get_asm_sym(s1, tok, NULL);
|
||||
esym = elfsym(sym);
|
||||
if (esym && esym->st_shndx == SHN_ABS) {
|
||||
/* if absolute symbol, no need to put a symbol value */
|
||||
|
@ -336,7 +343,7 @@ static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
|
|||
/* we also accept defined symbols in the same section */
|
||||
pe->v += esym1->st_value - esym2->st_value;
|
||||
pe->sym = NULL;
|
||||
} else if (esym2->st_shndx == tcc_state->cur_text_section->sh_num) {
|
||||
} else if (esym2->st_shndx == s1->cur_text_section->sh_num) {
|
||||
/* When subtracting a defined symbol in current section
|
||||
this actually makes the value PC-relative. */
|
||||
pe->v += 0 - esym2->st_value;
|
||||
|
@ -413,7 +420,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
|
|||
Sym *sym;
|
||||
ElfSym *esym;
|
||||
|
||||
sym = asm_label_find(label);
|
||||
sym = asm_label_find(s1, label);
|
||||
if (sym) {
|
||||
esym = elfsym(sym);
|
||||
/* A VT_EXTERN symbol, even if it has a section is considered
|
||||
|
@ -430,7 +437,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
|
|||
}
|
||||
} else {
|
||||
new_label:
|
||||
sym = asm_label_push(label);
|
||||
sym = asm_label_push(s1, label);
|
||||
}
|
||||
if (!sym->c)
|
||||
put_extern_sym2(sym, SHN_UNDEF, 0, 0, 1);
|
||||
|
@ -444,7 +451,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
|
|||
|
||||
static Sym* asm_new_label(TCCState *s1, int label, int is_local)
|
||||
{
|
||||
return asm_new_label1(s1, label, is_local, tcc_state->cur_text_section->sh_num, ind);
|
||||
return asm_new_label1(s1, label, is_local, s1->cur_text_section->sh_num, ind);
|
||||
}
|
||||
|
||||
/* Set the value of LABEL to that of some expression (possibly
|
||||
|
@ -468,9 +475,9 @@ static Sym* set_symbol(TCCState *s1, int label)
|
|||
|
||||
static void use_section1(TCCState *s1, Section *sec)
|
||||
{
|
||||
tcc_state->cur_text_section->data_offset = ind;
|
||||
tcc_state->cur_text_section = sec;
|
||||
ind = tcc_state->cur_text_section->data_offset;
|
||||
s1->cur_text_section->data_offset = ind;
|
||||
s1->cur_text_section = sec;
|
||||
ind = s1->cur_text_section->data_offset;
|
||||
}
|
||||
|
||||
static void use_section(TCCState *s1, const char *name)
|
||||
|
@ -483,16 +490,16 @@ static void use_section(TCCState *s1, const char *name)
|
|||
static void push_section(TCCState *s1, const char *name)
|
||||
{
|
||||
Section *sec = find_section(s1, name);
|
||||
sec->prev = tcc_state->cur_text_section;
|
||||
sec->prev = s1->cur_text_section;
|
||||
use_section1(s1, sec);
|
||||
}
|
||||
|
||||
static void pop_section(TCCState *s1)
|
||||
{
|
||||
Section *prev = tcc_state->cur_text_section->prev;
|
||||
Section *prev = s1->cur_text_section->prev;
|
||||
if (!prev)
|
||||
tcc_error(".popsection without .pushsection");
|
||||
tcc_state->cur_text_section->prev = NULL;
|
||||
s1->cur_text_section->prev = NULL;
|
||||
use_section1(s1, prev);
|
||||
}
|
||||
|
||||
|
@ -503,7 +510,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||
uint8_t *ptr;
|
||||
|
||||
/* assembler directive */
|
||||
sec = tcc_state->cur_text_section;
|
||||
sec = s1->cur_text_section;
|
||||
switch(tok) {
|
||||
case TOK_ASMDIR_align:
|
||||
case TOK_ASMDIR_balign:
|
||||
|
@ -682,7 +689,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||
n = e.v;
|
||||
esym = elfsym(e.sym);
|
||||
if (esym) {
|
||||
if (esym->st_shndx != tcc_state->cur_text_section->sh_num)
|
||||
if (esym->st_shndx != s1->cur_text_section->sh_num)
|
||||
expect("constant or same-section symbol");
|
||||
n += esym->st_value;
|
||||
}
|
||||
|
@ -710,7 +717,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||
do {
|
||||
Sym *sym;
|
||||
next();
|
||||
sym = get_asm_sym(tok, NULL);
|
||||
sym = get_asm_sym(s1, tok, NULL);
|
||||
if (tok1 != TOK_ASMDIR_hidden)
|
||||
sym->type.t &= ~VT_STATIC;
|
||||
if (tok1 == TOK_ASMDIR_weak)
|
||||
|
@ -806,7 +813,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||
Sym *sym;
|
||||
|
||||
next();
|
||||
sym = asm_label_find(tok);
|
||||
sym = asm_label_find(s1, tok);
|
||||
if (!sym) {
|
||||
tcc_error("label not found: %s", get_tok_str(tok, NULL));
|
||||
}
|
||||
|
@ -826,7 +833,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||
int st_type;
|
||||
|
||||
next();
|
||||
sym = get_asm_sym(tok, NULL);
|
||||
sym = get_asm_sym(s1, tok, NULL);
|
||||
next();
|
||||
skip(',');
|
||||
if (tok == TOK_STR) {
|
||||
|
@ -894,7 +901,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||
next();
|
||||
}
|
||||
}
|
||||
last_text_section = tcc_state->cur_text_section;
|
||||
last_text_section = s1->cur_text_section;
|
||||
if (tok1 == TOK_ASMDIR_section)
|
||||
use_section(s1, sname);
|
||||
else
|
||||
|
@ -903,8 +910,8 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||
1. new_section normally acts for GCC compatibility and
|
||||
sets alignment to PTR_SIZE. The assembler behaves different. */
|
||||
if (old_nb_section != s1->nb_sections) {
|
||||
tcc_state->cur_text_section->sh_addralign = 1;
|
||||
tcc_state->cur_text_section->sh_flags = flags;
|
||||
s1->cur_text_section->sh_addralign = 1;
|
||||
s1->cur_text_section->sh_flags = flags;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -914,7 +921,7 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||
next();
|
||||
if (!last_text_section)
|
||||
tcc_error("no previous section referenced");
|
||||
sec = tcc_state->cur_text_section;
|
||||
sec = s1->cur_text_section;
|
||||
use_section1(s1, last_text_section);
|
||||
last_text_section = sec;
|
||||
}
|
||||
|
@ -926,13 +933,11 @@ static void asm_parse_directive(TCCState *s1, int global)
|
|||
case TOK_ASMDIR_code16:
|
||||
{
|
||||
next();
|
||||
s1->seg_size = 16;
|
||||
}
|
||||
break;
|
||||
case TOK_ASMDIR_code32:
|
||||
{
|
||||
next();
|
||||
s1->seg_size = 32;
|
||||
}
|
||||
break;
|
||||
/* TODO: Implement symvar support. FreeBSD >= 14 needs this */
|
||||
|
@ -1015,11 +1020,11 @@ int tcc_assemble(TCCState *s1, int do_preprocess)
|
|||
{
|
||||
int ret;
|
||||
/* default section is text */
|
||||
tcc_state->cur_text_section = tcc_state->text_section;
|
||||
ind = tcc_state->cur_text_section->data_offset;
|
||||
s1->cur_text_section = s1->text_section;
|
||||
ind = s1->cur_text_section->data_offset;
|
||||
nocode_wanted = 0;
|
||||
ret = tcc_assemble_internal(s1, do_preprocess, 1);
|
||||
tcc_state->cur_text_section->data_offset = ind;
|
||||
s1->cur_text_section->data_offset = ind;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1187,7 +1192,7 @@ static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
|
|||
}
|
||||
|
||||
/* parse the GCC asm() instruction */
|
||||
void asm_instr(void)
|
||||
void asm_instr(TCCState *s1)
|
||||
{
|
||||
CString astr, *astr1;
|
||||
|
||||
|
@ -1262,11 +1267,11 @@ void asm_instr(void)
|
|||
csym->r = LABEL_FORWARD;
|
||||
}
|
||||
next();
|
||||
asmname = asm_get_prefix_name(tcc_state, "LG.",
|
||||
asmname = asm_get_prefix_name(s1, "LG.",
|
||||
++asmgoto_n);
|
||||
if (!csym->c)
|
||||
put_extern_sym2(csym, SHN_UNDEF, 0, 0, 1);
|
||||
get_asm_sym(asmname, csym);
|
||||
get_asm_sym(s1, asmname, csym);
|
||||
operands[nb_operands + nb_labels - 1].is_label = asmname;
|
||||
|
||||
if (tok != ',')
|
||||
|
@ -1312,13 +1317,13 @@ void asm_instr(void)
|
|||
|
||||
/* We don't allow switching section within inline asm to
|
||||
bleed out to surrounding code. */
|
||||
sec = tcc_state->cur_text_section;
|
||||
sec = s1->cur_text_section;
|
||||
/* assemble the string with tcc internal assembler */
|
||||
tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 0);
|
||||
tcc_assemble_inline(s1, astr.data, astr.size - 1, 0);
|
||||
cstr_free_s(&astr);
|
||||
if (sec != tcc_state->cur_text_section) {
|
||||
if (sec != s1->cur_text_section) {
|
||||
tcc_warning("inline asm tries to change current section");
|
||||
use_section1(tcc_state, sec);
|
||||
use_section1(s1, sec);
|
||||
}
|
||||
|
||||
/* restore the current C token */
|
||||
|
@ -1335,7 +1340,7 @@ void asm_instr(void)
|
|||
|
||||
}
|
||||
|
||||
void asm_global_instr(void)
|
||||
void asm_global_instr(TCCState *s1)
|
||||
{
|
||||
CString *astr;
|
||||
int saved_nocode_wanted = nocode_wanted;
|
||||
|
@ -1353,13 +1358,13 @@ void asm_global_instr(void)
|
|||
#ifdef ASM_DEBUG
|
||||
printf("asm_global: \"%s\"\n", (char *)astr->data);
|
||||
#endif
|
||||
tcc_state->cur_text_section = tcc_state->text_section;
|
||||
ind = tcc_state->cur_text_section->data_offset;
|
||||
s1->cur_text_section = s1->text_section;
|
||||
ind = s1->cur_text_section->data_offset;
|
||||
|
||||
/* assemble the string with tcc internal assembler */
|
||||
tcc_assemble_inline(tcc_state, astr->data, astr->size - 1, 1);
|
||||
tcc_assemble_inline(s1, astr->data, astr->size - 1, 1);
|
||||
|
||||
tcc_state->cur_text_section->data_offset = ind;
|
||||
s1->cur_text_section->data_offset = ind;
|
||||
|
||||
/* restore the current C token */
|
||||
next();
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
#define USING_GLOBALS
|
||||
#include <tcc.h>
|
||||
#define USING_GLOBALS
|
||||
#include "cc/cc.h"
|
||||
#include <tcc/memory.h>
|
||||
#include "utils/string.h"
|
||||
#include "token.h"
|
||||
|
@ -408,7 +410,7 @@ ElfSym *elfsym(Sym *s)
|
|||
{
|
||||
if (!s || !s->c)
|
||||
return NULL;
|
||||
return &((ElfSym *)symtab_section->data)[s->c];
|
||||
return &((ElfSym *)tcc_state->symtab_section->data)[s->c];
|
||||
}
|
||||
|
||||
/* apply storage attributes to Elf symbol */
|
||||
|
@ -435,23 +437,6 @@ void update_storage(Sym *sym)
|
|||
if (sym_bind != old_sym_bind) {
|
||||
esym->st_info = ELFW(ST_INFO)(sym_bind, ELFW(ST_TYPE)(esym->st_info));
|
||||
}
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (sym->a.dllimport)
|
||||
esym->st_other |= ST_PE_IMPORT;
|
||||
if (sym->a.dllexport)
|
||||
esym->st_other |= ST_PE_EXPORT;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
printf("storage %s: bind=%c vis=%d exp=%d imp=%d\n",
|
||||
get_tok_str(sym->v, NULL),
|
||||
sym_bind == STB_WEAK ? 'w' : sym_bind == STB_LOCAL ? 'l' : 'g',
|
||||
sym->a.visibility,
|
||||
sym->a.dllexport,
|
||||
sym->a.dllimport
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -512,7 +497,7 @@ void put_extern_sym2(Sym *sym, int sh_num,
|
|||
}
|
||||
|
||||
info = ELFW(ST_INFO)(sym_bind, sym_type);
|
||||
sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
|
||||
sym->c = put_elf_sym(tcc_state->symtab_section, value, size, info, other, sh_num, name);
|
||||
|
||||
} else {
|
||||
esym = elfsym(sym);
|
||||
|
@ -546,7 +531,7 @@ void greloca(Section *s, Sym *sym, unsigned long offset, int type,
|
|||
}
|
||||
|
||||
/* now we can add ELF relocation info */
|
||||
put_elf_reloca(symtab_section, s, offset, type, c, addend);
|
||||
put_elf_reloca(tcc_state->symtab_section, s, offset, type, c, addend);
|
||||
}
|
||||
|
||||
#if PTR_SIZE == 4
|
||||
|
@ -5186,7 +5171,7 @@ void unary(void)
|
|||
t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG | VT_UNSIGNED;
|
||||
goto push_tokc;
|
||||
case TOK___FUNCTION__:
|
||||
if (!gnu_ext)
|
||||
if (!tcc_state->gnu_ext)
|
||||
goto tok_identifier;
|
||||
/* fall thru */
|
||||
case TOK___FUNC__:
|
||||
|
@ -5462,7 +5447,7 @@ void unary(void)
|
|||
}
|
||||
break;
|
||||
case TOK_LAND:
|
||||
if (!gnu_ext)
|
||||
if (!tcc_state->gnu_ext)
|
||||
goto tok_identifier;
|
||||
next();
|
||||
/* allow to take the address of a label */
|
||||
|
@ -5598,13 +5583,6 @@ special_math_val:
|
|||
|
||||
if (r & VT_SYM) {
|
||||
vtop->c.i = 0;
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (s->a.dllimport) {
|
||||
mk_pointer(&vtop->type);
|
||||
vtop->r |= VT_LVAL;
|
||||
indir();
|
||||
}
|
||||
#endif
|
||||
} else if (r == VT_CONST && IS_ENUM_VAL(s->type.t)) {
|
||||
vtop->c.i = s->enum_val;
|
||||
}
|
||||
|
@ -6035,7 +6013,7 @@ static void expr_cond(void)
|
|||
if (tok == '?') {
|
||||
next();
|
||||
c = condition_3way();
|
||||
g = (tok == ':' && gnu_ext);
|
||||
g = (tok == ':' && tcc_state->gnu_ext);
|
||||
tt = 0;
|
||||
if (!g) {
|
||||
if (c < 0) {
|
||||
|
@ -6776,7 +6754,7 @@ again:
|
|||
dynarray_add(&cur_switch->p, &cur_switch->n, cr);
|
||||
t = cur_switch->sv.type.t;
|
||||
cr->v1 = cr->v2 = value64(expr_const64(), t);
|
||||
if (tok == TOK_DOTS && gnu_ext) {
|
||||
if (tok == TOK_DOTS && tcc_state->gnu_ext) {
|
||||
next();
|
||||
cr->v2 = value64(expr_const64(), t);
|
||||
if (case_cmp(cr->v2, cr->v1) < 0)
|
||||
|
@ -6800,7 +6778,7 @@ again:
|
|||
|
||||
} else if (t == TOK_GOTO) {
|
||||
vla_restore(cur_scope->vla.locorig);
|
||||
if (tok == '*' && gnu_ext) {
|
||||
if (tok == '*' && tcc_state->gnu_ext) {
|
||||
/* computed goto */
|
||||
next();
|
||||
gexpr();
|
||||
|
@ -6837,7 +6815,7 @@ again:
|
|||
skip(';');
|
||||
|
||||
} else if (t == TOK_ASM1 || t == TOK_ASM2 || t == TOK_ASM3) {
|
||||
asm_instr();
|
||||
asm_instr(tcc_state);
|
||||
|
||||
} else {
|
||||
if (tok == ':' && t >= TOK_UIDENT) {
|
||||
|
@ -6954,11 +6932,7 @@ static void parse_init_elem(int expr_type)
|
|||
(compound literals). */
|
||||
if (((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST
|
||||
&& ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL)
|
||||
|| vtop->sym->v < SYM_FIRST_ANOM))
|
||||
#ifdef TCC_TARGET_PE
|
||||
|| ((vtop->r & VT_SYM) && vtop->sym->a.dllimport)
|
||||
#endif
|
||||
)
|
||||
|| vtop->sym->v < SYM_FIRST_ANOM)))
|
||||
tcc_error("initializer element is not constant");
|
||||
break;
|
||||
case EXPR_ANY:
|
||||
|
@ -7047,7 +7021,7 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
|
|||
if (flags & DIF_HAVE_ELEM)
|
||||
goto no_designator;
|
||||
|
||||
if (gnu_ext && tok >= TOK_UIDENT) {
|
||||
if (tcc_state->gnu_ext && tok >= TOK_UIDENT) {
|
||||
l = tok, next();
|
||||
if (tok == ':')
|
||||
goto struct_field;
|
||||
|
@ -7061,7 +7035,7 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
|
|||
expect("array type");
|
||||
next();
|
||||
index = index_last = expr_const();
|
||||
if (tok == TOK_DOTS && gnu_ext) {
|
||||
if (tok == TOK_DOTS && tcc_state->gnu_ext) {
|
||||
next();
|
||||
index_last = expr_const();
|
||||
}
|
||||
|
@ -7093,7 +7067,7 @@ static int decl_designator(init_params *p, CType *type, unsigned long c,
|
|||
if (!cur_field) {
|
||||
if (tok == '=') {
|
||||
next();
|
||||
} else if (!gnu_ext) {
|
||||
} else if (!tcc_state->gnu_ext) {
|
||||
expect("=");
|
||||
}
|
||||
} else {
|
||||
|
@ -7234,7 +7208,7 @@ static void init_putv(init_params *p, CType *type, unsigned long c)
|
|||
continue;
|
||||
if (rel->r_offset < esym->st_value)
|
||||
break;
|
||||
put_elf_reloca(symtab_section, sec,
|
||||
put_elf_reloca(tcc_state->symtab_section, sec,
|
||||
c + rel->r_offset - esym->st_value,
|
||||
ELFW(R_TYPE)(rel->r_info),
|
||||
ELFW(R_SYM)(rel->r_info),
|
||||
|
@ -7728,17 +7702,11 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
|
|||
sec = tcc_state->rodata_section;
|
||||
} else if (has_init) {
|
||||
sec = tcc_state->data_section;
|
||||
} else if (tcc_state->nocommon)
|
||||
} else {
|
||||
sec = tcc_state->bss_section;
|
||||
}
|
||||
|
||||
if (sec) {
|
||||
addr = section_add(sec, size, align);
|
||||
|
||||
} else {
|
||||
addr = align; /* SHN_COMMON is special, symbol value is align */
|
||||
sec = common_section;
|
||||
}
|
||||
addr = section_add(sec, size, align);
|
||||
|
||||
if (v) {
|
||||
if (!sym) {
|
||||
|
@ -7997,7 +7965,7 @@ static int decl(int l)
|
|||
break;
|
||||
if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
|
||||
/* global asm block */
|
||||
asm_global_instr();
|
||||
asm_global_instr(tcc_state);
|
||||
continue;
|
||||
}
|
||||
if (tok >= TOK_UIDENT) {
|
||||
|
@ -8063,34 +8031,12 @@ static int decl(int l)
|
|||
tcc_warning("type defaults to int");
|
||||
}
|
||||
|
||||
if (gnu_ext && (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
|
||||
if (tcc_state->gnu_ext && (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
|
||||
ad.asm_label = asm_label_instr();
|
||||
/* parse one last attribute list, after asm label */
|
||||
parse_attribute(&ad);
|
||||
#if 0
|
||||
/* gcc does not allow __asm__("label") with function definition,
|
||||
but why not ... */
|
||||
if (tok == '{')
|
||||
expect(";");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TCC_TARGET_PE
|
||||
if (ad.a.dllimport || ad.a.dllexport) {
|
||||
if (type.t & VT_STATIC)
|
||||
tcc_error("cannot have dll linkage with static");
|
||||
if (type.t & VT_TYPEDEF) {
|
||||
tcc_warning("'%s' attribute ignored for typedef",
|
||||
ad.a.dllimport ? (ad.a.dllimport = 0, "dllimport") :
|
||||
(ad.a.dllexport = 0, "dllexport"));
|
||||
} else if (ad.a.dllimport) {
|
||||
if ((type.t & VT_BTYPE) == VT_FUNC)
|
||||
ad.a.dllimport = 0;
|
||||
else
|
||||
type.t |= VT_EXTERN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (tok == '{') {
|
||||
if (l != VT_CONST)
|
||||
tcc_error("cannot use local functions");
|
|
@ -23,9 +23,12 @@
|
|||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define USING_GLOBALS
|
||||
#include <tcc.h>
|
||||
#define USING_GLOBALS
|
||||
#include "cc/cc.h"
|
||||
#include <tcc/path.h>
|
||||
#include <tcc/memory.h>
|
||||
#include "utils/string.h"
|
||||
|
@ -1555,7 +1558,7 @@ void parse_define(void)
|
|||
if (varg == TOK_DOTS) {
|
||||
varg = TOK___VA_ARGS__;
|
||||
is_vaargs = 1;
|
||||
} else if (tok == TOK_DOTS && gnu_ext) {
|
||||
} else if (tok == TOK_DOTS && tcc_state->gnu_ext) {
|
||||
is_vaargs = 1;
|
||||
next_nomacro();
|
||||
}
|
||||
|
@ -2066,7 +2069,7 @@ static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long
|
|||
c = '\v';
|
||||
break;
|
||||
case 'e':
|
||||
if (!gnu_ext)
|
||||
if (!tcc_state->gnu_ext)
|
||||
goto invalid_escape;
|
||||
c = 27;
|
||||
break;
|
||||
|
@ -2357,7 +2360,7 @@ static void parse_number(const char *p)
|
|||
/* XXX: should patch directly float number */
|
||||
d = (double)bn[1] * 4294967296.0 + (double)bn[0];
|
||||
d = ldexp(d, exp_val - frac_bits);
|
||||
t = toup(ch);
|
||||
t = toupper(ch);
|
||||
if (t == 'F') {
|
||||
ch = *p++;
|
||||
tok = TOK_CFLOAT;
|
||||
|
@ -2412,7 +2415,7 @@ static void parse_number(const char *p)
|
|||
}
|
||||
}
|
||||
*q = '\0';
|
||||
t = toup(ch);
|
||||
t = toupper(ch);
|
||||
errno = 0;
|
||||
if (t == 'F') {
|
||||
ch = *p++;
|
||||
|
@ -2469,7 +2472,7 @@ static void parse_number(const char *p)
|
|||
lcount = ucount = 0;
|
||||
p1 = p;
|
||||
for(;;) {
|
||||
t = toup(ch);
|
||||
t = toupper(ch);
|
||||
if (t == 'L') {
|
||||
if (lcount >= 2)
|
||||
tcc_error("three 'l's in integer constant");
|
||||
|
@ -2737,7 +2740,7 @@ maybe_newline:
|
|||
&& !(parse_flags & PARSE_FLAG_ASM_FILE
|
||||
/* 0xe+1 is 3 tokens in asm */
|
||||
&& ((char*)tokcstr.data)[0] == '0'
|
||||
&& toup(((char*)tokcstr.data)[1]) == 'X'))
|
||||
&& toupper(((char*)tokcstr.data)[1]) == 'X'))
|
||||
|| t == 'p' || t == 'P'))))
|
||||
break;
|
||||
t = c;
|
||||
|
@ -3036,7 +3039,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
|||
if (t2 == TOK_PPJOIN || t1 == TOK_PPJOIN) {
|
||||
/* special case for var arg macros : ## eats the ','
|
||||
if empty VA_ARGS variable. */
|
||||
if (t1 == TOK_PPJOIN && t0 == ',' && gnu_ext && s->type.t) {
|
||||
if (t1 == TOK_PPJOIN && t0 == ',' && tcc_state->gnu_ext && s->type.t) {
|
||||
int c = str.str[str.len - 1];
|
||||
while (str.str[--str.len] != ',')
|
||||
;
|
||||
|
@ -3305,7 +3308,7 @@ static int macro_subst_tok(
|
|||
break;
|
||||
/* special case for gcc var args: add an empty
|
||||
var arg argument if it is omitted */
|
||||
if (sa->type.t && gnu_ext)
|
||||
if (sa->type.t && tcc_state->gnu_ext)
|
||||
goto empty_arg;
|
||||
tcc_error("macro '%s' used with too few args",
|
||||
get_tok_str(v, 0));
|
||||
|
@ -3554,8 +3557,6 @@ static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
|
|||
putdef(cs, "__ASSEMBLER__");
|
||||
if (s1->output_type == TCC_OUTPUT_PREPROCESS)
|
||||
putdef(cs, "__TCC_PP__");
|
||||
if (s1->output_type == TCC_OUTPUT_MEMORY)
|
||||
putdef(cs, "__TCC_RUN__");
|
||||
if (s1->char_is_unsigned)
|
||||
putdef(cs, "__CHAR_UNSIGNED__");
|
||||
if (s1->optimize > 0)
|
||||
|
@ -3832,7 +3833,7 @@ static int pp_need_space(int a, int b)
|
|||
/* maybe hex like 0x1e */
|
||||
static int pp_check_he0xE(int t, const char *p)
|
||||
{
|
||||
if (t == TOK_PPNUM && toup(strchr(p, 0)[-1]) == 'E')
|
||||
if (t == TOK_PPNUM && toupper(strchr(p, 0)[-1]) == 'E')
|
||||
return 'E';
|
||||
return t;
|
||||
}
|
|
@ -81,14 +81,6 @@ void tcc_undefine_symbol(TCCState *s, const char *sym);
|
|||
*/
|
||||
int tcc_add_file(TCCState *s, const char *filename);
|
||||
|
||||
/**
|
||||
* @brief compile a string containing a C source. Return -1 if error.
|
||||
*
|
||||
* Tip: to have more specific errors/warnings from tcc_compile_string(),
|
||||
* you can prefix the string with "#line <num> \"<filename>\"\n"
|
||||
*/
|
||||
int tcc_compile_string(TCCState *s, const char *buf);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
@ -97,7 +89,6 @@ int tcc_compile_string(TCCState *s, const char *buf);
|
|||
* @defgroup linking Linking commands
|
||||
* @{
|
||||
*/
|
||||
# define TCC_OUTPUT_MEMORY 1 /** output will be run in memory */
|
||||
# define TCC_OUTPUT_EXE 2 /** executable file */
|
||||
# define TCC_OUTPUT_OBJ 3 /** object file */
|
||||
# define TCC_OUTPUT_PREPROCESS 5 /** only preprocess */
|
||||
|
@ -117,35 +108,11 @@ int tcc_add_library_path(TCCState *s, const char *pathname);
|
|||
*/
|
||||
int tcc_add_library(TCCState *s, const char *libraryname);
|
||||
|
||||
/**
|
||||
* @brief add a symbol to the compiled program.
|
||||
*/
|
||||
int tcc_add_symbol(TCCState *s, const char *name, const void *val);
|
||||
|
||||
/**
|
||||
* @brief output an executable, library or object file.
|
||||
*
|
||||
* DO NOT call tcc_relocate() before.
|
||||
*/
|
||||
int tcc_output_file(TCCState *s, const char *filename);
|
||||
|
||||
/**
|
||||
* @brief do all relocations (needed before using tcc_get_symbol()).
|
||||
*/
|
||||
int tcc_relocate(TCCState *s1);
|
||||
|
||||
/**
|
||||
* @brief return symbol value or NULL if not found.
|
||||
*/
|
||||
void *tcc_get_symbol(TCCState *s, const char *name);
|
||||
|
||||
typedef void (TCCSymbolFunc)(void *ctx, const char *name, const void *val);
|
||||
|
||||
/**
|
||||
* @brief list all (global) symbols and their values via 'symbol_cb()'.
|
||||
*/
|
||||
void tcc_list_symbols(TCCState *s, void *ctx, TCCSymbolFunc *symbol_cb);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -57,12 +57,6 @@ extern long double strtold (const char *__nptr, char **__endptr);
|
|||
#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
#ifdef CONFIG_TCC_PIE
|
||||
# define CONFIG_TCC_PIC 1
|
||||
#endif
|
||||
|
||||
/* ------------ path configuration ------------ */
|
||||
|
||||
#ifndef CONFIG_SYSROOT
|
||||
|
@ -348,28 +342,7 @@ typedef struct Section {
|
|||
#define TYPE_PARAM 4 /* type declares function parameter */
|
||||
#define TYPE_NEST 8 /* nested call to post_type */
|
||||
|
||||
#define IO_BUF_SIZE 8192
|
||||
|
||||
typedef struct BufferedFile {
|
||||
uint8_t *buf_ptr;
|
||||
uint8_t *buf_end;
|
||||
int fd;
|
||||
struct BufferedFile *prev;
|
||||
int line_num; /* current line number - here to simplify code */
|
||||
int line_ref; /* tcc -E: last printed line */
|
||||
int ifndef_macro; /* #ifndef macro / #endif search */
|
||||
int ifndef_macro_saved; /* saved ifndef_macro */
|
||||
int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
|
||||
int include_next_index; /* next search path */
|
||||
int prev_tok_flags; /* saved tok_flags */
|
||||
char filename[1024]; /* filename */
|
||||
char *true_filename; /* filename not modified by # line directive */
|
||||
unsigned char unget[4];
|
||||
unsigned char buffer[1]; /* extra size for CH_EOB char */
|
||||
} BufferedFile;
|
||||
|
||||
#define CH_EOB '\\' /* end of buffer or '\0' char in file */
|
||||
#define CH_EOF (-1) /* end of file */
|
||||
#include <tcc/io.h>
|
||||
|
||||
/* used to record tokens */
|
||||
typedef struct TokenString {
|
||||
|
@ -436,24 +409,14 @@ typedef struct ASMOperand {
|
|||
int is_label; /* for asm goto */
|
||||
} ASMOperand;
|
||||
|
||||
/* extra symbol attributes (not in symbol table) */
|
||||
struct sym_attr {
|
||||
unsigned got_offset;
|
||||
unsigned plt_offset;
|
||||
int plt_sym;
|
||||
int dyn_index;
|
||||
};
|
||||
|
||||
struct TCCState {
|
||||
unsigned char verbose; /* if true, display some information during compilation */
|
||||
unsigned char nostdinc; /* if true, no standard headers are added */
|
||||
unsigned char nostdlib; /* if true, no standard libraries are added */
|
||||
unsigned char nocommon; /* if true, do not use common symbols for .bss data */
|
||||
unsigned char symbolic; /* if true, resolve symbols in the current module first */
|
||||
unsigned char filetype; /* file type for compilation (NONE,C,ASM) */
|
||||
unsigned char optimize; /* only to #define __OPTIMIZE__ */
|
||||
unsigned char option_pthread; /* -pthread option */
|
||||
unsigned char enable_new_dtags; /* -Wl,--enable-new-dtags */
|
||||
unsigned int cversion; /* supported C ISO version, 199901 (the default), 201112, ... */
|
||||
|
||||
/* C language options */
|
||||
|
@ -464,7 +427,6 @@ struct TCCState {
|
|||
unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */
|
||||
unsigned char reverse_funcargs; /* if true, evaluate last function arg first */
|
||||
unsigned char gnu89_inline; /* treat 'extern inline' like 'static inline' */
|
||||
unsigned char unwind_tables; /* create eh_frame section */
|
||||
|
||||
/* warning switches */
|
||||
unsigned char warn_none;
|
||||
|
@ -496,10 +458,7 @@ struct TCCState {
|
|||
addr_t text_addr; /* address of text section */
|
||||
unsigned section_align; /* section alignment */
|
||||
|
||||
int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
|
||||
|
||||
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
|
||||
char *rpath; /* as specified on the command line (-Wl,-rpath=) */
|
||||
char *entryname; /* "_start" unless set */
|
||||
|
||||
/* output type, see TCC_OUTPUT_XXX */
|
||||
|
@ -573,47 +532,23 @@ struct TCCState {
|
|||
|
||||
/* predefined sections */
|
||||
Section *text_section, *data_section, *rodata_section, *bss_section;
|
||||
Section *common_section;
|
||||
Section *cur_text_section; /* current section where function code is generated */
|
||||
/* symbol section */
|
||||
union { Section *symtab_section, *symtab; }; /* historical alias */
|
||||
/* exported dynamic symbol section */
|
||||
Section *dynsym;
|
||||
/* got & plt handling */
|
||||
Section *got, *plt;
|
||||
/* exception handling */
|
||||
Section *eh_frame_section;
|
||||
Section *eh_frame_hdr_section;
|
||||
unsigned long eh_start;
|
||||
Section *symtab_section;
|
||||
|
||||
/* Is there a new undefined sym since last new_undef_sym() */
|
||||
int new_undef_sym;
|
||||
/* extra attributes (eg. GOT/PLT value) for symtab symbols */
|
||||
struct sym_attr *sym_attrs;
|
||||
int nb_sym_attrs;
|
||||
|
||||
/* ptr to next reloc entry reused */
|
||||
ElfW_Rel *qrel;
|
||||
#define qrel s1->qrel
|
||||
|
||||
#ifndef ELF_OBJ_ONLY
|
||||
int nb_sym_versions;
|
||||
struct sym_version *sym_versions;
|
||||
int nb_sym_to_version;
|
||||
int *sym_to_version;
|
||||
int dt_verneednum;
|
||||
Section *versym_section;
|
||||
Section *verneed_section;
|
||||
#endif
|
||||
|
||||
/* benchmark info */
|
||||
int total_idents;
|
||||
int total_lines;
|
||||
unsigned int total_bytes;
|
||||
unsigned int total_output[4];
|
||||
|
||||
/* used by tcc_load_ldscript */
|
||||
int fd, cc;
|
||||
|
||||
/* for warnings/errors for object files */
|
||||
const char *current_filename;
|
||||
|
||||
|
@ -772,184 +707,6 @@ char *tcc_load_text(int fd);
|
|||
/* for #pragma once */
|
||||
int normalized_PATHCMP(const char *f1, const char *f2);
|
||||
|
||||
/* ------------ tccpp.c ------------ */
|
||||
|
||||
extern struct BufferedFile *file;
|
||||
extern int tok;
|
||||
extern CValue tokc;
|
||||
extern const int *macro_ptr;
|
||||
extern int parse_flags;
|
||||
extern int tok_flags;
|
||||
extern CString tokcstr; /* current parsed string, if any */
|
||||
|
||||
/* display benchmark infos */
|
||||
extern int tok_ident;
|
||||
extern TokenSym **table_ident;
|
||||
extern int pp_expr;
|
||||
|
||||
#define TOK_FLAG_BOL 0x0001 /* beginning of line before */
|
||||
#define TOK_FLAG_BOF 0x0002 /* beginning of file before */
|
||||
#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
|
||||
|
||||
#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
|
||||
#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
|
||||
#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
|
||||
token. line feed is also
|
||||
returned at eof */
|
||||
#define PARSE_FLAG_ASM_FILE 0x0008 /* we processing an asm file: '#' can be used for line comment, etc. */
|
||||
#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
|
||||
#define PARSE_FLAG_ACCEPT_STRAYS 0x0020 /* next() returns '\\' token */
|
||||
#define PARSE_FLAG_TOK_STR 0x0040 /* return parsed strings instead of TOK_PPSTR */
|
||||
|
||||
/* isidnum_table flags: */
|
||||
#define IS_SPC 1
|
||||
#define IS_ID 2
|
||||
#define IS_NUM 4
|
||||
|
||||
enum line_macro_output_format {
|
||||
LINE_MACRO_OUTPUT_FORMAT_GCC,
|
||||
LINE_MACRO_OUTPUT_FORMAT_NONE,
|
||||
LINE_MACRO_OUTPUT_FORMAT_STD,
|
||||
LINE_MACRO_OUTPUT_FORMAT_P10 = 11
|
||||
};
|
||||
|
||||
TokenSym *tok_alloc(const char *str, int len);
|
||||
int tok_alloc_const(const char *str);
|
||||
const char *get_tok_str(int v, CValue *cv);
|
||||
void begin_macro(TokenString *str, int alloc);
|
||||
void end_macro(void);
|
||||
int set_idnum(int c, int val);
|
||||
void tok_str_new(TokenString *s);
|
||||
TokenString *tok_str_alloc(void);
|
||||
void tok_str_free(TokenString *s);
|
||||
void tok_str_free_str(int *str);
|
||||
void tok_str_add(TokenString *s, int t);
|
||||
void tok_str_add_tok(TokenString *s);
|
||||
void define_push(int v, int macro_type, int *str, Sym *first_arg);
|
||||
void define_undef(Sym *s);
|
||||
Sym *define_find(int v);
|
||||
void free_defines(Sym *b);
|
||||
void parse_define(void);
|
||||
void skip_to_eol(int warn);
|
||||
void preprocess(int is_bof);
|
||||
void next(void);
|
||||
void unget_tok(int last_tok);
|
||||
void preprocess_start(TCCState *s1, int filetype);
|
||||
void preprocess_end(TCCState *s1);
|
||||
void tccpp_new(TCCState *s);
|
||||
void tccpp_delete(TCCState *s);
|
||||
void tccpp_putfile(const char *filename);
|
||||
int tcc_preprocess(TCCState *s1);
|
||||
void skip(int c);
|
||||
__attribute__((noreturn)) void expect(const char *msg);
|
||||
void pp_error(CString *cs);
|
||||
|
||||
|
||||
/* space excluding newline */
|
||||
static inline int is_space(int ch) {
|
||||
return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
|
||||
}
|
||||
static inline int isid(int c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
|
||||
}
|
||||
static inline int isnum(int c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
static inline int isoct(int c) {
|
||||
return c >= '0' && c <= '7';
|
||||
}
|
||||
static inline int toup(int c) {
|
||||
return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
|
||||
}
|
||||
|
||||
/* ------------ tccgen.c ------------ */
|
||||
|
||||
#define SYM_POOL_NB (8192 / sizeof(Sym))
|
||||
|
||||
extern Sym *global_stack;
|
||||
extern Sym *local_stack;
|
||||
extern Sym *local_label_stack;
|
||||
extern Sym *global_label_stack;
|
||||
extern Sym *define_stack;
|
||||
extern CType int_type, func_old_type, char_pointer_type;
|
||||
extern SValue *vtop;
|
||||
extern int rsym, anon_sym, ind, loc;
|
||||
extern char debug_modes;
|
||||
|
||||
extern int nocode_wanted; /* true if no code generation wanted for an expression */
|
||||
extern int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
|
||||
extern CType func_vt; /* current function return type (used by return instruction) */
|
||||
extern int func_var; /* true if current function is variadic */
|
||||
extern int func_vc;
|
||||
extern int func_ind;
|
||||
extern const char *funcname;
|
||||
|
||||
void tccgen_init(TCCState *s1);
|
||||
int tccgen_compile(TCCState *s1);
|
||||
void tccgen_finish(TCCState *s1);
|
||||
void check_vstack(void);
|
||||
|
||||
int is_float(int t);
|
||||
int ieee_finite(double d);
|
||||
int exact_log2p1(int i);
|
||||
void test_lvalue(void);
|
||||
|
||||
ElfSym *elfsym(Sym *);
|
||||
void update_storage(Sym *sym);
|
||||
void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
|
||||
void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
|
||||
#if PTR_SIZE == 4
|
||||
void greloc(Section *s, Sym *sym, unsigned long offset, int type);
|
||||
#endif
|
||||
void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
|
||||
|
||||
void sym_free(Sym *sym);
|
||||
Sym *sym_push(int v, CType *type, int r, int c);
|
||||
void sym_pop(Sym **ptop, Sym *b, int keep);
|
||||
Sym *sym_push2(Sym **ps, int v, int t, int c);
|
||||
Sym *sym_find2(Sym *s, int v);
|
||||
Sym *sym_find(int v);
|
||||
Sym *label_find(int v);
|
||||
Sym *label_push(Sym **ptop, int v, int flags);
|
||||
void label_pop(Sym **ptop, Sym *slast, int keep);
|
||||
Sym *struct_find(int v);
|
||||
|
||||
Sym *global_identifier_push(int v, int t, int c);
|
||||
Sym *external_global_sym(int v, CType *type);
|
||||
Sym *external_helper_sym(int v);
|
||||
void vpush_helper_func(int v);
|
||||
void vset(CType *type, int r, int v);
|
||||
void vset_VT_CMP(int op);
|
||||
void vpushi(int v);
|
||||
void vpushv(SValue *v);
|
||||
void vpushsym(CType *type, Sym *sym);
|
||||
void vswap(void);
|
||||
void vrott(int n);
|
||||
void vrotb(int n);
|
||||
void vrev(int n);
|
||||
void vpop(void);
|
||||
#if PTR_SIZE == 4
|
||||
void lexpand(void);
|
||||
#endif
|
||||
void save_reg(int r);
|
||||
void save_reg_upstack(int r, int n);
|
||||
int get_reg(int rc);
|
||||
void save_regs(int n);
|
||||
void gaddrof(void);
|
||||
int gv(int rc);
|
||||
void gv2(int rc1, int rc2);
|
||||
void gen_op(int op);
|
||||
int type_size(CType *type, int *a);
|
||||
void mk_pointer(CType *type);
|
||||
void vstore(void);
|
||||
void inc(int post, int c);
|
||||
CString* parse_mult_str(const char *msg);
|
||||
CString* parse_asm_str(void);
|
||||
void indir(void);
|
||||
void unary(void);
|
||||
void gexpr(void);
|
||||
int expr_const(void);
|
||||
|
||||
/* ------------ tccelf.c ------------ */
|
||||
|
||||
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
|
||||
|
@ -988,10 +745,7 @@ int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
|
|||
int tcc_load_archive(TCCState *s1, int fd, int alacarte);
|
||||
void add_array(TCCState *s1, const char *sec, int c);
|
||||
|
||||
struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);
|
||||
addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc);
|
||||
void list_elf_symbols(TCCState *s, void *ctx,
|
||||
void (*symbol_cb)(void *ctx, const char *name, const void *val));
|
||||
int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs);
|
||||
|
||||
/* Browse each elem of type <type> in section <sec> starting at elem <startoff>
|
||||
|
@ -1001,7 +755,6 @@ int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs);
|
|||
elem < (type *) (sec->data + sec->data_offset); elem++)
|
||||
|
||||
#ifndef ELF_OBJ_ONLY
|
||||
int tcc_load_ldscript(TCCState *s1, int fd);
|
||||
void tccelf_add_crtbegin(TCCState *s1);
|
||||
void tccelf_add_crtend(TCCState *s1);
|
||||
#endif
|
||||
|
@ -1011,120 +764,7 @@ void tcc_add_runtime(TCCState *s1);
|
|||
|
||||
int coff_load_file(TCCState *s1, int fd, const char *fname);
|
||||
|
||||
/* ------------ xxx-link.c ------------ */
|
||||
|
||||
#if !defined ELF_OBJ_ONLY
|
||||
int code_reloc (int reloc_type);
|
||||
int gotplt_entry_type (int reloc_type);
|
||||
/* Whether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so
|
||||
that unknown relocation don't create a GOT or PLT entry */
|
||||
enum gotplt_entry {
|
||||
NO_GOTPLT_ENTRY, /* never generate (eg. GLOB_DAT & JMP_SLOT relocs) */
|
||||
BUILD_GOT_ONLY, /* only build GOT (eg. TPOFF relocs) */
|
||||
AUTO_GOTPLT_ENTRY, /* generate if sym is UNDEF */
|
||||
ALWAYS_GOTPLT_ENTRY /* always generate (eg. PLTOFF relocs) */
|
||||
};
|
||||
#define NEED_RELOC_TYPE
|
||||
|
||||
unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
|
||||
void relocate_plt(TCCState *s1);
|
||||
void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */
|
||||
#define NEED_BUILD_GOT
|
||||
|
||||
#endif
|
||||
|
||||
void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
|
||||
|
||||
/* ------------ xxx-gen.c ------------ */
|
||||
extern const char * const target_machine_defs;
|
||||
extern const int reg_classes[NB_REGS];
|
||||
|
||||
void gsym_addr(int t, int a);
|
||||
void gsym(int t);
|
||||
void load(int r, SValue *sv);
|
||||
void store(int r, SValue *v);
|
||||
int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
|
||||
void gfunc_call(int nb_args);
|
||||
void gfunc_prolog(Sym *func_sym);
|
||||
void gfunc_epilog(void);
|
||||
void gen_fill_nops(int);
|
||||
int gjmp(int t);
|
||||
void gjmp_addr(int a);
|
||||
int gjmp_cond(int op, int t);
|
||||
int gjmp_append(int n, int t);
|
||||
void gen_opi(int op);
|
||||
void gen_opf(int op);
|
||||
void gen_cvt_ftoi(int t);
|
||||
void gen_cvt_itof(void);
|
||||
void gen_cvt_ftof(void);
|
||||
void ggoto(void);
|
||||
void o(unsigned int c);
|
||||
void gen_vla_sp_save(int addr);
|
||||
void gen_vla_sp_restore(int addr);
|
||||
void gen_vla_alloc(CType *type, int align);
|
||||
|
||||
static inline uint16_t read16le(unsigned char *p) {
|
||||
return p[0] | (uint16_t)p[1] << 8;
|
||||
}
|
||||
static inline void write16le(unsigned char *p, uint16_t x) {
|
||||
p[0] = x & 255; p[1] = x >> 8 & 255;
|
||||
}
|
||||
static inline uint32_t read32le(unsigned char *p) {
|
||||
return read16le(p) | (uint32_t)read16le(p + 2) << 16;
|
||||
}
|
||||
static inline void write32le(unsigned char *p, uint32_t x) {
|
||||
write16le(p, x); write16le(p + 2, x >> 16);
|
||||
}
|
||||
static inline void add32le(unsigned char *p, int32_t x) {
|
||||
write32le(p, read32le(p) + x);
|
||||
}
|
||||
static inline uint64_t read64le(unsigned char *p) {
|
||||
return read32le(p) | (uint64_t)read32le(p + 4) << 32;
|
||||
}
|
||||
static inline void write64le(unsigned char *p, uint64_t x) {
|
||||
write32le(p, x); write32le(p + 4, x >> 32);
|
||||
}
|
||||
static inline void add64le(unsigned char *p, int64_t x) {
|
||||
write64le(p, read64le(p) + x);
|
||||
}
|
||||
|
||||
/* ------------ i386-gen.c ------------ */
|
||||
void g(int c);
|
||||
void gen_le16(int c);
|
||||
void gen_le32(int c);
|
||||
|
||||
void gen_addr32(int r, Sym *sym, int c);
|
||||
void gen_addrpc32(int r, Sym *sym, int c);
|
||||
void gen_cvt_csti(int t);
|
||||
|
||||
/* ------------ tccasm.c ------------ */
|
||||
void asm_instr(void);
|
||||
void asm_global_instr(void);
|
||||
int tcc_assemble(TCCState *s1, int do_preprocess);
|
||||
int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
|
||||
Sym* get_asm_sym(int name, Sym *csym);
|
||||
void asm_expr(TCCState *s1, ExprValue *pe);
|
||||
int asm_int_expr(TCCState *s1);
|
||||
/* ------------ i386-asm.c ------------ */
|
||||
void gen_expr32(ExprValue *pe);
|
||||
void asm_opcode(TCCState *s1, int opcode);
|
||||
int asm_parse_regvar(int t);
|
||||
void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
|
||||
void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
|
||||
void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
|
||||
void asm_clobber(uint8_t *clobber_regs, const char *str);
|
||||
|
||||
#define ST_ASM_SET 0x04
|
||||
|
||||
|
||||
/* ------------ tccdbg.c ------------ */
|
||||
#define eh_frame_hdr_section s1->eh_frame_hdr_section
|
||||
|
||||
#define common_section TCC_STATE_VAR(common_section)
|
||||
#define bounds_section TCC_STATE_VAR(bounds_section)
|
||||
#define lbounds_section TCC_STATE_VAR(lbounds_section)
|
||||
#define symtab_section TCC_STATE_VAR(symtab_section)
|
||||
#define gnu_ext TCC_STATE_VAR(gnu_ext)
|
||||
#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort)
|
||||
#define tcc_error TCC_SET_STATE(_tcc_error)
|
||||
#define tcc_warning TCC_SET_STATE(_tcc_warning)
|
||||
|
|
|
@ -371,7 +371,6 @@ typedef struct
|
|||
#define PT_TLS 7 /* Thread-local storage segment */
|
||||
#define PT_NUM 8 /* Number of defined types */
|
||||
#define PT_LOOS 0x60000000 /* Start of OS-specific */
|
||||
#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
|
||||
#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
|
||||
#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
|
||||
#define PT_LOSUNW 0x6ffffffa
|
||||
|
@ -432,19 +431,6 @@ typedef struct
|
|||
|
||||
#define NT_VERSION 1 /* Contains a version string. */
|
||||
|
||||
|
||||
/* Dynamic section entry. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Sword d_tag; /* Dynamic entry type */
|
||||
union
|
||||
{
|
||||
Elf32_Word d_val; /* Integer value */
|
||||
Elf32_Addr d_ptr; /* Address value */
|
||||
} d_un;
|
||||
} Elf32_Dyn;
|
||||
|
||||
/* Legal values for d_tag (dynamic entry type). */
|
||||
|
||||
#define DT_NULL 0 /* Marks end of dynamic section */
|
||||
|
@ -462,7 +448,6 @@ typedef struct
|
|||
#define DT_INIT 12 /* Address of init function */
|
||||
#define DT_FINI 13 /* Address of termination function */
|
||||
#define DT_SONAME 14 /* Name of shared object */
|
||||
#define DT_RPATH 15 /* Library search path (deprecated) */
|
||||
#define DT_SYMBOLIC 16 /* Start symbol search here */
|
||||
#define DT_REL 17 /* Address of Rel relocs */
|
||||
#define DT_RELSZ 18 /* Total size of Rel relocs */
|
||||
|
@ -837,14 +822,10 @@ typedef struct
|
|||
#define R_386_NONE 0 /* No reloc */
|
||||
#define R_386_32 1 /* Direct 32 bit */
|
||||
#define R_386_PC32 2 /* PC relative 32 bit */
|
||||
#define R_386_GOT32 3 /* 32 bit GOT entry */
|
||||
#define R_386_PLT32 4 /* 32 bit PLT address */
|
||||
#define R_386_COPY 5 /* Copy symbol at runtime */
|
||||
#define R_386_GLOB_DAT 6 /* Create GOT entry */
|
||||
#define R_386_JMP_SLOT 7 /* Create PLT entry */
|
||||
#define R_386_RELATIVE 8 /* Adjust by program base */
|
||||
#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
|
||||
#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
|
||||
#define R_386_32PLT 11
|
||||
#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */
|
||||
#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS
|
||||
|
@ -896,17 +877,5 @@ typedef struct
|
|||
/* Keep this the last entry. */
|
||||
#define R_386_NUM 44
|
||||
|
||||
/* AMD x86-64 relocations. */
|
||||
#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
|
||||
#define R_X86_64_PLT32 4 /* 32 bit PLT address */
|
||||
#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative
|
||||
offset to GOT */
|
||||
#define R_X86_64_GOTPCRELX 41 /* like GOTPCREL, but optionally with
|
||||
linker optimizations */
|
||||
#define R_X86_64_REX_GOTPCRELX 42 /* like GOTPCRELX, but a REX prefix
|
||||
is present */
|
||||
|
||||
/* x86-64 sh_type values. */
|
||||
#define SHT_X86_64_UNWIND 0x70000001 /* Unwind information. */
|
||||
|
||||
#endif /* elf.h */
|
||||
|
|
|
@ -14,7 +14,4 @@
|
|||
# define ELF_START_ADDR 0x08048000
|
||||
# define ELF_PAGE_SIZE 0x1000
|
||||
|
||||
# define PCRELATIVE_DLLPLT 0
|
||||
# define RELOCATE_DLLPLT 1
|
||||
|
||||
#endif /* !TCC_I386_LINK_H */
|
|
@ -17,7 +17,7 @@ typedef struct BufferedFile {
|
|||
int *ifdef_stack_ptr; /** ifdef_stack value at the start of the file */
|
||||
int include_next_index; /** next search path */
|
||||
int prev_tok_flags; /** saved tok_flags */
|
||||
char *filename[1024]; /** filename */
|
||||
char filename[1024]; /** filename */
|
||||
char *true_filename; /** filename not modified by # line directive */
|
||||
unsigned char unget[4];
|
||||
unsigned char buffer[1]; /** extra size for CH_EOB char */
|
||||
|
|
|
@ -71,6 +71,7 @@ typedef struct COFFSectionHeader {
|
|||
# define COFF_STYP_TEXT 0x020
|
||||
# define COFF_STYP_DATA 0x040
|
||||
# define COFF_STYP_BSS 0x080
|
||||
# define COFF_STYP_RODATA 0x100 /** stupidos extension */
|
||||
# define COFF_STYP_INFO 0x200
|
||||
# define COFF_STYP_OVER 0x400
|
||||
# define COFF_STYP_LIB 0x800
|
||||
|
@ -103,6 +104,9 @@ typedef struct COFFSym {
|
|||
int8_t numaux;
|
||||
} COFFSym;
|
||||
|
||||
# define COFF_N_UNDEF 0
|
||||
# define COFF_N_ABS -1
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
# define TCC_OPT_HELP_MORE 'm'
|
||||
# define TCC_OPT_ARCHIVE 'a'
|
||||
# define TCC_OPT_VERSION 'V'
|
||||
# define TCC_OPT_PRINT_DIRS 'P'
|
||||
|
||||
typedef struct TCCOption {
|
||||
const char *name;
|
||||
|
|
|
@ -22,7 +22,7 @@ typedef struct InlineFunc InlineFunc;
|
|||
|
||||
typedef struct TCCStrtab {
|
||||
size_t len;
|
||||
uint8_t *tab;
|
||||
char *tab;
|
||||
} TCCStrtab;
|
||||
|
||||
typedef struct TCCSymtab {
|
||||
|
@ -41,6 +41,8 @@ typedef struct TCCSection {
|
|||
char name[8]; /** section name */
|
||||
int32_t flags;
|
||||
int16_t secnum;
|
||||
int16_t addralign;
|
||||
size_t offset;
|
||||
} TCCSection;
|
||||
|
||||
struct TCCState2 {
|
||||
|
@ -89,8 +91,6 @@ struct TCCState2 {
|
|||
uint32_t text_addr; /** address of text section */
|
||||
unsigned section_align; /** section alignment */
|
||||
|
||||
int seg_size; /** 32. Can be 16 with i386 assembler (.code16) */
|
||||
|
||||
char *tcc_lib_path; /** CONFIG_TCCDIR or -B option */
|
||||
char *entryname; /** "_start" unless set */
|
||||
|
||||
|
@ -161,12 +161,7 @@ struct TCCState2 {
|
|||
TCCSection *cur_text_section; /** current section where function code is generated */
|
||||
|
||||
/* symbol data */
|
||||
TCCSymtab symtab;
|
||||
|
||||
/* exception handling */
|
||||
TCCSection *eh_frame_section;
|
||||
TCCSection *eh_frame_hdr_section;
|
||||
uint32_t eh_start;
|
||||
TCCSymtab *symtab;
|
||||
|
||||
/* benchmark info */
|
||||
int total_idents;
|
||||
|
@ -174,10 +169,6 @@ struct TCCState2 {
|
|||
uint32_t total_bytes;
|
||||
uint32_t total_output[4];
|
||||
|
||||
/* used by tcc_load_ldscript */
|
||||
int fd;
|
||||
int cc;
|
||||
|
||||
/* for warnings/errors for object files */
|
||||
const char *current_filename;
|
||||
};
|
||||
|
|
53
libtcc/io.c
Normal file
53
libtcc/io.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
|
||||
#include "libtcc.h"
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <tcc.h>
|
||||
#include <tcc/memory.h>
|
||||
#include <tcc/io.h>
|
||||
#include "utils/string.h"
|
||||
#include "cc/cc.h"
|
||||
|
||||
void
|
||||
tcc_open_bf(TCCState *s1, const char *filename, int initlen)
|
||||
{
|
||||
BufferedFile *bf;
|
||||
int buflen;
|
||||
|
||||
buflen = initlen ? initlen : IO_BUF_SIZE;
|
||||
bf = tcc_mallocz(sizeof(BufferedFile) + buflen);
|
||||
bf->buf_ptr = bf->buffer;
|
||||
bf->buf_end = bf->buffer + initlen;
|
||||
bf->buf_end[0] = CH_EOB; /* put eob symbol */
|
||||
pstrcpy(bf->filename, sizeof(bf->filename), filename);
|
||||
|
||||
bf->true_filename = bf->filename;
|
||||
bf->line_num = 1;
|
||||
bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
|
||||
bf->fd = -1;
|
||||
bf->prev = file;
|
||||
bf->prev_tok_flags = tok_flags;
|
||||
file = bf;
|
||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||
}
|
||||
|
||||
void tcc_close(void)
|
||||
{
|
||||
TCCState *s1 = tcc_state;
|
||||
BufferedFile *bf = file;
|
||||
|
||||
if (bf->fd > 0)
|
||||
{
|
||||
close(bf->fd);
|
||||
total_lines += bf->line_num - 1;
|
||||
}
|
||||
if (bf->true_filename != bf->filename)
|
||||
{
|
||||
tcc_free(bf->true_filename);
|
||||
}
|
||||
file = bf->prev;
|
||||
tok_flags = bf->prev_tok_flags;
|
||||
tcc_free(bf);
|
||||
}
|
|
@ -29,6 +29,7 @@
|
|||
#include <tcc/memory.h>
|
||||
#include <tcc/object.h>
|
||||
#include "utils/string.h"
|
||||
#include "cc/cc.h"
|
||||
|
||||
/********************************************************/
|
||||
/* global variables */
|
||||
|
@ -64,9 +65,6 @@ char *tcc_load_text(int fd)
|
|||
return buf;
|
||||
}
|
||||
|
||||
/********************************************************/
|
||||
/* memory management */
|
||||
|
||||
#ifdef _WIN32
|
||||
# define realpath(file, buf) _fullpath(buf, file, 260)
|
||||
#endif
|
||||
|
@ -278,42 +276,6 @@ PUB_FUNC void _tcc_warning(const char *fmt, ...)
|
|||
/********************************************************/
|
||||
/* I/O layer */
|
||||
|
||||
void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
|
||||
{
|
||||
BufferedFile *bf;
|
||||
int buflen = initlen ? initlen : IO_BUF_SIZE;
|
||||
|
||||
bf = tcc_mallocz(sizeof(BufferedFile) + buflen);
|
||||
bf->buf_ptr = bf->buffer;
|
||||
bf->buf_end = bf->buffer + initlen;
|
||||
bf->buf_end[0] = CH_EOB; /* put eob symbol */
|
||||
pstrcpy(bf->filename, sizeof(bf->filename), filename);
|
||||
|
||||
bf->true_filename = bf->filename;
|
||||
bf->line_num = 1;
|
||||
bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
|
||||
bf->fd = -1;
|
||||
bf->prev = file;
|
||||
bf->prev_tok_flags = tok_flags;
|
||||
file = bf;
|
||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||
}
|
||||
|
||||
void tcc_close(void)
|
||||
{
|
||||
TCCState *s1 = tcc_state;
|
||||
BufferedFile *bf = file;
|
||||
if (bf->fd > 0) {
|
||||
close(bf->fd);
|
||||
total_lines += bf->line_num - 1;
|
||||
}
|
||||
if (bf->true_filename != bf->filename)
|
||||
tcc_free(bf->true_filename);
|
||||
file = bf->prev;
|
||||
tok_flags = bf->prev_tok_flags;
|
||||
tcc_free(bf);
|
||||
}
|
||||
|
||||
static int _tcc_open(TCCState *s1, const char *filename)
|
||||
{
|
||||
int fd;
|
||||
|
@ -384,11 +346,6 @@ static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd)
|
|||
return s1->nb_errors != 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
int tcc_compile_string(TCCState *s, const char *str)
|
||||
{
|
||||
return tcc_compile(s, s->filetype, str, -1);
|
||||
}
|
||||
|
||||
/* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */
|
||||
void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
|
||||
{
|
||||
|
@ -419,22 +376,16 @@ TCCState *tcc_new(void)
|
|||
#undef gnu_ext
|
||||
s->gnu_ext = 1;
|
||||
s->tcc_ext = 1;
|
||||
s->nocommon = 1;
|
||||
s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/
|
||||
s->cversion = 199901; /* default unless -std=c11 is supplied */
|
||||
s->warn_implicit_function_declaration = 1;
|
||||
s->warn_discarded_qualifiers = 1;
|
||||
s->ms_extensions = 1;
|
||||
s->unwind_tables = 1;
|
||||
|
||||
#ifdef __CHAR_UNSIGNED__
|
||||
s->char_is_unsigned = 1;
|
||||
#endif
|
||||
s->seg_size = 32;
|
||||
|
||||
#ifdef CONFIG_NEW_DTAGS
|
||||
s->enable_new_dtags = 1;
|
||||
#endif
|
||||
s->ppfp = stdout;
|
||||
/* might be used in error() before preprocess_start() */
|
||||
s->include_stack_ptr = s->include_stack;
|
||||
|
@ -457,7 +408,6 @@ void tcc_delete(TCCState *s1)
|
|||
dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
|
||||
|
||||
tcc_free(s1->tcc_lib_path);;
|
||||
tcc_free(s1->rpath);
|
||||
tcc_free(s1->entryname);
|
||||
tcc_free(s1->outfile);
|
||||
tcc_free(s1->deps_outfile);
|
||||
|
@ -501,7 +451,7 @@ int tcc_set_output_type(TCCState *s, int output_type)
|
|||
|
||||
/* paths for crt objects */
|
||||
tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
|
||||
if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib)
|
||||
if (!s->nostdlib)
|
||||
tccelf_add_crtbegin(s);
|
||||
return 0;
|
||||
}
|
||||
|
@ -564,8 +514,6 @@ int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
|
|||
|
||||
default:
|
||||
/* as GNU ld, consider it is an ld script if not recognized */
|
||||
ret = tcc_load_ldscript(s1, fd);
|
||||
if (ret < 0)
|
||||
tcc_error_noabort("%s: unrecognized file type", filename);
|
||||
break;
|
||||
}
|
||||
|
@ -660,6 +608,7 @@ int tcc_add_library(TCCState *s, const char *libraryname)
|
|||
static const char * const libs[] = { "%s/lib%s.a", NULL };
|
||||
const char * const *pp = libs;
|
||||
int flags = s->filetype & AFF_WHOLE_ARCHIVE;
|
||||
|
||||
while (*pp) {
|
||||
int ret = tcc_add_library_internal(s, *pp,
|
||||
libraryname, flags, s->library_paths, s->nb_library_paths);
|
||||
|
@ -678,18 +627,6 @@ void tcc_add_pragma_libs(TCCState *s1)
|
|||
tcc_add_library(s1, s1->pragma_libs[i]);
|
||||
}
|
||||
|
||||
int tcc_add_symbol(TCCState *s1, const char *name, const void *val)
|
||||
{
|
||||
char buf[256];
|
||||
if (s1->leading_underscore) {
|
||||
buf[0] = '_';
|
||||
pstrcpy(buf + 1, sizeof(buf) - 1, name);
|
||||
name = buf;
|
||||
}
|
||||
set_global_sym(s1, name, NULL, (addr_t)(uintptr_t)val); /* NULL: SHN_ABS */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tcc_set_lib_path(TCCState *s, const char *path)
|
||||
{
|
||||
tcc_free(s->tcc_lib_path);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <tcc.h>
|
||||
#include "cc/cc.h"
|
||||
|
||||
#ifdef TCC_MEMORY_DEBUG
|
||||
# undef tcc_free
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <tcc.h>
|
||||
#include <string.h>
|
||||
#include <tcc/state.h>
|
||||
#include <tcc/memory.h>
|
||||
#include <tcc/object.h>
|
||||
#include <tcc/object/archive.h>
|
||||
#include <tcc/object/coff.h>
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
#include "utils/string.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
|
@ -7,6 +10,8 @@
|
|||
#include <tcc/object/coff.h>
|
||||
#include <tcc/state.h>
|
||||
|
||||
#define ALIGN_UP(val, alignment) ((val + alignment - 1) & -alignment)
|
||||
|
||||
#define COFF_DEFAULT_ENTRYNAME "_start"
|
||||
|
||||
void dynarray_add(void *ptab, int *nb_ptr, void *data);
|
||||
|
@ -39,14 +44,6 @@ coff_free_section(TCCSection *s)
|
|||
s->data_allocated = s->data_offset = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
coff_new_symtab(TCCState2 *s1)
|
||||
{
|
||||
TCCSymtab *symtab;
|
||||
|
||||
symtab = tcc_mallocz(sizeof(TCCSymtab));
|
||||
}
|
||||
|
||||
void
|
||||
coff_new(TCCState2 *s1)
|
||||
{
|
||||
|
@ -55,9 +52,12 @@ coff_new(TCCState2 *s1)
|
|||
s1->text_section = coff_new_section(s1, ".text", COFF_STYP_TEXT);
|
||||
s1->data_section = coff_new_section(s1, ".data", COFF_STYP_DATA);
|
||||
s1->bss_section = coff_new_section(s1, ".bss", COFF_STYP_BSS);
|
||||
s1->rodata_section = coff_new_section(s1, ".rodata", COFF_STYP_DATA);
|
||||
s1->rodata_section = coff_new_section(s1, ".rodata", COFF_STYP_RODATA);
|
||||
|
||||
coff_new_symtab(s1);
|
||||
s1->symtab = tcc_mallocz(sizeof(TCCSymtab)); /* create new symtab */
|
||||
/* add dummy symbols */
|
||||
s1->symtab->nsym++;
|
||||
s1->symtab->syms = tcc_mallocz(sizeof(COFFSym));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -71,6 +71,218 @@ coff_delete(TCCState2 *s1)
|
|||
}
|
||||
|
||||
dynarray_reset(&s1->sections, &s1->nb_sections);
|
||||
|
||||
if (s1->symtab != NULL)
|
||||
{
|
||||
tcc_free(s1->symtab->strtab.tab);
|
||||
tcc_free(s1->symtab->syms);
|
||||
tcc_free(s1->symtab);
|
||||
s1->symtab = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
coff_begin_file(TCCState2 *s1)
|
||||
{
|
||||
TCCSection *sec;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++)
|
||||
{
|
||||
sec = s1->sections[i];
|
||||
sec->offset = sec->data_offset;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
coff_section_realloc(TCCSection *sec, size_t new_size)
|
||||
{
|
||||
size_t size;
|
||||
uint8_t *data;
|
||||
|
||||
size = sec->data_allocated;
|
||||
if (size == 0)
|
||||
{
|
||||
size = 1;
|
||||
}
|
||||
|
||||
while (size < new_size)
|
||||
{
|
||||
size = size * 2;
|
||||
}
|
||||
data = tcc_realloc(sec->data, size);
|
||||
memset(data + sec->data_allocated, 0, size - sec->data_allocated);
|
||||
sec->data = data;
|
||||
sec->data_allocated = size;
|
||||
}
|
||||
|
||||
size_t
|
||||
coff_section_add(TCCSection *sec, size_t size, int align)
|
||||
{
|
||||
size_t offset;
|
||||
size_t offset1;
|
||||
|
||||
offset = ALIGN_UP(sec->data_offset, align);
|
||||
offset1 = offset + size;
|
||||
if (sec->flags != COFF_STYP_BSS && offset1 > sec->data_allocated)
|
||||
{
|
||||
coff_section_realloc(sec, offset1);
|
||||
}
|
||||
sec->data_offset = offset1;
|
||||
if (align > sec->addralign)
|
||||
{
|
||||
sec->addralign = align;
|
||||
}
|
||||
return (offset);
|
||||
}
|
||||
|
||||
/* reserve at least 'size' bytes in section 'sec' from
|
||||
sec->data_offset. */
|
||||
void *
|
||||
coff_section_ptr_add(TCCSection *sec, size_t size)
|
||||
{
|
||||
return (sec->data + coff_section_add(sec, size, 1));
|
||||
}
|
||||
|
||||
static TCCSection *
|
||||
coff_have_section(TCCState2 *s1, const char *name)
|
||||
{
|
||||
TCCSection *sec;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < s1->nb_sections; i++)
|
||||
{
|
||||
sec = s1->sections[i];
|
||||
if (strncmp(name, sec->name, 8) == 0)
|
||||
{
|
||||
return (sec);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* return a reference to a section, and create it if it does not
|
||||
exists */
|
||||
TCCSection *
|
||||
coff_find_section(TCCState2 *s1, const char *name)
|
||||
{
|
||||
TCCSection *sec;
|
||||
|
||||
sec = coff_have_section(s1, name);
|
||||
if (sec != NULL)
|
||||
{
|
||||
return (sec);
|
||||
}
|
||||
|
||||
return (coff_new_section(s1, name, COFF_STYP_TEXT));
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------------
|
||||
* Symbols
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
coff_add_sym(TCCState2 *s1, uint32_t value, const char *name, size_t size,
|
||||
int16_t scnum, uint16_t type, int8_t sclass)
|
||||
{
|
||||
size_t symidx;
|
||||
size_t strtaboffset;
|
||||
COFFSym *sym;
|
||||
char *ptr;
|
||||
|
||||
symidx = s1->symtab->nsym;
|
||||
s1->symtab->nsym++;
|
||||
|
||||
s1->symtab->syms = tcc_realloc(s1->symtab->syms, sizeof(COFFSym) * s1->symtab->nsym);
|
||||
sym = &(s1->symtab->syms[symidx]);
|
||||
if (size > 8)
|
||||
{
|
||||
strtaboffset = ALIGN_UP(s1->symtab->strtab.len, 1);
|
||||
s1->symtab->strtab.len += strtaboffset + size + 1;
|
||||
ptr = s1->symtab->strtab.tab;
|
||||
s1->symtab->strtab.tab = tcc_realloc(ptr, s1->symtab->strtab.len);
|
||||
ptr += strtaboffset;
|
||||
memcpy(ptr, name, size + 1);
|
||||
|
||||
sym->n.n.zeroes = 0x0;
|
||||
sym->n.n.offset = strtaboffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(sym->n.name, 0, 8);
|
||||
memcpy(sym->n.name, name, size);
|
||||
}
|
||||
|
||||
return (symidx);
|
||||
}
|
||||
|
||||
int
|
||||
coff_find_sym(TCCState2 *s1, const char *name)
|
||||
{
|
||||
size_t symidx;
|
||||
size_t len;
|
||||
COFFSym *sym;
|
||||
const char *str;
|
||||
|
||||
len = strlen(name);
|
||||
|
||||
for (symidx = 1; symidx < s1->symtab->nsym; symidx++)
|
||||
{
|
||||
sym = &(s1->symtab->syms[symidx]);
|
||||
|
||||
if ((len > 8 && sym->n.n.zeroes != 0)
|
||||
|| (len <= 8 && sym->n.n.zeroes == 0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (len > 8)
|
||||
{
|
||||
str = s1->symtab->strtab.tab + sym->n.n.offset;
|
||||
if (strcmp(name, str) == 0)
|
||||
{
|
||||
return (symidx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strncmp(name, sym->n.name, 8) == 0)
|
||||
{
|
||||
return (symidx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
coff_get_sym_addr(TCCState2 *s1, const char *name, int err, int forc)
|
||||
{
|
||||
COFFSym *sym;
|
||||
int sym_idx;
|
||||
char buf[256];
|
||||
|
||||
if (forc && s1->leading_underscore)
|
||||
{
|
||||
buf[0] = '_';
|
||||
pstrcpy(buf + 1, sizeof(buf) - 1, name);
|
||||
name = buf;
|
||||
}
|
||||
|
||||
sym_idx = coff_find_sym(s1, name);
|
||||
sym = &((COFFSym *)s1->symtab->syms)[sym_idx];
|
||||
if (sym_idx == 0 || sym->scnum == COFF_N_UNDEF)
|
||||
{
|
||||
if (err)
|
||||
{
|
||||
//_tcc_error_noabort("%s not defined", name);
|
||||
}
|
||||
return ((uint32_t)-1);
|
||||
}
|
||||
|
||||
return (sym->value);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -54,7 +54,6 @@ enum {
|
|||
OPTION_include,
|
||||
OPTION_nostdinc,
|
||||
OPTION_nostdlib,
|
||||
OPTION_print_search_dirs,
|
||||
OPTION_w,
|
||||
OPTION_E,
|
||||
OPTION_M,
|
||||
|
@ -100,7 +99,6 @@ static const TCCOption options[] = {
|
|||
{"include", OPTION_include, TCC_OPTION_HAS_ARG},
|
||||
{"nostdinc", OPTION_nostdinc, 0},
|
||||
{"nostdlib", OPTION_nostdlib, 0},
|
||||
{"print-search-dirs", OPTION_print_search_dirs, 0},
|
||||
{"w", OPTION_w, 0},
|
||||
{"E", OPTION_E, 0},
|
||||
{"M", OPTION_M, 0},
|
||||
|
@ -141,13 +139,11 @@ static const Flag options_W[] = {
|
|||
static const Flag options_f[] = {
|
||||
{offsetof(TCCState, char_is_unsigned), 0, "unsigned-char"},
|
||||
{offsetof(TCCState, char_is_unsigned), F_FD_INVERT, "signed-char"},
|
||||
{offsetof(TCCState, nocommon), F_FD_INVERT, "common"},
|
||||
{offsetof(TCCState, leading_underscore), 0, "leading-underscore"},
|
||||
{offsetof(TCCState, ms_extensions), 0, "ms-extensions"},
|
||||
{offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers"},
|
||||
{offsetof(TCCState, reverse_funcargs), 0, "reverse-funcargs"},
|
||||
{offsetof(TCCState, gnu89_inline), 0, "gnu89-inline"},
|
||||
{offsetof(TCCState, unwind_tables), 0, "asynchronous-unwind-tables"},
|
||||
{0, 0, NULL}
|
||||
};
|
||||
|
||||
|
@ -333,25 +329,23 @@ set_linker(TCCState *s, const char *option)
|
|||
s->text_addr = strtoull(p, &end, 16);
|
||||
s->has_text_addr = 1;
|
||||
} else if (link_option(option, "oformat=", &p)) {
|
||||
if (strstart("elf32-", &p)) {
|
||||
s->output_format = TCC_OUTPUT_FORMAT_ELF;
|
||||
} else if (link_arg("binary", p)) {
|
||||
if (link_arg("binary", p))
|
||||
{
|
||||
s->output_format = TCC_OUTPUT_FORMAT_BINARY;
|
||||
#ifdef TCC_TARGET_COFF
|
||||
} else if (link_arg("coff", p)) {
|
||||
}
|
||||
else if (link_arg("coff", p))
|
||||
{
|
||||
s->output_format = TCC_OUTPUT_FORMAT_COFF;
|
||||
#endif
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
|
||||
} else if (link_option(option, "as-needed", &p)) {
|
||||
ignoring = 1;
|
||||
} else if (link_option(option, "O", &p)) {
|
||||
ignoring = 1;
|
||||
} else if (link_option(option, "rpath=", &p)) {
|
||||
copy_linker_arg(&s->rpath, p, ':');
|
||||
} else if (link_option(option, "enable-new-dtags", &p)) {
|
||||
s->enable_new_dtags = 1;
|
||||
} else if (link_option(option, "section-alignment=", &p)) {
|
||||
s->section_align = strtoul(p, &end, 16);
|
||||
} else if (ret = link_option(option, "?whole-archive", &p), ret) {
|
||||
|
@ -717,9 +711,6 @@ reparse:
|
|||
case OPTION_O:
|
||||
s->optimize = atoi(optarg);
|
||||
break;
|
||||
case OPTION_print_search_dirs:
|
||||
x = TCC_OPT_PRINT_DIRS;
|
||||
goto extra_action;
|
||||
case OPTION_ar:
|
||||
x = TCC_OPT_ARCHIVE;
|
||||
extra_action:
|
||||
|
@ -745,8 +736,6 @@ unsupported_option:
|
|||
return (tool);
|
||||
if (optind != noaction)
|
||||
return (0);
|
||||
if (s->verbose == 2)
|
||||
return (TCC_OPT_PRINT_DIRS);
|
||||
if (s->verbose)
|
||||
return (TCC_OPT_VERSION);
|
||||
return (TCC_OPT_HELP);
|
||||
|
|
1033
libtcc/tccelf.c
1033
libtcc/tccelf.c
File diff suppressed because it is too large
Load diff
32
tcc-doc.texi
32
tcc-doc.texi
|
@ -284,7 +284,7 @@ Specify an additional static library path for the @option{-l} option. The
|
|||
default library paths are @file{/usr/local/lib}, @file{/usr/lib} and @file{/lib}.
|
||||
|
||||
@item -lxxx
|
||||
Link your program with dynamic library libxxx.so or static library
|
||||
Link your program with static library
|
||||
libxxx.a. The library is searched in the paths specified by the
|
||||
@option{-L} option and @env{LIBRARY_PATH} variable.
|
||||
|
||||
|
@ -292,30 +292,14 @@ libxxx.a. The library is searched in the paths specified by the
|
|||
Set the path where the tcc internal libraries (and include files) can be
|
||||
found (default is @file{PREFIX/lib/tcc}).
|
||||
|
||||
@item -shared
|
||||
Generate a shared library instead of an executable.
|
||||
|
||||
@item -soname name
|
||||
set name for shared library to be used at runtime
|
||||
|
||||
@item -static
|
||||
Generate a statically linked executable (default is a shared linked
|
||||
executable).
|
||||
|
||||
@item -rdynamic
|
||||
Export global symbols to the dynamic linker. It is useful when a library
|
||||
opened with @code{dlopen()} needs to access executable symbols.
|
||||
|
||||
@item -r
|
||||
Generate an object file combining all input files.
|
||||
|
||||
@item -Wl,-rpath=path
|
||||
Put custom search path for dynamic libraries into executable.
|
||||
|
||||
@item -Wl,--enable-new-dtags
|
||||
When putting a custom search path for dynamic libraries into the executable,
|
||||
create the new ELF dynamic tag DT_RUNPATH instead of the old legacy DT_RPATH.
|
||||
|
||||
@item -Wl,--oformat=fmt
|
||||
Use @var{fmt} as output format. The supported output formats are:
|
||||
@table @code
|
||||
|
@ -327,11 +311,6 @@ Binary image (only for executable output)
|
|||
COFF output format (only for executable output for TMS320C67xx target)
|
||||
@end table
|
||||
|
||||
@item -Wl,--export-all-symbols
|
||||
@item -Wl,--export-dynamic
|
||||
Export global symbols to the dynamic linker. It is useful when a library
|
||||
opened with @code{dlopen()} needs to access executable symbols.
|
||||
|
||||
@item -Wl,-subsystem=console/gui/wince/...
|
||||
Set type for PE (Windows) executables.
|
||||
|
||||
|
@ -827,13 +806,9 @@ Currently, MMX opcodes are supported but not SSE ones.
|
|||
@cindex ELF
|
||||
|
||||
TCC can directly output relocatable ELF files (object files),
|
||||
executable ELF files and dynamic ELF libraries without relying on an
|
||||
executable ELF files without relying on an
|
||||
external linker.
|
||||
|
||||
Dynamic ELF libraries can be output but the C compiler does not generate
|
||||
position independent code (PIC). It means that the dynamic library
|
||||
code generated by TCC cannot be factorized among processes yet.
|
||||
|
||||
TCC linker eliminates unreferenced object code in libraries. A single pass is
|
||||
done on the object and library list, so the order in which object files and
|
||||
libraries are specified is important (same constraint as GNU ld). No grouping
|
||||
|
@ -841,8 +816,7 @@ options (@option{--start-group} and @option{--end-group}) are supported.
|
|||
|
||||
@section ELF file loader
|
||||
|
||||
TCC can load ELF object files, archives (.a files) and dynamic
|
||||
libraries (.so).
|
||||
TCC can load ELF object files and archives (.a files).
|
||||
|
||||
@section PE-i386 file generation
|
||||
@cindex PE-i386
|
||||
|
|
23
tcc/tcc.c
23
tcc/tcc.c
|
@ -17,8 +17,9 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -50,7 +51,7 @@ static const char help_str[] =
|
|||
" -E preprocess only\n"
|
||||
"Linker options:\n"
|
||||
" -Ldir add library path 'dir'\n"
|
||||
" -llib link with dynamic or static library 'lib'\n"
|
||||
" -llib link with static library 'lib'\n"
|
||||
" -r generate (relocatable) object file\n"
|
||||
" -Wl,-opt[=val] set linker option (see tcc -hh)\n"
|
||||
"Misc. options:\n"
|
||||
|
@ -89,14 +90,11 @@ static const char help_more_str[] =
|
|||
" discarded-qualifiers warn when const is dropped (*)\n"
|
||||
"-f[no-]... flags:\n"
|
||||
" unsigned-char default char is unsigned\n"
|
||||
" signed-char default char is signed\n"
|
||||
" common use common section instead of bss\n"
|
||||
" leading-underscore decorate extern symbols\n"
|
||||
" signed-char default char is signed\n" " leading-underscore decorate extern symbols\n"
|
||||
" ms-extensions allow anonymous struct in struct\n"
|
||||
" dollars-in-identifiers allow '$' in C symbols\n"
|
||||
" reverse-funcargs evaluate function arguments right to left\n"
|
||||
" gnu89-inline 'extern inline' is like 'static inline'\n"
|
||||
" asynchronous-unwind-tables create eh_frame section [on]\n"
|
||||
"-m... target specific options:\n"
|
||||
" ms-bitfields use MSVC bitfield layout\n"
|
||||
"-Wl,... linker options:\n"
|
||||
|
@ -104,7 +102,6 @@ static const char help_more_str[] =
|
|||
" -[no-]whole-archive load lib(s) fully/only as needed\n"
|
||||
" -image-base= -Ttext= set base address of executable\n"
|
||||
" -section-alignment= set section alignment in executable\n"
|
||||
" -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
|
||||
" -oformat=[coff,binary] set executable output format\n"
|
||||
" -init= -fini= -Map= -as-needed -O (ignored)\n"
|
||||
"Predefined macros:\n"
|
||||
|
@ -221,13 +218,6 @@ redo:
|
|||
return tcc_tool_ar(s, argc, argv);
|
||||
if (opt == TCC_OPT_VERSION)
|
||||
return 0;
|
||||
if (opt == TCC_OPT_PRINT_DIRS) {
|
||||
/* initialize search dirs */
|
||||
set_environment(s);
|
||||
tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
|
||||
print_search_dirs(s);
|
||||
return (EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
if (s->nb_files == 0) {
|
||||
tcc_error_noabort("no input files");
|
||||
|
@ -279,8 +269,6 @@ redo:
|
|||
if (s->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||
;
|
||||
} else if (0 == ret) {
|
||||
if (s->output_type == TCC_OUTPUT_MEMORY) {
|
||||
} else {
|
||||
if (!s->outfile)
|
||||
s->outfile = default_outputfile(s, first_file);
|
||||
if (!s->just_deps)
|
||||
|
@ -288,7 +276,6 @@ redo:
|
|||
if (!ret && s->gen_deps)
|
||||
gen_makedeps(s, s->outfile, s->deps_outfile);
|
||||
}
|
||||
}
|
||||
|
||||
done = 1;
|
||||
if (ret) {
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -361,6 +364,9 @@ const int _dowildcard = 1;
|
|||
|
||||
/* -------------------------------------------------------------- */
|
||||
/* generate xxx.d file */
|
||||
static inline int is_space(int ch) {
|
||||
return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
|
||||
}
|
||||
|
||||
static char *escape_target_dep(const char *s) {
|
||||
char *res = tcc_malloc(strlen(s) * 2 + 1);
|
||||
|
|
Loading…
Reference in a new issue