Jump to page: 1 2
Thread overview
Question about WebAssembly
Oct 02, 2019
materus
Oct 02, 2019
John Colvin
Oct 02, 2019
Sebastiaan Koppe
Oct 03, 2019
Max Haughton
Oct 03, 2019
Dukc
Oct 03, 2019
Max Haughton
Oct 03, 2019
Sebastiaan Koppe
Dec 11, 2019
Jani Hur
Dec 11, 2019
Sebastiaan Koppe
Dec 11, 2019
Dukc
Dec 11, 2019
Sebastiaan Koppe
Oct 02, 2019
Dukc
Oct 02, 2019
Mark Rousell
October 02, 2019
Are there any plans to support webassembly?
I know betterC is working but i mean full language.
All i found was there is problem with GC but Go and C# works so what's preventing D to work?
October 02, 2019
On Wednesday, 2 October 2019 at 09:26:56 UTC, materus wrote:
> Are there any plans to support webassembly?
> I know betterC is working but i mean full language.
> All i found was there is problem with GC but Go and C# works so what's preventing D to work?

https://github.com/skoppe/spasm
October 02, 2019
On Wednesday, 2 October 2019 at 09:26:56 UTC, materus wrote:
> Are there any plans to support webassembly?
> I know betterC is working but i mean full language.
> All i found was there is problem with GC but Go and C# works so what's preventing D to work?

The short answer is manpower.

Long answer depends on what you mean by working. Go produces very large binaries, and C# currently works by emulating dlls in your browser. TinyGo is an option but doesn't support the full language [https://tinygo.org/lang-support/]. Rust is the most mature, mostly because it doesn't have a runtime to port, so it is a lot easier.

With D the main issue is that someone needs to port druntime to wasm. I am working on it in my spare time, but progress is slow.

Here are some examples of what I have got running:

https://skoppe.github.io/spasm/examples/todo-mvc/ -> famous todo-mvc
https://skoppe.github.io/spasm-imgui/ -> use c++ library
https://skoppe.github.io/spasm/examples/underrun/ -> ported js game
https://skoppe.github.io/spasm-tradingview-example/index.html ->  calling typescript
October 02, 2019
On Wednesday, 2 October 2019 at 09:26:56 UTC, materus wrote:
> C# works so what's preventing D to work?

If you mean Bridge.NET[1], well, nothing in theory. Bridge.NET essentially implements .NET runtime library in JavaScript, and translates C# to it. Nothing would prevent implementing a D compiler that does the same to D -indeed, it would likely be easier thanks to lighter runtime library. But still, you'd need a lot of manpower -Bridge.NET has a company behind it, not just freetime volunteers. Bridge.NET is the main tool behind my commercial project, with some parts written in Spasm.

I feel that while the C# transpiler is excellent work and very useful, the challenge of doing a specialized JavaScript transpiler shows. It often has worse error messages than D compilers for errors of similar complexity, and you do run into a codegen bug every now and then. Also, the runtime library isn't completely implemented, and there are not very good docs about what's implemented and what's not. When you consider how mature language C# is, this speaks a lot IMO.

1: https://bridge.net/
October 02, 2019
On 02/10/2019 15:27, Dukc via Digitalmars-d wrote:
> On Wednesday, 2 October 2019 at 09:26:56 UTC, materus wrote:
>> C# works so what's preventing D to work?
>
> If you mean Bridge.NET[1], well, nothing in theory. Bridge.NET essentially implements .NET runtime library in JavaScript, and translates C# to it. Nothing would prevent implementing a D compiler that does the same to D -indeed, it would likely be easier thanks to lighter runtime library. But still, you'd need a lot of manpower -Bridge.NET has a company behind it, not just freetime volunteers. Bridge.NET is the main tool behind my commercial project, with some parts written in Spasm.
>
> I feel that while the C# transpiler is excellent work and very useful, the challenge of doing a specialized JavaScript transpiler shows. It often has worse error messages than D compilers for errors of similar complexity, and you do run into a codegen bug every now and then. Also, the runtime library isn't completely implemented, and there are not very good docs about what's implemented and what's not. When you consider how mature language C# is, this speaks a lot IMO.
>
> 1: https://bridge.net/

https://blazor.net/ surely.



-- 
Mark Rousell






