Fix Windows x64 env/runtime and PE alignment tests

This commit is contained in:
Benjamin Oldenburg 2026-03-15 21:25:28 +07:00
parent 396675f74f
commit 4371ebd682
6 changed files with 1052 additions and 5 deletions

3
tcc.h
View File

@ -505,6 +505,7 @@ struct SymAttr {
unsigned short
aligned : 5, /* alignment as log2+1 (0 == unspecified) */
packed : 1,
typedef_align : 1, /* alignment came from a typedef'ed type */
weak : 1,
visibility : 2,
dllexport : 1,
@ -512,7 +513,7 @@ struct SymAttr {
dllimport : 1,
addrtaken : 1,
nodebug : 1,
xxxx : 2; /* not used */
xxxx : 1; /* not used */
};
/* function attributes or temporary attributes for parsing */

View File

@ -1177,8 +1177,10 @@ ST_FUNC void vpush_helper_func(int v)
/* Merge symbol attributes. */
static void merge_symattr(struct SymAttr *sa, struct SymAttr *sa1)
{
if (sa1->aligned && !sa->aligned)
if (sa1->aligned && !sa->aligned) {
sa->aligned = sa1->aligned;
sa->typedef_align = sa1->typedef_align;
}
sa->packed |= sa1->packed;
sa->weak |= sa1->weak;
sa->nodebug |= sa1->nodebug;
@ -4000,6 +4002,7 @@ redo:
n = MAX_ALIGN;
}
ad->a.aligned = exact_log2p1(n);
ad->a.typedef_align = 0;
if (n != 1 << (ad->a.aligned - 1))
tcc_error("alignment of %d is larger than implemented", n);
break;
@ -4226,8 +4229,11 @@ static void struct_layout(CType *type, AttributeDef *ad)
}
/* some individual align was specified */
#ifdef TCC_TARGET_PE
/* GNU aligned(n) on a field is a minimum, not a way to lower alignment. */
if (a > align)
/* GNU aligned(n) on a field is a minimum, not a way to lower alignment.
Typedef-level alignment changes the type alignment itself. */
if (f->a.typedef_align && a)
align = a;
else if (a > align)
align = a;
#else
if (a)
@ -4701,7 +4707,10 @@ do_decl:
static void sym_to_attr(AttributeDef *ad, Sym *s)
{
int had_aligned = ad->a.aligned;
merge_symattr(&ad->a, &s->a);
if (!had_aligned && (s->type.t & VT_TYPEDEF) && s->a.aligned)
ad->a.typedef_align = 1;
merge_funcattr(&ad->f, &s->f);
}

View File

@ -21,6 +21,12 @@
#include "tcc.h"
#ifdef _WIN32
#include <stdlib.h>
# if !defined(_UCRT) && !defined(_ARM_) && !defined(__arm__) && !defined(_ARM64_) && !defined(__aarch64__) && !defined(_ARM64EC_) && !defined(__arm64ec__)
/* MinGW's x86_64 msvcrt headers prefer __p__environ(), but msvcrt.dll exports
_get_environ() directly, which is what the TCC runtime can reliably import. */
_CRTIMP errno_t __cdecl _get_environ(char ***);
_CRTIMP errno_t __cdecl _get_wenviron(wchar_t ***);
# endif
#endif
/* only native compiler supports -run */

View File

@ -69,9 +69,17 @@ ifneq (,$(filter FreeBSD NetBSD,$(TARGETOS)))
TESTS += test1
endif
HOST_WIN_UCRT = no
ifeq ($(TARGETOS),WIN32)
HOST_WIN_UCRT := $(shell printf '#include <stdlib.h>\n' | $(CC) -dM -E -xc - 2>/dev/null | grep -q '^#define _UCRT' && echo yes || echo no)
endif
TCCTEST_REF = test.ref
ifeq ($(ARCH)-$(TARGETOS),arm64-WIN32)
TCCTEST_REF = test.ref.win32-arm64
else ifeq ($(ARCH)-$(TARGETOS)-$(HOST_WIN_UCRT),x86_64-WIN32-yes)
# CLANG64/UCRT generates a different host reference than the msvcrt-backed TCC runtime.
TCCTEST_REF = test.ref.win32-x86_64-ucrt
endif
RUN_TCC = -run $(TOPSRC)/tcc.c $(TCCFLAGS)

View File

@ -294,7 +294,7 @@ aligntest5 sizeof=16 alignof=16
aligntest6 sizeof=16 alignof=16
aligntest7 sizeof=4 alignof=4
aligntest8 sizeof=4096 alignof=4096
aligntest9 sizeof=16 alignof=8
aligntest9 sizeof=12 alignof=4
aligntest10 sizeof=16 alignof=8
altest5 sizeof=32 alignof=16
altest6 sizeof=32 alignof=16

File diff suppressed because it is too large Load Diff