From d17b459eccf9cde57191c08c2f756e9c2b50bc36 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 28 May 2019 20:13:14 +0300 Subject: [PATCH] C: fix MSVC support --- .../backend/c/generate/ClassGenerator.java | 5 +- .../main/resources/org/teavm/backend/c/date.c | 17 +++++-- .../resources/org/teavm/backend/c/runtime.c | 47 ++++++++++++----- .../resources/org/teavm/backend/c/runtime.h | 3 +- .../java/org/teavm/junit/CRunStrategy.java | 51 +++++++++++++------ 5 files changed, 88 insertions(+), 35 deletions(-) diff --git a/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java b/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java index c1cc87d29..6a7cb029f 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java +++ b/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java @@ -478,7 +478,7 @@ public class ClassGenerator { headerWriter.print("extern ").print(structName).print(" ").print(name).println(";"); if (classLayout != null) { - codeWriter.println("static int16_t teavm_classLayouts_" + name + "[];"); + codeWriter.println("static int16_t teavm_classLayouts_" + name + "[" + (classLayout.length + 1) + "];"); } codeWriter.print("alignas(8) ").print(structName).print(" ").print(name).println(" = {").indent(); @@ -741,7 +741,8 @@ public class ClassGenerator { } String name = context.getNames().forClassInstance(ValueType.object(className)); - codeWriter.print("static int16_t teavm_classLayouts_" + name + "[" + classLayout.length + " + 1] = {").indent(); + codeWriter.print("static int16_t teavm_classLayouts_" + name + "[" + (classLayout.length + 1) + "] = {") + .indent(); codeWriter.println().print("INT16_C(" + classLayout.length + ")"); for (FieldReference field : classLayout) { diff --git a/core/src/main/resources/org/teavm/backend/c/date.c b/core/src/main/resources/org/teavm/backend/c/date.c index ca8d32f05..748e996f6 100644 --- a/core/src/main/resources/org/teavm/backend/c/date.c +++ b/core/src/main/resources/org/teavm/backend/c/date.c @@ -12,6 +12,11 @@ #define _GNU_SOURCE #endif +#ifdef _MSC_VER +#define timegm _mkgmtime +#define localtime_r(a, b) localtime_s(b, a) +#endif + #include static time_t teavm_epochStart; @@ -73,10 +78,14 @@ int64_t teavm_date_createUtc(int32_t year, int32_t month, int32_t day, int32_t h } int64_t teavm_date_parse(char* s) { - struct tm t; - strptime(s, teavm_date_defaultFormat, &t); - time_t result = mktime(&t); - return (int64_t) (1000 * difftime(result, teavm_epochStart)); + #ifdef __GNUC__ + struct tm t; + strptime(s, teavm_date_defaultFormat, &t); + time_t result = mktime(&t); + return (int64_t) (1000 * difftime(result, teavm_epochStart)); + #else + return 0; + #endif } int32_t teavm_date_getYear(int64_t time) { diff --git a/core/src/main/resources/org/teavm/backend/c/runtime.c b/core/src/main/resources/org/teavm/backend/c/runtime.c index 82de3709b..88dd69229 100644 --- a/core/src/main/resources/org/teavm/backend/c/runtime.c +++ b/core/src/main/resources/org/teavm/backend/c/runtime.c @@ -18,6 +18,7 @@ #ifdef _MSC_VER #include +#include #endif void* teavm_gc_heapAddress = NULL; @@ -55,25 +56,32 @@ TeaVM_ResourceMapEntry* teavm_lookupResource(TeaVM_ResourceMap *map, TeaVM_Strin static timer_t teavm_queueTimer; #endif +#ifdef _MSC_VER +static HANDLE teavm_queueTimer; +#endif + void teavm_beforeInit() { srand(time(NULL)); #ifdef __GNUC__ - struct sigaction sigact; - sigact.sa_flags = 0; - sigact.sa_handler = NULL; - sigaction(SIGRTMIN, &sigact, NULL); + struct sigaction sigact; + sigact.sa_flags = 0; + sigact.sa_handler = NULL; + sigaction(SIGRTMIN, &sigact, NULL); - sigset_t signals; - sigemptyset(&signals ); - sigaddset(&signals, SIGRTMIN); - sigprocmask(SIG_BLOCK, &signals, NULL); + sigset_t signals; + sigemptyset(&signals ); + sigaddset(&signals, SIGRTMIN); + sigprocmask(SIG_BLOCK, &signals, NULL); - struct sigevent sev; - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = SIGRTMIN; - timer_create(CLOCK_REALTIME, &sev, &teavm_queueTimer); + struct sigevent sev; + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGRTMIN; + timer_create(CLOCK_REALTIME, &sev, &teavm_queueTimer); + #endif + #ifdef _MSC_VER + teavm_queueTimer = CreateEvent(NULL, TRUE, FALSE, TEXT("TeaVM_eventQueue")); #endif } @@ -218,6 +226,19 @@ void teavm_interrupt() { #endif +#ifdef _MSC_VER + +void teavm_waitFor(int64_t timeout) { + WaitForSingleObject(teavm_queueTimer, timeout); + ResetEvent(teavm_queueTimer); +} + +void teavm_interrupt() { + SetEvent(teavm_queueTimer); +} + +#endif + void teavm_outOfMemory() { fprintf(stderr, "Application crashed due to lack of free memory\n"); exit(1); @@ -279,7 +300,7 @@ TeaVM_Array* teavm_resourceMapKeys(TeaVM_ResourceMap *map) { size_t teavm_mbSize(char16_t* javaChars, int32_t javaCharsCount) { size_t sz = 0; - char buffer[__STDC_UTF_16__]; + char buffer[8]; mbstate_t state = {0}; for (int32_t i = 0; i < javaCharsCount; ++i) { size_t result = c16rtomb(buffer, javaChars[i], &state); diff --git a/core/src/main/resources/org/teavm/backend/c/runtime.h b/core/src/main/resources/org/teavm/backend/c/runtime.h index f87c59e7a..8b8f4b28b 100644 --- a/core/src/main/resources/org/teavm/backend/c/runtime.h +++ b/core/src/main/resources/org/teavm/backend/c/runtime.h @@ -10,7 +10,8 @@ #endif #ifdef _MSC_VER -#define alignas(x) +#define alignas(n) __declspec(align(n)) +#pragma comment (lib,"uuid.lib") #endif typedef struct TeaVM_Object { diff --git a/tools/junit/src/main/java/org/teavm/junit/CRunStrategy.java b/tools/junit/src/main/java/org/teavm/junit/CRunStrategy.java index 170525672..9ab1382d5 100644 --- a/tools/junit/src/main/java/org/teavm/junit/CRunStrategy.java +++ b/tools/junit/src/main/java/org/teavm/junit/CRunStrategy.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; class CRunStrategy implements TestRunStrategy { private String compilerCommand; @@ -87,25 +88,45 @@ class CRunStrategy implements TestRunStrategy { return runProcess(new ProcessBuilder(command).directory(inputDir).start(), output); } - private boolean runProcess(Process process, List output) throws IOException, InterruptedException { + private boolean runProcess(Process process, List output) throws InterruptedException { BufferedReader stdin = new BufferedReader(new InputStreamReader(process.getInputStream())); BufferedReader stderr = new BufferedReader(new InputStreamReader(process.getErrorStream())); + ConcurrentLinkedQueue lines = new ConcurrentLinkedQueue<>(); - while (true) { - String line = stderr.readLine(); - if (line == null) { - break; + Thread thread = new Thread(() -> { + try { + while (true) { + String line = stderr.readLine(); + if (line == null) { + break; + } + lines.add(line); + } + } catch (IOException e) { + // do nothing } - output.add(line); - } - while (true) { - String line = stdin.readLine(); - if (line == null) { - break; - } - output.add(line); - } + }); + thread.setDaemon(true); + thread.start(); - return process.waitFor() == 0; + thread = new Thread(() -> { + try { + while (true) { + String line = stdin.readLine(); + if (line == null) { + break; + } + lines.add(line); + } + } catch (IOException e) { + // do nothing + } + }); + thread.setDaemon(true); + thread.start(); + + boolean result = process.waitFor() == 0; + output.addAll(lines); + return result; } }