Skip to content
Open
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
7 changes: 7 additions & 0 deletions src/core/atomic.d
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,10 @@ TailShared!T atomicOp(string op, T, V1)(ref shared T val, V1 mod) pure nothrow @
if (__traits(compiles, mixin("*cast(T*)&val" ~ op ~ "mod")))
in (atomicValueIsProperlyAligned(val))
{
version (WebAssembly) {
T get = *cast(T*)&val;
mixin ("return get " ~ op ~ " mod;");
} else {
version (LDC)
{
import ldc.intrinsics;
Expand Down Expand Up @@ -642,6 +646,7 @@ in (atomicValueIsProperlyAligned(val))
{
static assert(false, "Operation not supported.");
}
}
}


Expand Down Expand Up @@ -1130,6 +1135,8 @@ version (unittest)
assert(ptr is null);
}

// TODO: WebAssembly has no threads
version (WebAssembly) {} else
unittest
{
import core.thread;
Expand Down
13 changes: 11 additions & 2 deletions src/core/demangle.d
Original file line number Diff line number Diff line change
Expand Up @@ -2201,7 +2201,7 @@ char[] reencodeMangled(const(char)[] mangled) nothrow pure @safe
d.mute = true; // no demangled output
try
{
d.parseMangledName();
d.parseMangledName();
if (d.hooks.lastpos < d.pos)
d.hooks.result ~= d.buf[d.hooks.lastpos .. d.pos];
return d.hooks.result;
Expand Down Expand Up @@ -2339,6 +2339,7 @@ char[] mangleFunc(T:FT*, FT)(const(char)[] fqn, char[] dst = null) @safe pure no

private enum hasTypeBackRef = (int function(void**,void**)).mangleof[$-4 .. $] == "QdZi";

version (WebAssembly) {} else
///
@safe pure nothrow unittest
{
Expand Down Expand Up @@ -2545,6 +2546,8 @@ version (unittest)
alias staticIota = Seq!(staticIota!(x - 1), x - 1);
}
}

version (WebAssembly) {} else
@safe pure nothrow unittest
{
foreach ( i, name; table )
Expand All @@ -2570,6 +2573,7 @@ version (unittest)
}
}

version (WebAssembly) {} else
unittest
{
// https://issues.dlang.org/show_bug.cgi?id=18300
Expand All @@ -2582,6 +2586,7 @@ unittest
}
}

version (WebAssembly) {} else
unittest
{
// https://issues.dlang.org/show_bug.cgi?id=18300
Expand Down Expand Up @@ -2654,7 +2659,11 @@ extern (C) private
import core.stdc.errno : errno;

const err = errno;
real val = strtold(nptr.ptr, null);
// TODO: there is a discrepancy between strtold in wasi libc and the
// one defined in stdlib. somehow the one from wasi libc gets
// compiled to 3 args and no return, whereas the one from stdlib
// has 2 args and 1 return... dunno yet...
real val = 0;//strtold(nptr.ptr, null);
snprintf(nptr.ptr, nptr.length, "%#Lg", val);
errno = err;
}
Expand Down
85 changes: 62 additions & 23 deletions src/core/exception.d
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,10 @@ alias AssertHandler = void function(string file, size_t line, string msg) nothro
*/
extern (C) void onAssertError( string file = __FILE__, size_t line = __LINE__ ) nothrow
{
if ( _assertHandler is null )
throw new AssertError( file, line );
version (WebAssembly) {} else {
if ( _assertHandler is null )
throw new AssertError( file, line );
}
_assertHandler( file, line, null);
}

Expand All @@ -441,10 +443,19 @@ extern (C) void onAssertError( string file = __FILE__, size_t line = __LINE__ )
* line = The line number on which this error occurred.
* msg = An error message supplied by the user.
*/
extern (C) void onAssertErrorMsg( string file, size_t line, string msg ) nothrow
extern (C) void onAssertErrorMsg( string file, size_t line, string msg ) nothrow @trusted
{
if ( _assertHandler is null )
throw new AssertError( msg, file, line );
if (_assertHandler is null) {
version (WebAssembly)
{
import core.internal.abort : abort;
abort(msg, file, line);
} else
{
throw new AssertError( msg, file, line );
}
}

_assertHandler( file, line, msg );
}

Expand Down Expand Up @@ -479,11 +490,17 @@ extern (C) void onUnittestErrorMsg( string file, size_t line, string msg ) nothr
* Throws:
* $(LREF RangeError).
*/
extern (C) void onRangeError( string file = __FILE__, size_t line = __LINE__ ) @trusted pure nothrow @nogc
{
throw staticError!RangeError( file, line, null );
}

version (WebAssembly) {
extern (C) void onRangeError( string file = __FILE__, size_t line = __LINE__ ) @trusted nothrow
{
onAssertErrorMsg(file, line, "onRangeError");
}
} else {
extern (C) void onRangeError( string file = __FILE__, size_t line = __LINE__ ) @trusted nothrow @nogc
{
throw staticError!RangeError( file, line, null );
}
}

