xen2 / SharpLang

Compiles .NET/C# to native code using LLVM framework. No longer active, consider migrating to https://github.com/dotnet/corert
Other
282 stars 38 forks source link

Emscripten support #6

Open tritao opened 10 years ago

tritao commented 10 years ago

I'm creating this issue so we can track what needs to be done to have proper support for Emscripten.

tritao commented 10 years ago

I've been trying to get Emscripten to generate JS from an hello world test IR and right now it fails the llc step that converts from LLVM IR to JS.

; ModuleID = 'WriteLine'

%System.String = type { i8*, i8* }

@0 = global [13 x i8] c"Hello, World!"

declare void @System_Void_System_Console__WriteLine_System_String_(%System.String)

declare void @System_Void_System_Console__WriteLine_System_Int32_(i32)

define void @System_Void_Program__Main__() {
  call void @System_Void_System_Console__WriteLine_System_String_(%System.String { i8* inttoptr (i64 13 to i8*), i8* getelementptr inbounds ([13 x i8]* @0, i32 0, i32 0) })
  ret void
}

define i32 @main() {
  call void @System_Void_Program__Main__()
  ret i32 0
}

With a debug build it's possible to get a backtrace:

D:\emscripten-fastcomp\build\bin\Debug>llc -march=js -filetype=asm WriteLine.ll
warning: incorrect target triple '' (did you use emcc/em++ on all source files and not clang directly?)
%System.String { i8* inttoptr (i64 13 to i8*), i8* getelementptr inbounds ([13 x i8]* @0, i32 0, i32 0) }
Unsupported constant kind
UNREACHABLE executed at D:\emscripten-fastcomp\lib\Target\JSBackend\JSBackend.cpp:1074!
Stack dump:
0.      Program arguments: llc -march=js -filetype=asm WriteLine.ll
1.      Running pass 'JavaScript backend' on module 'WriteLine.ll'.
0x0F46A16A (0x0000000A 0x00000000 0x014DC824 0x00C8C249), exit() + 0x13A bytes(s)
0x0F5547BC (0x015E21B8 0x014DCC3C 0x0022B712 0x0108EDB8), abort() + 0x1C bytes(s)
0x00C8C249 (0x0108EDB8 0x0108ED78 0x00000432 0x014DCCD4), llvm::llvm_unreachable_internal() + 0x89 bytes(s), d:\emscripten-fastcomp\lib\support\errorhandling.cpp, line 98 + 0x8 byte(s)
0x0022B712 (0x014DCCB0 0x015E2C80 0x00000000 0x015E2C80), `anonymous namespace'::JSWriter::getConstant() + 0x972 bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 1076
0x0022B7FB (0x014DCCB0 0x015E2C80 0x00000000 0x014DD040), `anonymous namespace'::JSWriter::getValueAsStr() + 0x4B bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 1083 + 0x14 byte(s)
0x0022BA7F (0x014DCDD0 0x015E2C80 0x0000000A 0x014DD170), `anonymous namespace'::JSWriter::getValueAsCastParenStr() + 0x9F bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 1118 + 0x12 byte(s)
0x00268469 (0x014DD09C 0x015E21B8 0x015F36F8 0x015F3D20), `anonymous namespace'::JSWriter::CH___default__() + 0x829 bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\callhandlers.h, line 135 + 0x829 byte(s)
0x00295DF1 (0x014DD6EC 0x015E21B8 0x014DEA50 0x015E21B8), `anonymous namespace'::JSWriter::handleCall() + 0x241 bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\callhandlers.h, line 1062 + 0x2E byte(s)
0x0023474B (0x015E21B8 0x014DEA08 0x014DF078 0x014DF3B0), `anonymous namespace'::JSWriter::generateExpression() + 0x2ADB bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 1614
0x0022F4B1 (0x015DFB38 0x014DF034 0x014DF01C 0x014DF158), `anonymous namespace'::JSWriter::addBlock() + 0xB1 bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 1700
0x0022F708 (0x015E2090 0x014DF330 0x01CCCCCC 0xCCCCCCCC), `anonymous namespace'::JSWriter::printFunctionBody() + 0xD8 bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 1725
0x0022952B (0x015E2090 0x014DF3A4 0x014DF3B0 0xCCCCCCCC), `anonymous namespace'::JSWriter::printFunction() + 0x2AB bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 1932
0x00235804 (0x015E54F0 0x014DF350 0x0022923E 0x014DF364), `anonymous namespace'::JSWriter::printModuleBody() + 0xC4 bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 1946
0x00229266 (0x014DF364 0x014DF380 0x015E54F0 0x014DF3A4), `anonymous namespace'::JSWriter::printModule() + 0x16 bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 2379
0x0022923E (0x014DF364 0x014DF380 0x014DF46C 0x015E1DB8), `anonymous namespace'::JSWriter::printProgram() + 0x1E bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 2374
0x002291EB (0x015D8B18 0x014DF8D8 0x014DF478 0x00000000), `anonymous namespace'::JSWriter::runOnModule() + 0xBB bytes(s), d:\emscripten-fastcomp\lib\target\jsbackend\jsbackend.cpp, line 2391 + 0x2A byte(s)
0x00A88BD9 (0x015D8B18 0x014DF4BC 0x7EFDE000 0xCCCCCCCC), llvm::MPPassManager::runOnModule() + 0x1C9 bytes(s), d:\emscripten-fastcomp\lib\ir\passmanager.cpp, line 1608 + 0x17 byte(s)
0x00A891F1 (0x015D8B18 0x014DF5D4 0x014DF8D8 0x000D5BF9), llvm::PassManagerImpl::run() + 0x101 bytes(s), d:\emscripten-fastcomp\lib\ir\passmanager.cpp, line 1703 + 0x1B byte(s)
0x00A87C1D (0x015D8B18 0x014DF928 0x00000000 0xCCCCCCCC), llvm::PassManager::run() + 0x1D bytes(s), d:\emscripten-fastcomp\lib\ir\passmanager.cpp, line 1739
0x000D5BF9 (0x015D1BF8 0x015CE4F8 0x00000000 0xCCCCCCCC), compileModule() + 0x1109 bytes(s), d:\emscripten-fastcomp\tools\llc\llc.cpp, line 378
0x000D6347 (0x00000004 0x015D1BF8 0x015CCBD8 0x33051FDF), main() + 0xE7 bytes(s), d:\emscripten-fastcomp\tools\llc\llc.cpp, line 195 + 0xD byte(s)
0x00CDC249 (0x014DF98C 0x75B533AA 0x7EFDE000 0x014DF9CC), __tmainCRTStartup() + 0x199 bytes(s), f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c, line 536 + 0x19 byte(s)
0x00CDC38D (0x7EFDE000 0x014DF9CC 0x77EB9F72 0x7EFDE000), mainCRTStartup() + 0xD bytes(s), f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c, line 377
0x75B533AA (0x7EFDE000 0x7877C3FA 0x00000000 0x00000000), BaseThreadInitThunk() + 0x12 bytes(s)
0x77EB9F72 (0x00CDC380 0x7EFDE000 0x00000000 0x00000000), RtlInitializeExceptionChain() + 0x63 bytes(s)
0x77EB9F45 (0x00CDC380 0x7EFDE000 0x00000000 0x00000000), RtlInitializeExceptionChain() + 0x36 bytes(s)

The problem is the usage of an LLVM ConstantStruct in the IR which the Emscripten LLVM JS backend does not know how to deal with. We can either implement this in its backend or change how we generate the LLVM IR to not use this construct.

xen2 commented 10 years ago

Good idea, having all tests running on emscripten early in the project life will probably save us lot of potential future troubles!

amerkoleci commented 10 years ago

I was trying to setup toolchain for Android, could you show me how you setup the Emscripten toolchain?

xen2 commented 10 years ago

Didn't try it myself yet so you would have to look for info on how to do that.

amerkoleci commented 10 years ago

Ok guys, I've managed to setup everything with emscripten, I can compile and link mscorlib with no problem, when I link MyApp.exe and mscorlib and invoke the emscripten toolchain, i have something like this:

Value: %System.Decimal.data %0
LLVM ERROR: Unrecognized struct value
Stack dump:
0.      Program arguments: C:/Program Files/Emscripten/clang/e1.25.0_64bit\opt c
:/users/amer~1.kol/appdata/local/temp\tmpakqot7\Test.bc -strip-debug -internaliz
e -internalize-public-api-list=main,malloc,free -globaldce -pnacl-abi-simplify-p
reopt -pnacl-abi-simplify-postopt -enable-emscripten-cxx-exceptions -o c:/users/
amer~1.kol/appdata/local/temp\tmpakqot7\Test.bc.opt.bc
1.      Running pass 'Function Pass Manager' on module 'c:/users/amer~1.kol/appd
ata/local/temp\tmpakqot7\Test.bc'.
2.      Running pass 'Expand out variables with struct types' on function '@Syst
em_Convert__ToInt64_System_Decimal_'
warning: incorrect target triple '' (did you use emcc/em++ on all source files a
nd not clang directly?)

The module target need to be: asmjs-unknown-emscripten, hopefully we can resovel this issue and then I can make a pull request.

amerkoleci commented 10 years ago

After digging inside the ll generated seams that: %System.Decimal.data = type { i32, i32, i32, i32 }

Gets generated before System.Convert, maybe some cyclic reference, can be?

xen2 commented 10 years ago

LLVM bitcode type declarations don't need to be in order.