How the RemObjects Elements targets work

RemObjects Oxygene and RemObjects C# have 3 targets, the .NET, Cocoa (OSX/iOS) and Java (Android) targets. Each of the targets are unique, there's no interpretting from 1 to another, even though the original target was .NET. Internally the compiler reduces each of the C# and Oxygene elements to low level elements, that is, for loops become while loops, try/finally is converted to try/except on platforms that don't have a finally (like Java), using to a try/finally, etc. Then the targets convert the reduced data into the platform specific code. When the compiler is done, what's left is Exit, Assignments, If, Goto, Label, Switch, Case, While, Break, Continue, Case and Try. Each target also has a "Type Loader", which deals with adding references to .dll, .fx or .jar files.The type loader deals with listing types from external sources and getting their members. The last part of each target is the Target itself, which has the unique code for each platform, including things like specifying what types translate to the system types, dealing with operator overloading and platform specific system logic.

.NET

On .NET things are converted into IL. The compiler converts each type, member, statement and expression into a low level IL constructs.

Java

For the Java target we generate a set of .class files in memory then combine it in a JAR file, which is essentially a zip file.

Cocoa

The cocoa target is more interesting, since there's no .class or clr file format that we can use, instead it's a raw executable built with LLVM. LLVM uses a very low level assembly that it optimizes and converts to native code for the target platform, of which we support 5: armv7, armv7s, armv8, x86_64 and i386. The type loader here uses .fx formats as an intermediate. fx files are also written next to libraries emitted when compiling.

The end result is that each of the targets has nice and optimized code made specially for those platforms.

RemObjects C# cross platform shared projects tutorial

I've posted a tutorial for using RemObjects C# at tutorial. This tutorial shows how to share source files between different platforms while keeping the ifdefs to a minimum, using Sugar.

Updates on my RemObjects Projects

It's been a while since I blogged about my work, and I've been way busy with all of that. Here's a list of things I worked on in the last year:

I'm also working on several new things for the coming year, keep looking here & on the RemObjects blog for news.

updates on the media player project

In my previous post about the media player project I expected several possibilities, but I found a better option for all of this, which is a simple Android Player box like the G-Box Midnight 2. I found a cheap clone of the G-Box here on dx.com, which has the exact same board and replaceable firmware.

Took a few weeks to arrive but when it did it was easy enough to replace the Android OS with Linux + XBMC which made a great media player system. Attached a disk for storage and supports WLAN/LAN, so now I've got a nice present for about 60 euro + a cheap 1 TB USB harddisk (60-70 euro).

dcas with llvm

Trying to implement a lock free linked list/stack and other lock free structures sometimes requires the use of a "double compare and swap", essentially comparing two pointers with two other pointers and replacing the first with a new pair, only if both match, atomically. Reading the LangRef it's not obvious how to do this, the cmpxchg instruction is what you'd use if you had just a pair of integers. The trick is to use an int sized (2*pointersize) for example int(64) on a 32bits cpu or int(128) on a 64bits cpu and casting the pointer/values to it. For example:

%struct.dcas = type { i8*, i8* }

%struct.dcas void @dcas(%struct.dcas* %ptr, %struct.dcas %_cmp, 
    %struct.dcas %_newval) {
  %cmp = alloca %struct.dcas
  %newval = alloca %struct.dcas
  store %struct.dcas %_cmp, %cmp
  store %struct.dcas %_newval, %newval

  %res = alloca i64
  %ptri64 = bitcast %struct.test* %ptr to i64*

  %ptrcmpi64 = bitcast %struct.dcas* %cmp to i64*
  %cmpi64 = load i64* %ptrcmpi64

  %ptrnewvali64 = bitcast %struct.dcas* %newval to i64*
  %newvali64 = load i64* %ptrnewvali64

  %resi64 = cmpxchg i64* %ptri64, i64 %cmpi64, i64 %newvali64 seq_cst

  store i64 %resi64, i64* %res
  %resdcasptr = bitcast i64* %res to %struct.dcas*
  %resdcas = load %struct.dcas* %resdcasptr

  ret %resdcas
}

Replace i64 with i128 on 64bits platforms. Tested on x86 (creates cmpxchg8b) and x86_64 (cmpxchg16b), seems to work for arm too but I'm not entirely familiar with arm asm yet to say 100%.