Skip to content

feat: Add support for compiling with Microsoft Visual Studio C++ (MSVC) #246

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,34 @@ jobs:
run: |
make test

windows-msvc:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
buildType: [Debug, Release]
steps:
- uses: actions/checkout@v3
- name: build
run: |
cmake -B build -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -G "Visual Studio 17 2022"
cmake --build build --target qjs_exe
cmake --build build --target function_source
- name: stats
run: |
build\Debug\qjs.exe -qd
- name: test
run: |
build\Debug\qjs.exe tests\test_bigint.js
build\Debug\qjs.exe tests\test_closure.js
build\Debug\qjs.exe tests\test_language.js
build\Debug\qjs.exe tests\test_builtin.js
build\Debug\qjs.exe tests\test_loop.js
build\Debug\qjs.exe tests\test_std.js
build\Debug\qjs.exe tests\test_worker.js
build\Debug\qjs.exe tests\test_queue_microtask.js
build\Debug\function_source.exe

windows-clang:
runs-on: windows-latest
strategy:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
build/
unicode/
test262_*.txt
.idea
cmake-*
105 changes: 90 additions & 15 deletions cutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,56 @@
#include <malloc_np.h>
#endif

#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define force_inline inline __attribute__((always_inline))
#define no_inline __attribute__((noinline))
#define __maybe_unused __attribute__((unused))

#if defined(_MSC_VER) && !defined(__clang__)
# define likely(x) (x)
# define unlikely(x) (x)
# define force_inline __forceinline
# define no_inline __declspec(noinline)
# define __maybe_unused
# define __attribute__(x)
# define __attribute(x)
# include <intrin.h>
static void *__builtin_frame_address(unsigned int level) {
return (void *)((char*)_AddressOfReturnAddress() - sizeof(int *) - level * sizeof(int *));
}
#else
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
# define force_inline inline __attribute__((always_inline))
# define no_inline __attribute__((noinline))
# define __maybe_unused __attribute__((unused))
#endif

// https://stackoverflow.com/a/6849629
#undef FORMAT_STRING
#if _MSC_VER >= 1400
# include <sal.h>
# if _MSC_VER > 1400
# define FORMAT_STRING(p) _Printf_format_string_ p
# else
# define FORMAT_STRING(p) __format_string p
# endif /* FORMAT_STRING */
#else
# define FORMAT_STRING(p) p
#endif /* _MSC_VER */

// https://stackoverflow.com/a/3312896
// https://stackoverflow.com/a/3312896
#if defined(__GNUC__) || defined(__clang__) // GCC, clang, clang-cl, and so on but not MSVC
# define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
#elif defined(_MSC_VER) && !defined(__clang__) // MSVC
# define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
#endif

#if defined(_MSC_VER) && !defined(__clang__)
#include <math.h>
#define INF INFINITY
#define NEG_INF -INFINITY
#else
#define INF (1.0/0.0)
#define NEG_INF (-1.0/0.0)
#endif

#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
Expand Down Expand Up @@ -136,38 +181,68 @@ static inline int64_t min_int64(int64_t a, int64_t b)
/* WARNING: undefined if a = 0 */
static inline int clz32(unsigned int a)
{
#if defined(_MSC_VER) && !defined(__clang__)
unsigned long index;
_BitScanReverse(&index, a);
return 31 - index;
#else
return __builtin_clz(a);
#endif
}

/* WARNING: undefined if a = 0 */
static inline int clz64(uint64_t a)
{
#if defined(_MSC_VER) && !defined(__clang__)
unsigned long index;
_BitScanReverse64(&index, a);
return 63 - index;
#else
return __builtin_clzll(a);
#endif
}

/* WARNING: undefined if a = 0 */
static inline int ctz32(unsigned int a)
{
#if defined(_MSC_VER) && !defined(__clang__)
unsigned long index;
_BitScanForward(&index, a);
return index;
#else
return __builtin_ctz(a);
#endif
}

/* WARNING: undefined if a = 0 */
static inline int ctz64(uint64_t a)
{
#if defined(_MSC_VER) && !defined(__clang__)
unsigned long index;
_BitScanForward64(&index, a);
return index;
#else
return __builtin_ctzll(a);
#endif
}

struct __attribute__((packed)) packed_u64 {
uint64_t v;
};
PACK(
struct packed_u64 {
uint64_t v;
}
);

struct __attribute__((packed)) packed_u32 {
uint32_t v;
};
PACK(
struct packed_u32 {
uint32_t v;
}
);

struct __attribute__((packed)) packed_u16 {
uint16_t v;
};
PACK(
struct packed_u16 {
uint16_t v;
}
);

static inline uint64_t get_u64(const uint8_t *tab)
{
Expand Down Expand Up @@ -299,7 +374,7 @@ static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
return dbuf_put(s, (uint8_t *)&val, 8);
}
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
const char *fmt, ...);
FORMAT_STRING(const char *fmt), ...);
void dbuf_free(DynBuf *s);
static inline BOOL dbuf_error(DynBuf *s) {
return s->error;
Expand Down
6 changes: 4 additions & 2 deletions quickjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -10153,7 +10153,7 @@ static JSValue js_atof2(JSContext *ctx, const char *str, const char **pp,
if (!(flags & ATOD_INT_ONLY) &&
atod_type == ATOD_TYPE_FLOAT64 &&
strstart(p, "Infinity", &p)) {
double d = 1.0 / 0.0;
double d = INF;
if (is_neg)
d = -d;
val = js_float64(d);
Expand Down Expand Up @@ -22082,6 +22082,8 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
int opcode, scope, tok1, skip_bits;
BOOL has_initializer;

label_lvalue = -1;

if (has_ellipsis < 0) {
/* pre-parse destructuration target for spread detection */
js_parse_skip_parens_token(s, &skip_bits, FALSE);
Expand Down Expand Up @@ -40441,7 +40443,7 @@ static JSValue js_math_min_max(JSContext *ctx, JSValue this_val,
uint32_t tag;

if (unlikely(argc == 0)) {
return __JS_NewFloat64(is_max ? -1.0 / 0.0 : 1.0 / 0.0);
return __JS_NewFloat64(is_max ? NEG_INF : INF);
}

tag = JS_VALUE_GET_TAG(argv[0]);
Expand Down