October 03, 2019
On Wednesday, 2 October 2019 at 10:23:45 UTC, Sebastiaan Koppe wrote:
> On Wednesday, 2 October 2019 at 09:26:56 UTC, materus wrote:
>> [...]
>
> The short answer is manpower.
>
> Long answer depends on what you mean by working. Go produces very large binaries, and C# currently works by emulating dlls in your browser. TinyGo is an option but doesn't support the full language [https://tinygo.org/lang-support/]. Rust is the most mature, mostly because it doesn't have a runtime to port, so it is a lot easier.
>
> With D the main issue is that someone needs to port druntime to wasm. I am working on it in my spare time, but progress is slow.
>
> Here are some examples of what I have got running:
>
> https://skoppe.github.io/spasm/examples/todo-mvc/ -> famous todo-mvc
> https://skoppe.github.io/spasm-imgui/ -> use c++ library
> https://skoppe.github.io/spasm/examples/underrun/ -> ported js game
> https://skoppe.github.io/spasm-tradingview-example/index.html ->  calling typescript

Is there still a barrier on having syscalls to use, e.g. being able to implement malloc/free? Assuming it's technically possible I would like to work on this but probably in 2020 :(
October 03, 2019
On Thursday, 3 October 2019 at 15:33:54 UTC, Max Haughton wrote:
> Is there still a barrier on having syscalls to use, e.g. being able to implement malloc/free? Assuming it's technically possible I would like to work on this but probably in 2020 :(

