bootstrappable: HAVE_LONG_LONG, part 2.

This commit is contained in:
Jan (janneke) Nieuwenhuizen 2020-11-25 21:13:35 +01:00
parent 2556e10583
commit bdec98dd01
No known key found for this signature in database
GPG Key ID: F3C1A0D9C1D65273
7 changed files with 173 additions and 8 deletions

54
elf.h
View File

@ -27,13 +27,17 @@
typedef signed char int8_t;
typedef short int int16_t;
typedef int int32_t;
#if HAVE_LONG_LONG
typedef long long int int64_t;
#endif
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
#if HAVE_LONG_LONG
typedef unsigned long long int uint64_t;
#endif
#endif
#endif
/* Standard ELF types. */
@ -47,19 +51,25 @@ typedef int32_t Elf32_Sword;
typedef uint32_t Elf64_Word;
typedef int32_t Elf64_Sword;
#if HAVE_LONG_LONG
/* Types for signed and unsigned 64-bit quantities. */
typedef uint64_t Elf32_Xword;
typedef int64_t Elf32_Sxword;
typedef uint64_t Elf64_Xword;
typedef int64_t Elf64_Sxword;
#endif
/* Type of addresses. */
typedef uint32_t Elf32_Addr;
#if HAVE_LONG_LONG
typedef uint64_t Elf64_Addr;
#endif
/* Type of file offsets. */
typedef uint32_t Elf32_Off;
#if HAVE_LONG_LONG
typedef uint64_t Elf64_Off;
#endif
/* Type for section indices, which are 16-bit quantities. */
typedef uint16_t Elf32_Section;
@ -67,8 +77,9 @@ typedef uint16_t Elf64_Section;
/* Type for version symbol information. */
typedef Elf32_Half Elf32_Versym;
#if HAVE_LONG_LONG
typedef Elf64_Half Elf64_Versym;
#endif
/* The ELF file header. This appears at the start of every ELF file. */
@ -92,6 +103,7 @@ typedef struct
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;
#if HAVE_LONG_LONG
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
@ -109,6 +121,7 @@ typedef struct
Elf64_Half e_shnum; /* Section header table entry count */
Elf64_Half e_shstrndx; /* Section header string table index */
} Elf64_Ehdr;
#endif
/* Fields in the e_ident array. The EI_* macros are indices into the
array. The macros under each EI_* macro are the values the byte
@ -293,6 +306,7 @@ typedef struct
Elf32_Word sh_entsize; /* Entry size if section holds table */
} Elf32_Shdr;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word sh_name; /* Section name (string tbl index) */
@ -306,6 +320,7 @@ typedef struct
Elf64_Xword sh_addralign; /* Section alignment */
Elf64_Xword sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
#endif
/* Special section indices. */
@ -399,6 +414,7 @@ typedef struct
Elf32_Section st_shndx; /* Section index */
} Elf32_Sym;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word st_name; /* Symbol name (string tbl index) */
@ -408,6 +424,7 @@ typedef struct
Elf64_Addr st_value; /* Symbol value */
Elf64_Xword st_size; /* Symbol size */
} Elf64_Sym;
#endif
/* The syminfo section if available contains additional information about
every dynamic symbol. */
@ -418,11 +435,13 @@ typedef struct
Elf32_Half si_flags; /* Per symbol flags */
} Elf32_Syminfo;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
Elf64_Half si_flags; /* Per symbol flags */
} Elf64_Syminfo;
#endif
/* Possible values for si_boundto. */
#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */
@ -510,6 +529,7 @@ typedef struct
Elf32_Word r_info; /* Relocation type and symbol index */
} Elf32_Rel;
#if HAVE_LONG_LONG
/* I have seen two different definitions of the Elf64_Rel and
Elf64_Rela structures, so we'll leave them out until Novell (or
whoever) gets their act together. */
@ -520,6 +540,7 @@ typedef struct
Elf64_Addr r_offset; /* Address */
Elf64_Xword r_info; /* Relocation type and symbol index */
} Elf64_Rel;
#endif
/* Relocation table entry with addend (in section of type SHT_RELA). */
@ -530,12 +551,14 @@ typedef struct
Elf32_Sword r_addend; /* Addend */
} Elf32_Rela;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Addr r_offset; /* Address */
Elf64_Xword r_info; /* Relocation type and symbol index */
Elf64_Sxword r_addend; /* Addend */
} Elf64_Rela;
#endif
/* How to extract and insert information held in the r_info field. */
@ -561,6 +584,7 @@ typedef struct
Elf32_Word p_align; /* Segment alignment */
} Elf32_Phdr;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word p_type; /* Segment type */
@ -572,6 +596,7 @@ typedef struct
Elf64_Xword p_memsz; /* Segment size in memory */
Elf64_Xword p_align; /* Segment alignment */
} Elf64_Phdr;
#endif
/* Special value for e_phnum. This indicates that the real number of
program headers is too large to fit into e_phnum. Instead the real
@ -665,6 +690,7 @@ typedef struct
} d_un;
} Elf32_Dyn;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Sxword d_tag; /* Dynamic entry type */
@ -674,6 +700,7 @@ typedef struct
Elf64_Addr d_ptr; /* Address value */
} d_un;
} Elf64_Dyn;
#endif
/* Legal values for d_tag (dynamic entry type). */
@ -843,6 +870,7 @@ typedef struct
entry */
} Elf32_Verdef;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Half vd_version; /* Version revision */
@ -854,7 +882,7 @@ typedef struct
Elf64_Word vd_next; /* Offset in bytes to next verdef
entry */
} Elf64_Verdef;
#endif
/* Legal values for vd_version (version revision). */
#define VER_DEF_NONE 0 /* No version */
@ -880,13 +908,14 @@ typedef struct
entry */
} Elf32_Verdaux;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word vda_name; /* Version or dependency names */
Elf64_Word vda_next; /* Offset in bytes to next verdaux
entry */
} Elf64_Verdaux;
#endif
/* Version dependency section. */
@ -901,6 +930,7 @@ typedef struct
entry */
} Elf32_Verneed;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Half vn_version; /* Version of structure */
@ -911,7 +941,7 @@ typedef struct
Elf64_Word vn_next; /* Offset in bytes to next verneed
entry */
} Elf64_Verneed;
#endif
/* Legal values for vn_version (version revision). */
#define VER_NEED_NONE 0 /* No version */
@ -930,6 +960,7 @@ typedef struct
entry */
} Elf32_Vernaux;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word vna_hash; /* Hash value of dependency name */
@ -939,7 +970,7 @@ typedef struct
Elf64_Word vna_next; /* Offset in bytes to next vernaux
entry */
} Elf64_Vernaux;
#endif
/* Legal values for vna_flags. */
#define VER_FLG_WEAK 0x2 /* Weak version identifier */
@ -966,6 +997,7 @@ typedef struct
} a_un;
} Elf32_auxv_t;
#if HAVE_LONG_LONG
typedef struct
{
uint64_t a_type; /* Entry type */
@ -977,6 +1009,7 @@ typedef struct
on 64-bit platforms and vice versa. */
} a_un;
} Elf64_auxv_t;
#endif
/* Legal values for a_type (entry type). */
@ -1045,12 +1078,14 @@ typedef struct
Elf32_Word n_type; /* Type of the note. */
} Elf32_Nhdr;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word n_namesz; /* Length of the note's name. */
Elf64_Word n_descsz; /* Length of the note's descriptor. */
Elf64_Word n_type; /* Type of the note. */
} Elf64_Nhdr;
#endif
/* Known names of notes. */
@ -1104,13 +1139,18 @@ typedef struct
/* Move records. */
typedef struct
{
#if HAVE_LONG_LONG
Elf32_Xword m_value; /* Symbol value. */
#else
Elf32_Word m_info; /* Size and index. */
Elf32_Word m_info_padding;
#endif
Elf32_Word m_poffset; /* Symbol offset. */
Elf32_Half m_repeat; /* Repeat count. */
Elf32_Half m_stride; /* Stride info. */
} Elf32_Move;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Xword m_value; /* Symbol value. */
@ -1119,6 +1159,7 @@ typedef struct
Elf64_Half m_repeat; /* Repeat count. */
Elf64_Half m_stride; /* Stride info. */
} Elf64_Move;
#endif
/* Macro to construct move records. */
#define ELF32_M_SYM(info) ((info) >> 8)
@ -1732,6 +1773,7 @@ typedef struct
Elf32_Word l_flags; /* Flags */
} Elf32_Lib;
#if HAVE_LONG_LONG
typedef struct
{
Elf64_Word l_name; /* Name (string table index) */
@ -1740,7 +1782,7 @@ typedef struct
Elf64_Word l_version; /* Interface version */
Elf64_Word l_flags; /* Flags */
} Elf64_Lib;
#endif
/* Legal values for l_flags. */