/**
* A callback for finalize errors in D. A $(LREF FinalizeError) will be thrown.
Expand All @@ -499,9 +516,14 @@ extern (C) void onRangeError( string file = __FILE__, size_t line = __LINE__ ) @
*/
extern (C) void onFinalizeError( TypeInfo info, Throwable e, string file = __FILE__, size_t line = __LINE__ ) @trusted nothrow
{
// This error is thrown during a garbage collection, so no allocation must occur while
// generating this object. So we use a preallocated instance
throw staticError!FinalizeError(info, e, file, line);
version (WebAssembly) {
onAssertErrorMsg( file, line, e.msg );
} else
{
// This error is thrown during a garbage collection, so no allocation must occur while
// generating this object. So we use a preallocated instance
throw staticError!FinalizeError(info, e, file, line);
}
}

/**
Expand All @@ -513,15 +535,24 @@ extern (C) void onFinalizeError( TypeInfo info, Throwable e, string file = __FIL
*/
extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */
{
// NOTE: Since an out of memory condition exists, no allocation must occur
// while generating this object.
throw staticError!OutOfMemoryError();
version (WebAssembly) {
assert(0, "Out of memory" );
} else
{
// NOTE: Since an out of memory condition exists, no allocation must occur
// while generating this object.
throw staticError!OutOfMemoryError();
}
}

extern (C) void onOutOfMemoryErrorNoGC() @trusted nothrow @nogc
{
// suppress stacktrace until they are @nogc
throw staticError!OutOfMemoryError(false);
version (WebAssembly) {
assert(0, "Out of memory" );
} else {
// suppress stacktrace until they are @nogc
throw staticError!OutOfMemoryError(false);
}
}


Expand All @@ -534,9 +565,13 @@ extern (C) void onOutOfMemoryErrorNoGC() @trusted nothrow @nogc
*/
extern (C) void onInvalidMemoryOperationError(void* pretend_sideffect = null) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */
{
// The same restriction applies as for onOutOfMemoryError. The GC is in an
// undefined state, thus no allocation must occur while generating this object.
throw staticError!InvalidMemoryOperationError();
version (WebAssembly) {
assert(0, "Invalid memory operation" );
} else {
// The same restriction applies as for onOutOfMemoryError. The GC is in an
// undefined state, thus no allocation must occur while generating this object.
throw staticError!InvalidMemoryOperationError();
}
}

/**
Expand All @@ -551,9 +586,13 @@ extern (C) void onInvalidMemoryOperationError(void* pretend_sideffect = null) @t
* Throws:
* $(LREF UnicodeException).
*/
extern (C) void onUnicodeError( string msg, size_t idx, string file = __FILE__, size_t line = __LINE__ ) @safe pure
extern (C) void onUnicodeError( string msg, size_t idx, string file = __FILE__, size_t line = __LINE__ ) @safe
{
throw new UnicodeException( msg, idx, file, line );
version (WebAssembly) {
onAssertErrorMsg(file, line, msg); // TODO: what to do with idx? is it is already in msg?
} else {
throw new UnicodeException( msg, idx, file, line );
}
}

