C: properly print stack trace when application crashes in Windows

This commit is contained in:
Alexey Andreev 2019-07-29 14:19:58 +03:00
parent 2d3d92f9a8
commit 1074293aad
3 changed files with 56 additions and 8 deletions

View File

@ -37,13 +37,14 @@ public class ConsoleIntrinsic implements Intrinsic {
switch (invocation.getMethod().getName()) { switch (invocation.getMethod().getName()) {
case "printString": { case "printString": {
context.includes().addInclude("<stdio.h>"); context.includes().addInclude("<stdio.h>");
context.writer().print("fprintf(stderr, \"%s\", "); context.writer().print("teavm_printString(");
Expr arg = invocation.getArguments().get(0); Expr arg = invocation.getArguments().get(0);
String literal = extractStringConstant(arg); String literal = extractStringConstant(arg);
if (literal != null) { if (literal != null) {
context.writer().print("u");
StringPoolGenerator.generateSimpleStringLiteral(context.writer(), literal); StringPoolGenerator.generateSimpleStringLiteral(context.writer(), literal);
} else { } else {
context.writer().print("teavm_stringToC("); context.writer().print("teavm_stringToC16(");
context.emit(arg); context.emit(arg);
context.writer().print(")"); context.writer().print(")");
} }

View File

@ -263,17 +263,64 @@ void teavm_interrupt() {
#endif #endif
#ifndef TEAVM_WINDOWS_LOG
#define TEAVM_OUTPUT_STRING(s) fprintf(stderr, s)
#else
#define TEAVM_OUTPUT_STRING(s) OutputDebugStringW(L##s)
#endif
void teavm_outOfMemory() { void teavm_outOfMemory() {
fprintf(stderr, "Application crashed due to lack of free memory\n"); TEAVM_OUTPUT_STRING("Application crashed due to lack of free memory\n");
exit(1); abort();
} }
void teavm_printString(char* s) { static char16_t* teavm_utf16ToUtf32(char16_t* source, char32_t* target) {
fprintf(stderr, "%s", s); char16_t c = *source;
if (c & 0xFC00 == 0xD800) {
char16_t n = *(source + 1);
if (n & 0xFC00 == 0xDC00) {
*target = (((c & ~0xFC00) << 10) | (n & ~0xFC00)) + 0x10000;
return source + 2;
}
}
*target = c;
return source + 1;
}
void teavm_printString(char16_t* s) {
#ifndef TEAVM_WINDOWS_LOG
#ifdef _MSC_VER
fprintf(stderr, "%ls", s);
#else
int32_t cap = 128;
wchar_t* buf = malloc(sizeof(wchar_t) * cap);
wchar_t* out = buf;
int32_t sz = 0;
wchar_t c;
do {
s = teavm_utf16ToUtf32(s, out++);
if (++sz == cap) {
cap *= 2;
buf = realloc(buf, sizeof(wchar_t) * cap);
out = buf + sz;
}
} while (c != '\0');
fprintf(stderr, "%ls", buf);
free(buf);
#endif
#else
OutputDebugStringW(s);
#endif
} }
void teavm_printInt(int32_t i) { void teavm_printInt(int32_t i) {
fprintf(stderr, "%" PRId32, i); #ifndef TEAVM_WINDOWS_LOG
fprintf(stderr, "%" PRId32, i);
#else
wchar_t str[10];
swprintf(str, 10, L"%d", i);
OutputDebugStringW(str);
#endif
} }
int32_t teavm_hashCode(TeaVM_String* string) { int32_t teavm_hashCode(TeaVM_String* string) {

View File

@ -270,7 +270,7 @@ extern void teavm_waitFor(int64_t timeout);
extern void teavm_interrupt(); extern void teavm_interrupt();
extern void teavm_outOfMemory(); extern void teavm_outOfMemory();
extern void teavm_printString(char*); extern void teavm_printString(char16_t*);
extern void teavm_printInt(int32_t); extern void teavm_printInt(int32_t);
extern TeaVM_Array* teavm_parseArguments(int, char**); extern TeaVM_Array* teavm_parseArguments(int, char**);