View File

@ -223,7 +223,11 @@ static const uint8_t segment_prefixes[] = {
static const ASMInstr asm_instrs[] = {
#define ALT(x) x
/* This removes a 0x0f in the second byte */
#if HAVE_LONG_LONG
#define O(o) ((uint64_t) ((((o) & 0xff00) == 0x0f00) ? ((((o) >> 8) & ~0xff) | ((o) & 0xff)) : (o)))
#else
#define O(o) ((uint32_t) ((((o) & 0xff00) == 0x0f00) ? ((((o) >> 8) & ~0xff) | ((o) & 0xff)) : (o)))
#endif
/* This constructs instr_type from opcode, type and group. */
#define T(o,i,g) ((i) | ((g) << OPC_GROUP_SHIFT) | ((((o) & 0xff00) == 0x0f00) ? OPC_0F : 0))
#define DEF_ASM_OP0(name, opcode)

View File

@ -13,12 +13,16 @@ typedef __SIZE_TYPE__ uintptr_t;
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
#if HAVE_LONG_LONG
typedef signed long long int int64_t;
#endif
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
#if HAVE_LONG_LONG
typedef unsigned long long int uint64_t;
#endif
#endif
#ifndef NULL
#define NULL ((void*)0)

View File

@ -780,6 +780,8 @@ LIBTCCAPI TCCState *tcc_new(void)
tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
tcc_define_symbol(s, "__STDC_HOSTED__", NULL);
tcc_define_symbol(s, "__SIZEOF_LONG_LONG__", "8");
/* target defines */
#if defined(TCC_TARGET_I386)
tcc_define_symbol(s, "__i386__", NULL);

13
tcc.h
View File

@ -390,7 +390,12 @@ typedef union CValue {
long double ld;
double d;
float f;
#if HAVE_LONG_LONG
uint64_t i;
#else
uint32_t i;
uint32_t i_padding;
#endif
struct {
int size;
const void *data;
@ -606,7 +611,12 @@ typedef struct CachedInclude {
#ifdef CONFIG_TCC_ASM
typedef struct ExprValue {
#if HAVE_LONG_LONG
uint64_t v;
#else
uint32_t v;
uint32_t v_padding;
#endif
Sym *sym;
int pcrel;
} ExprValue;
@ -1516,6 +1526,7 @@ static inline void write32le(unsigned char *p, uint32_t x) {
static inline void add32le(unsigned char *p, int32_t x) {
write32le(p, read32le(p) + x);
}
#if HAVE_LONG_LONG
static inline uint64_t read64le(unsigned char *p) {
return read32le(p) | (uint64_t)read32le(p + 4) << 32;
}
@ -1525,7 +1536,7 @@ static inline void write64le(unsigned char *p, uint64_t x) {
static inline void add64le(unsigned char *p, int64_t x) {
write64le(p, read64le(p) + x);
}
#endif
/* ------------ i386-gen.c ------------ */
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
ST_FUNC void g(int c);

View File

@ -90,7 +90,11 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
{
Sym *sym;
int op, label;
#if HAVE_LONG_LONG
uint64_t n;
#else
uint32_t n;
#endif
const char *p;
switch(tok) {
@ -324,6 +328,7 @@ static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe)
case TOK_NE:
pe->v = pe->v != e2.v;
break;
#if HAVE_LONG_LONG
case TOK_LT:
pe->v = (int64_t)pe->v < (int64_t)e2.v;
break;
@ -336,11 +341,29 @@ static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe)
case TOK_GT:
pe->v = (int64_t)pe->v > (int64_t)e2.v;
break;
#else
case TOK_LT:
pe->v = (int32_t)pe->v < (int32_t)e2.v;
break;
case TOK_GE:
pe->v = (int32_t)pe->v >= (int32_t)e2.v;
break;
case TOK_LE:
pe->v = (int32_t)pe->v <= (int32_t)e2.v;
break;
case TOK_GT:
pe->v = (int32_t)pe->v > (int32_t)e2.v;
break;
#endif
default:
break;
}
#if HAVE_LONG_LONG
/* GAS compare results are -1/0 not 1/0. */
pe->v = -(int64_t)pe->v;
#else
pe->v = -(int32_t)pe->v;
#endif
}
}
@ -522,7 +545,11 @@ static void asm_parse_directive(TCCState *s1, int global)
#else
next();
for(;;) {
#if HAVE_LONG_LONG
uint64_t vl;
#else
uint32_t vl;
#endif
const char *p;
p = tokc.str.data;
@ -537,7 +564,9 @@ static void asm_parse_directive(TCCState *s1, int global)
if (sec->sh_type != SHT_NOBITS) {
/* XXX: endianness */
gen_le32(vl);
#if HAVE_LONG_LONG
gen_le32(vl >> 32);
#endif
} else {
ind += 8;
}

View File

@ -64,7 +64,11 @@ ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
ST_DATA struct switch_t {
struct case_t {
#if HAVE_LONG_LONG
int64_t v1, v2;
#else
int32_t v1, v1_padding, v2, v2_padding;
#endif
int sym;
} **p; int n; /* list of case ranges */
int def_sym; /* default symbol */
@ -88,8 +92,12 @@ static void vla_runtime_type_size(CType *type, int *a);
static void vla_sp_restore(void);
static void vla_sp_restore_root(void);
static int is_compatible_parameter_types(CType *type1, CType *type2);
#if HAVE_LONG_LONG
static inline int64_t expr_const64(void);
ST_FUNC void vpush64(int ty, unsigned long long v);
#else
static inline int32_t expr_const32(void);
#endif
ST_FUNC void vpush(CType *type);
ST_FUNC int gvtst(int inv, int t);
ST_FUNC int is_btype_size(int bt);
@ -1302,7 +1310,9 @@ static void lexpand(void)
v = vtop->r & (VT_VALMASK | VT_LVAL);
if (v == VT_CONST) {
vdup();
#if HAVE_LONG_LONG
vtop[0].c.i >>= 32;
#endif
} else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
vdup();
vtop[0].c.i += 4;
@ -1329,7 +1339,9 @@ ST_FUNC void lexpand_nr(void)
v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
if (v == VT_CONST) {
vtop[-1].c.i = vtop->c.i;
#if HAVE_LONG_LONG
vtop->c.i = vtop->c.i >> 32;
#endif
vtop->r = VT_CONST;
} else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
vtop->c.i += 4;
@ -1654,6 +1666,7 @@ static void gen_opl(int op)
}
#endif
#if HAVE_LONG_LONG
static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b)
{
uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b);
@ -1664,6 +1677,18 @@ static int gen_opic_lt(uint64_t a, uint64_t b)
{
return (a ^ (uint64_t)1 << 63) < (b ^ (uint64_t)1 << 63);
}
#else
static uint32_t gen_opic_sdiv(uint32_t a, uint32_t b)
{
uint32_t x = (a >> 31 ? -a : a) / (b >> 31 ? -b : b);
return (a ^ b) >> 31 ? -x : x;
}
static int gen_opic_lt(uint32_t a, uint32_t b)
{
return (a ^ (uint32_t)1 << 31) < (b ^ (uint32_t)1 << 31);
}
#endif
/* handle integer constant optimizations and various machine
independent opt */
@ -1675,10 +1700,15 @@ static void gen_opic(int op)
int t2 = v2->type.t & VT_BTYPE;
int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
#if HAVE_LONG_LONG
uint64_t l1 = c1 ? v1->c.i : 0;
uint64_t l2 = c2 ? v2->c.i : 0;
int shm = (t1 == VT_LLONG) ? 63 : 31;
#else
uint32_t l1 = c1 ? v1->c.i : 0;
uint32_t l2 = c2 ? v2->c.i : 0;
int shm = 31;
#endif
if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR))
l1 = ((uint32_t)l1 |
(v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000)));
@ -1716,7 +1746,11 @@ static void gen_opic(int op)
case TOK_SHL: l1 <<= (l2 & shm); break;
case TOK_SHR: l1 >>= (l2 & shm); break;
case TOK_SAR:
#if HAVE_LONG_LONG
l1 = (l1 >> 63) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm);
#else
l1 = (l1 >> 31) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm);
#endif
break;
/* tests */
case TOK_ULT: l1 = l1 < l2; break;
@ -4538,10 +4572,18 @@ ST_FUNC void unary(void)
break;
case TOK_builtin_choose_expr:
{
#if HAVE_LONG_LONG
int64_t c;
#else
int32_t c;
#endif
next();
skip('(');
#if HAVE_LONG_LONG
c = expr_const64();
#else
c = expr_const32();
#endif
skip(',');
if (!c) {
nocode_wanted++;
@ -5348,6 +5390,7 @@ static void expr_const1(void)
const_wanted--;
}
#if HAVE_LONG_LONG
/* parse an integer constant and return its value. */
static inline int64_t expr_const64(void)
{
@ -5359,13 +5402,30 @@ static inline int64_t expr_const64(void)
vpop();
return c;
}
#else
/* parse an integer constant and return its value. */
static inline int32_t expr_const32(void)
{
int32_t c;
expr_const1();
if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
expect("constant expression");
c = vtop->c.i;
vpop();
return c;
}
#endif
/* parse an integer constant and return its value.
Complain if it doesn't fit 32bit (signed or unsigned). */
ST_FUNC int expr_const(void)
{
int c;
#if HAVE_LONG_LONG
int64_t wc = expr_const64();
#else
int32_t wc = expr_const32();
#endif
c = wc;
if (c != wc && (unsigned)c != wc)
tcc_error("constant exceeds 32 bit");
@ -5460,8 +5520,13 @@ static void gfunc_return(CType *func_type)
static int case_cmp(const void *pa, const void *pb)
{
#if HAVE_LONG_LONG
int64_t a = (*(struct case_t**) pa)->v1;
int64_t b = (*(struct case_t**) pb)->v1;
#else
int32_t a = (*(struct case_t**) pa)->v1;
int32_t b = (*(struct case_t**) pb)->v1;
#endif
return a < b ? -1 : a > b;
}
@ -5786,10 +5851,18 @@ static void block(int *bsym, int *csym, int is_expr)
expect("switch");
nocode_wanted &= ~0x20000000;
next();
#if HAVE_LONG_LONG
cr->v1 = cr->v2 = expr_const64();
#else
cr->v1 = cr->v2 = expr_const32();
#endif
if (gnu_ext && tok == TOK_DOTS) {
next();
#if HAVE_LONG_LONG
cr->v2 = expr_const64();
#else
cr->v2 = expr_const32();
#endif
if (cr->v2 < cr->v1)
tcc_warning("empty case range");
}