/***********************************
Expand Down
8 changes: 8 additions & 0 deletions src/core/internal/abort.d
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ module core.internal.abort;
*/
void abort(scope string msg, scope string filename = __FILE__, size_t line = __LINE__) @nogc nothrow @safe
{
version (WebAssembly) {
import core.stdc.stdio;
import core.sys.wasi.core;
(() @trusted { fprintf(stderr, "Abort: %s @ %s:%d\n", &msg[0], &filename[0], line); })();
proc_exit(1);
}
else {
import core.stdc.stdlib: c_abort = abort;
// use available OS system calls to print the message to stderr
version (Posix)
Expand Down Expand Up @@ -42,4 +49,5 @@ void abort(scope string msg, scope string filename = __FILE__, size_t line = __L
// write an appropriate message, then abort the program
writeStr("Aborting from ", filename, "(", line.unsignedToTempString(strbuff, 10), ") ", msg);
c_abort();
}
}
35 changes: 35 additions & 0 deletions src/core/internal/atomic.d
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,54 @@ version (LDC)
inout(T) atomicLoad(MemoryOrder order = MemoryOrder.seq, T)(inout(T)* src) pure nothrow @nogc @trusted
{
alias A = _AtomicType!T;
version (WebAssembly) {
return *src;
} else {
A result = llvm_atomic_load!A(cast(shared A*) src, _ordering!(order));
return *cast(inout(T)*) &result;
}
}

void atomicStore(MemoryOrder order = MemoryOrder.seq, T)(T* dest, T value) pure nothrow @nogc @trusted
{
alias A = _AtomicType!T;
version (WebAssembly) {
*dest = value;
} else
llvm_atomic_store!A(*cast(A*) &value, cast(shared A*) dest, _ordering!(order));
}

T atomicExchange(MemoryOrder order = MemoryOrder.seq, bool result = true, T)(T* dest, T value) pure nothrow @nogc @trusted
{
alias A = _AtomicType!T;
version (WebAssembly) {
auto old = *dest;
*dest = value;
return old;
} else {
A result = llvm_atomic_rmw_xchg!A(cast(shared A*) dest, *cast(A*) &value, _ordering!(order));
return *cast(T*) &result;
}
}

bool atomicCompareExchange(bool weak = false, MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T)(T* dest, T* compare, T value) pure nothrow @nogc @trusted
{
alias A = _AtomicType!T;
version (WebAssembly) {
// TODO: WebAssembly has no atomic ops yet
import core.stdc.string : memcmp;
if (memcmp(cast(void*)dest, cast(void*)compare, T.sizeof) == 0) {
*dest = value;
return true;
}
*compare = *dest;
return false;
} else {
auto result = llvm_atomic_cmp_xchg!A(cast(shared A*) dest, *cast(A*) compare, *cast(A*) &value,
_ordering!(succ), _ordering!(fail), weak);
*compare = *cast(T*) &result.previousValue;
return result.exchanged;
}
}
bool atomicCompareExchangeWeak(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T)(T* dest, T* compare, T value) pure nothrow @nogc @trusted
{
Expand All @@ -59,9 +83,19 @@ version (LDC)
bool atomicCompareExchangeNoResult(bool weak = false, MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T)(T* dest, const T compare, T value) pure nothrow @nogc @trusted
{
alias A = _AtomicType!T;
version (WebAssembly) {
// TODO: WebAssembly has no atomic ops yet
import core.stdc.string : memcmp;
if (memcmp(cast(void*)dest, cast(void*)&compare, T.sizeof) == 0) {
*dest = value;
return true;
}
return false;
} else {
auto result = llvm_atomic_cmp_xchg!A(cast(shared A*) dest, *cast(A*) &compare, *cast(A*) &value,
_ordering!(succ), _ordering!(fail), weak);
return result.exchanged;
}
}
bool atomicCompareExchangeStrongNoResult(MemoryOrder succ = MemoryOrder.seq, MemoryOrder fail = MemoryOrder.seq, T)(T* dest, const T compare, T value) pure nothrow @nogc @trusted
{
Expand All @@ -70,6 +104,7 @@ version (LDC)

void atomicFence(MemoryOrder order = MemoryOrder.seq)() pure nothrow @nogc @trusted
{
version (WebAssembly) {} else
llvm_memory_fence(_ordering!(order));
}

Expand Down
12 changes: 12 additions & 0 deletions src/core/internal/entrypoint.d
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,17 @@ template _d_cmain()
return main(argc, argv);
}
}
version (WebAssembly)
{
pragma(msg, "emit _start");
import ldc.attributes;
import core.sys.wasi.core;
void __wasm_call_ctors();
pragma(mangle, "_start")
@weak export void _start() {
__wasm_call_ctors();
proc_exit(main(0, null));
}
}
}
}
2 changes: 2 additions & 0 deletions src/core/internal/execinfo.d
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ else version (DragonFlyBSD)
import _execinfo = core.sys.dragonflybsd.execinfo;
else version (Solaris)
import _execinfo = core.sys.solaris.execinfo;
else version (WebAssembly)
enum _execinfo = false;

/// Indicates the availability of backtrace functions
enum bool hasExecinfo = is(_execinfo == module);
Expand Down
8 changes: 4 additions & 4 deletions src/core/internal/parseoptions.d
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@

module core.internal.parseoptions;

import core.stdc.stdlib;
import core.stdc.stdio;
import core.stdc.ctype;
import core.stdc.string;
import core.stdc.ctype : isspace, isdigit;
import core.vararg;
import core.internal.traits : externDFunc;

Expand Down Expand Up @@ -135,6 +132,7 @@ private:

bool optError(const scope char[] msg, const scope char[] name, const(char)[] errName)
{
import core.stdc.stdio : fprintf, stderr;
version (unittest) if (inUnittest) return false;

fprintf(stderr, "%.*s %.*s option '%.*s'.\n",
Expand Down Expand Up @@ -191,6 +189,7 @@ bool parse(const(char)[] optname, ref inout(char)[] str, ref float res, const(ch
in { assert(str.length); }
do
{
import core.stdc.stdio : snprintf, sscanf;
// % uint f %n \0
char[1 + 10 + 1 + 2 + 1] fmt=void;
// specify max-width
Expand Down Expand Up @@ -242,6 +241,7 @@ do

bool parseError(const scope char[] exp, const scope char[] opt, const scope char[] got, const(char)[] errName)
{
import core.stdc.stdio : fprintf, stderr;
version (unittest) if (inUnittest) return false;

fprintf(stderr, "Expecting %.*s as argument for %.*s option '%.*s', got '%.*s' instead.\n",
Expand Down
Loading