diff --git a/CMakeLists.txt b/CMakeLists.txt index 345d7eed0..588401d69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -511,6 +511,10 @@ function(wabt_executable) add_dependencies(everything ${EXE_NAME}) target_link_libraries(${EXE_NAME} ${EXE_LIBS}) + if (MSVC) + target_link_options(${EXE_NAME} PRIVATE "/STACK:8388608") + endif () + if (EMSCRIPTEN) set(EXTRA_LINK_FLAGS "${EXTRA_LINK_FLAGS} -sNODERAWFS -Oz -sALLOW_MEMORY_GROWTH" diff --git a/src/common.cc b/src/common.cc index 9fe3275b3..08e01ac1f 100644 --- a/src/common.cc +++ b/src/common.cc @@ -23,6 +23,10 @@ #include #include +#if COMPILER_IS_MSVC +#include +#endif + #include #include @@ -31,8 +35,13 @@ #include #include #define PATH_MAX _MAX_PATH -#define stat _stat +#define stat _stat64 +#define fseek _fseeki64 +#define ftell _ftelli64 #define S_IFREG _S_IFREG +#define WABT_FILE_OFFSET __int64 +#else +#define WABT_FILE_OFFSET long #endif namespace wabt { @@ -129,7 +138,7 @@ Result ReadFile(std::string_view filename, std::vector* out_data) { return res; } - long size = ftell(infile); + WABT_FILE_OFFSET size = ftell(infile); if (size < 0) { perror("ftell failed"); fclose(infile); @@ -142,12 +151,36 @@ Result ReadFile(std::string_view filename, std::vector* out_data) { return Result::Error; } +#if COMPILER_IS_MSVC + if (static_cast(size) > + static_cast(std::numeric_limits::max())) { + fprintf(stderr, "%s: file too large to read into memory\n", filename_cstr); + fclose(infile); + return Result::Error; + } + + static constexpr size_t kReadChunkSize = 64 * 1024 * 1024; + size_t data_size = static_cast(size); + out_data->resize(data_size); + size_t offset = 0; + while (offset < data_size) { + size_t remaining = data_size - offset; + size_t chunk_size = remaining < kReadChunkSize ? remaining : kReadChunkSize; + if (fread(out_data->data() + offset, chunk_size, 1, infile) != 1) { + fprintf(stderr, "%s: fread failed: %s\n", filename_cstr, strerror(errno)); + fclose(infile); + return Result::Error; + } + offset += chunk_size; + } +#else out_data->resize(size); if (size != 0 && fread(out_data->data(), size, 1, infile) != 1) { fprintf(stderr, "%s: fread failed: %s\n", filename_cstr, strerror(errno)); fclose(infile); return Result::Error; } +#endif fclose(infile); return Result::Ok; diff --git a/src/stream.cc b/src/stream.cc index af385e69a..69c9f3c80 100644 --- a/src/stream.cc +++ b/src/stream.cc @@ -20,6 +20,11 @@ #include #include +#if COMPILER_IS_MSVC +#include +#include +#endif + #define DUMP_OCTETS_PER_LINE 16 #define DUMP_OCTETS_PER_GROUP 2 @@ -28,6 +33,39 @@ namespace wabt { +#if COMPILER_IS_MSVC +static Result WriteDataChunked(FILE* file, + const void* data, + size_t size, + const char* name) { + static constexpr size_t kWriteChunkSize = 64 * 1024 * 1024; + const uint8_t* src = static_cast(data); + size_t offset = 0; + + while (offset < size) { + size_t remaining = size - offset; + size_t chunk_size = + remaining < kWriteChunkSize ? remaining : kWriteChunkSize; + size_t bytes_written = fwrite(src + offset, 1, chunk_size, file); + if (bytes_written != chunk_size) { + ERROR("failed to write %" PRIzd " bytes to %s\n", size, name); + return Result::Error; + } + offset += bytes_written; + } + + return Result::Ok; +} + +static int SeekFile(FILE* file, size_t offset) { + if (offset > static_cast(std::numeric_limits::max())) { + errno = EINVAL; + return -1; + } + return _fseeki64(file, static_cast(offset), SEEK_SET); +} +#endif + Stream::Stream(Stream* log_stream) : offset_(0), result_(Result::Ok), log_stream_(log_stream) {} @@ -145,6 +183,13 @@ Result OutputBuffer::WriteToFile(std::string_view filename) const { return Result::Ok; } +#if COMPILER_IS_MSVC + if (Failed(WriteDataChunked(file, data.data(), data.size(), + filename_str.c_str()))) { + fclose(file); + return Result::Error; + } +#else ssize_t bytes = fwrite(data.data(), 1, data.size(), file); if (bytes < 0 || static_cast(bytes) != data.size()) { ERROR("failed to write %" PRIzd " bytes to %s\n", data.size(), @@ -152,6 +197,7 @@ Result OutputBuffer::WriteToFile(std::string_view filename) const { fclose(file); return Result::Error; } +#endif fclose(file); return Result::Ok; @@ -161,11 +207,17 @@ Result OutputBuffer::WriteToStdout() const { if (data.empty()) { return Result::Ok; } +#if COMPILER_IS_MSVC + if (Failed(WriteDataChunked(stdout, data.data(), data.size(), "stdout"))) { + return Result::Error; + } +#else ssize_t bytes = fwrite(data.data(), 1, data.size(), stdout); if (bytes < 0 || static_cast(bytes) != data.size()) { ERROR("failed to write %" PRIzd " bytes to stdout\n", data.size()); return Result::Error; } +#endif return Result::Ok; } @@ -281,16 +333,29 @@ Result FileStream::WriteDataImpl(size_t at, const void* data, size_t size) { return Result::Ok; } if (at != offset_) { +#if COMPILER_IS_MSVC + if (SeekFile(file_, at) != 0) { + ERROR("fseek offset=%" PRIzd " failed, errno=%d\n", at, errno); + return Result::Error; + } +#else if (fseek(file_, at, SEEK_SET) != 0) { ERROR("fseek offset=%" PRIzd " failed, errno=%d\n", size, errno); return Result::Error; } +#endif offset_ = at; } +#if COMPILER_IS_MSVC + if (Failed(WriteDataChunked(file_, data, size, "FileStream"))) { + return Result::Error; + } +#else if (fwrite(data, size, 1, file_) != 1) { ERROR("fwrite size=%" PRIzd " failed, errno=%d\n", size, errno); return Result::Error; } +#endif offset_ += size; return Result::Ok; }