Why would you need syscalls to implement malloc/free? Just allocate out of a static buffer. It is not even that hard to do, versions I use myself (feel free to use for any purpose, but bad code quality and high probability of bugs as it's fairly little used):

```
@nogc:

/+
0x0000_0000 = varaamaton
0x0000_0001 = varattu, yksi 4kt lohko
0x0000_0002 = varattu, yli 4kt
0x0000_0003 = varattu, osa varausta aikaisemmalla sivulla
0x0000_0004 = puoliksi varattu, yksi 2kt lohko
0x0000_0005 = kokonaan varattu, 2 kt lohkoissa
0x0000_0007 = jälkimmäinen 2kt puolisko varattu
0x0000_0010 = varattu, yksi 1kt lohko
0x0000_0011 = varattu, 2*1kt
0x0000_0013 = varattu kokonaan, 1kt lohkoissa
0x0000_0015 = varattu 2*1kt joista jompi kumpi vapautettu
0x0000_001B = varattu 4*1kt, kaksi vapautettu
0x0000_001F = varattu 4*1kt, kolme vapautettu
0x0000_004X = varattu 512t lohkoissa
0x0000_01XX = varattu 256t lohkoissa
0x0000_040X = varattu 128t lohkoissa
0x0000_1XXX = varattu 64t lohkoissa
0x0000_4XXX = varattu 32t lohkoissa
0x0001_XXXX = varattu 16t lohkoissa
0x0004_XXXX = varattu 8t lohkoissa
0x01XX_XXXX = varattu 1t lohkoissa
+/

enum memPageAmount = 0x200u;
enum memSizeClasses = 13u;
enum pageSize = 1u << memSizeClasses-1;
__gshared ushort[memSizeClasses] lastMemoryPages;
__gshared uint[memPageAmount] heapMap;
__gshared void[pageSize][memPageAmount] heap = void;

export extern(C) void* malloc(size_t amount)
{   if (amount == 0) return null;
    foreach(allocSize; memSizeClasses.iota)
        if (amount <= (1u << allocSize))
        foreach(pageI; lastMemoryPages[allocSize].iota(lastMemoryPages[allocSize] + memPageAmount).map!(i => cast(short)i))
    {   pageI %= memPageAmount;

        void* result;
        if
        (   heapMap[pageI] >= 0x0100_0000u >>> allocSize * 2
            &&  heapMap[pageI] <  0x0300_0000u >>> allocSize * 2
            && ~heapMap[pageI] &  0x0000_0FFFu >>> allocSize
        )
        {   result = &heap[pageI][0] + ((heapMap[pageI] & 0xFFF >>> allocSize) + 1) * (1u << allocSize);
            //merkitsee muistikarttaan lohkon käyttöönoton.
            heapMap[pageI]++;
        } else if (heapMap[pageI] == 0)
        // varaamaton sivu. Eiköhän oteta käyttöön.
        {   heapMap[pageI] = 0x0100_0000u >>> allocSize * 2;
            result = heap[pageI].ptr;
        }
        else continue;

        assert(result >= heap.ptr && result < heap.ptr + memPageAmount);
        lastMemoryPages[allocSize] = pageI;
        assert(heapMap[pageI] != 0);
        return result;
    }

    //yli muistisivun kokoisen alueen varaus
    auto pagesNeeded = (amount - 1) / pageSize + 1;
    size_t result = 0;
    foreach (canditate; heapMap[].slide(pagesNeeded))
    {   if (canditate.all!(page => page == 0u)) goto foundArea;
        result++;
    }
    //muisti loppu
    return null;

    foundArea:
    heapMap[result] = 2u;
    foreach(ref pageMark; heapMap[].drop(result + 1).takeExactly(pagesNeeded-1))
    {   pageMark = 3u;
    }

    return heap[result].ptr;
}

export extern(C) void free(const(void)* cAllocation)
{   //Oletettavasti tälle funktiolle välitetty osoitin dumpataan jorpakkoon heti jälkeenpäin,
    //joten tämä tyyppimuunnos ei luultavasti aiheuta ongelmia.
    auto allocation = cast(void*) cAllocation;
    if (allocation == null) return;
    assert(allocation >= heap.ptr && allocation < heap.ptr + memPageAmount, "free() ei osoita kekoon!");

    ptrdiff_t allocAddr = allocation - &heap[0][0];
    size_t pageI = allocAddr / pageSize;
    size_t pageOffset = allocAddr % pageSize;

    assert (heapMap[pageI] != 0, "Yritetään vapauttaa jo valmiiksi varaamatonta muistia");
    assert (heapMap[pageI] != 3, "Muistin vapautus ei osoita varatun pätkän alkuun");

    foreach(allocSize; memSizeClasses.iota) if
    (   heapMap[pageI] >= 0x0100_0000u >>> allocSize * 2
        &&  heapMap[pageI] <  0x0300_0000u >>> allocSize * 2
    )
    {   /+assert
        (   heapMap[pageI] >= cast(ulong)pageOffset * pageSize + 0x0100_0000u >>> allocSize * 2,
            "Yritetään vapauttaa jo valmiiksi varaamatonta muistia"
        );+/
        assert (pageOffset % 1u << allocSize == 0, "Muistin vapautus ei osoita varatun pätkän alkuun");

        //kirjoitetaan muistiin: yksi vapautettu.
        heapMap[pageI] += pageSize >>> allocSize;
        if (heapMap[pageI] > 0x0200_0000u >>> allocSize * 2) heapMap[pageI] = 0;
        return;
    }

    assert (heapMap[pageI] == 2u);
    heapMap[pageI] = 0;
    foreach(ref pageMark; heapMap[pageI+1 .. $].until!(a => a!=3u)) pageMark = 0;
}
```
October 03, 2019
On Thursday, 3 October 2019 at 16:28:43 UTC, Dukc wrote:
> On Thursday, 3 October 2019 at 15:33:54 UTC, Max Haughton wrote:
>> [...]
>
> Why would you need syscalls to implement malloc/free? Just allocate out of a static buffer. It is not even that hard to do, versions I use myself (feel free to use for any purpose, but bad code quality and high probability of bugs as it's fairly little used):
>
> [...]

I am aware, but I was more thinking about the other calls too. Obviously it can be done as you have described, but it also would involve completely reimplementing druntime

October 03, 2019
On Thursday, 3 October 2019 at 15:33:54 UTC, Max Haughton wrote:
> Is there still a barrier on having syscalls to use, e.g. being able to implement malloc/free? Assuming it's technically possible I would like to work on this but probably in 2020 :(

It all depends on what you want to do. If you want to write client side web applications, you likely have no need for syscalls, since you will just use the web apis, like I did in the examples I posted earlier.

If you want your wasm to run outside the browser, e.g. in the cloud, then your best bet would be to port druntime to WASI. Or use the libc provided by the WASI C sdk and write bindings for druntime for it.

On the other hand, I already have hello-world code running on cloudflare workers (http://skoppe.nl/hello) and have also had something on fastly as well.

In the next month or so I want to finish a document outlining my approach to getting more of D supported in WebAssembly. Ultimately that will require porting druntime, or at least its most essential features.

What do you want to build?
December 11, 2019
Is D's WebAssembly support usable in Screeps (https://screeps.com/) ?

I just yesterday run into Screeps so I have no experience about it but the following caught my eye:

"Use JavaScript or compile other languages via WebAssembly."

See https://docs.screeps.com/modules.html#Binary-modules about the Screeps' WASM support. As I know nothing about Screeps and WebAssembly that tells me nothing at the moment :(
« First   ‹ Prev
1 2