Home About Eric Topics SourceGear

2021-02-23 12:00:00

Llama Rust SDK preview 0.1.4

My outer loop for working on the Llama Rust SDK currently looks like this:

while (still_motivated())
{
    find_a_crate_that_doesnt_work();
    while (llama_is_crashing())
    {
        fix_something();
    }
    while (compiled_result_is_crashing())
    {
        fix_something();
    }
    while (compiled_result_is_wrong())
    {
        fix_something();
    }
    delude_self();
}

I consider this a perfectly fine development process for a side project. If Llama ever becomes something more serious, I'll [try to] approach this with a bit more discipline.

When choosing a crate that doesn't work, I do have to look for things that have a chance. In terms of platform-specific functionality, my current scope is limited to "whatever is in .NET 5", so I don't even bother working on something like a UI library or a game engine.

For this iteration, I chose an SVG rendering library I found on GitHub:

https://github.com/RazrFalcon/resvg

To get started, first I had to split the crate into two, so the executable and the library each have their own project. Then I created an .rsproj file from the Cargo.toml so I could use dotnet build. Both of these steps are described in more detail in a previous blog entry.

In this case, each of the three inner loops lasted several days. The first two loops are often the easy part. When something crashes, I usually get enough clues to diagnose and find the actual problem.

That third loop can be rather painful. The program runs, and it thinks everything went fine, but the resulting output is just wrong. In this case, I'm rendering SVG into PNG files, so the symptoms are visual. There is supposed to be a picture of couch, but there is not. The star is the wrong color. But these kinds of clues don't tell me much about where the incorrect code is.

There are a variety of things I can try to isolate where the problem is, but this step is rarely straightforward. Sometimes I discover that I'm chasing multiple problems that all look the same. Very often I add a debug print statement and it completely changes what the LLVM optimizer does and the symptoms change or go away.

Finally, after fixing a whole bunch of bugs, I was able to successfully run:

dotnet run car.svg car.png

and get this:

BTW, I found that car.svg file here:

https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/

The final step in the loop is delude_self(). I'm not saying this is constructive, but I pause for this bit of silliness on every iteration, and I have no plans to stop.

Yeah, right.

Anyway...

I have published a new version of the Llama Rust SDK on nuget.org:

SourceGear.Rust.NET.Sdk version 0.1.4

What got fixed

I'll finish here with a list of things I fixed for this iteration. Each of the features in the unreadable wall of text below was either previously unimplemented or needed some kind of fix in order to get resvg working.

The thing I found remarkable is to think about the previous projects that were working fine WITHOUT these fixes. I mean, there are dozens of items here. How did anything work at all?

llvm.floor.f32; llvm.ceil.f32; llvm.trunc.v2f32; llvm.fabs.v2f32; llvm.sqrt.v2f32; llvm.pow.f32; llvm.round.f32; fix llvm.maxnum.f32 and llvm.minnum.f32 to deal with NaN problems; llvm.minnum.v2f32; llvm.maxnum.v2f32; llvm.fabs.f32; llvm.fabs.v2f64; llvm.cos.f32; llvm.sqrt.v2f64; llvm.sqrt.f32; implement sat arith for i16 and i8; refactor llvm constant expressions; implement select with vector of i1; fix fcmp problems for NaNs; fcmp for vectors; fpext for vectors; fix bug with fptrunc for vectors; cleanup fptosi; cleanup fptoui; cleanup sitofp; uitofp fixes; sign extension from vec of i1; cleanup llvmtrunc; make sure immed chain isn't too long to avoid overflowing the stack on recursion; fixes for where instruction values get stored; fix rs sdk to handle when either kind of references empty; improve error messages from the stack checking code; implement sadd_sat_i32; v8i8_add; v4i16_add; v4i16_mul; v4i16_or; v4i16_shl; v4i16_lshr; v2i32_shl; v2i32_lshr; v2i32_ashr; v2f32_min; v2f32_max; v2f32_mul; v2f32_div; v2f32_add; v2f32_sub; v2f32_trunc; v2f32_fabs; v2f32_sqrt; v2f64_fabs; v2f64_sqrt; v2f32_to_v2i32; v2i32_to_v2f32; v2u32_to_v2f32; v4u8_to_v4f32; v8i16_sub; v8i16_mul; v8i16_and; v8i16_xor; v8i16_lshr; v8i16_shl; v4f32_div; v4i32_lshr; v4f64_to_v4f32; v2f64_to_v2f32; v2f32_to_v2f64; v8i32_lshr; file attributes return value sometimes wrong; bug in permissions for memory mapped files; bug in get length of open file;

Delusion aside, I won't be a bit surprised if the next iteration involves a lot of fixes as well.