Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMorgan Brown <morganbr@users.noreply.github.com>2018-04-07 05:35:17 +0300
committerGitHub <noreply@github.com>2018-04-07 05:35:17 +0300
commita1d1dc873fb52db2cff913572f714fa6524cc5a9 (patch)
tree2ba8de97eca332c75e909ac9d2a43dbd6895d653 /src/ILCompiler.WebAssembly
parentc4d4dd827f788e134a6f9f1a4443b8f467759266 (diff)
Initialize modules and run StartupCodeMain in wasm (#5621)
Code to call InitializeModules on startup and associated bug fixes and workarounds. Handles mismatched struct calling conventions between LLVM and Clang and works around the dup opcode incorrectly reloading values. Enables StartupCodeMain and fix associated bugs in pinvokes. Implements main return codes
Diffstat (limited to 'src/ILCompiler.WebAssembly')
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs28
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs16
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs28
3 files changed, 66 insertions, 6 deletions
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
index b4859b849..f49035bde 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
@@ -141,6 +141,11 @@ namespace Internal.IL
{
EcmaMethod ecmaMethod = ((EcmaMethod)_method);
string exportName = ecmaMethod.IsRuntimeExport ? ecmaMethod.GetRuntimeExportName() : ecmaMethod.GetNativeCallableExportName();
+ if (exportName == null)
+ {
+ exportName = ecmaMethod.Name;
+ }
+
EmitNativeToManagedThunk(_compilation, _method, exportName, _llvmFunction);
}
}
@@ -669,7 +674,18 @@ namespace Internal.IL
case TypeFlags.ValueType:
case TypeFlags.Nullable:
- return LLVM.ArrayType(LLVM.Int8Type(), (uint)type.GetElementSize().AsInt);
+ {
+ // LLVM thinks certain sizes of struct have a different calling convention than Clang does.
+ // Treating them as ints fixes that and is more efficient in general
+ if (type.GetElementSize().AsInt == 4)
+ {
+ return LLVM.Int32Type();
+ }
+ else
+ {
+ return LLVM.ArrayType(LLVM.Int8Type(), (uint)type.GetElementSize().AsInt);
+ }
+ }
case TypeFlags.Enum:
return GetLLVMTypeForTypeDesc(type.UnderlyingType);
@@ -1313,7 +1329,15 @@ namespace Internal.IL
string realMethodName = method.Name;
- if (!method.IsPInvoke && method is TypeSystem.Ecma.EcmaMethod)
+ if (method.IsPInvoke)
+ {
+ string entrypointName = method.GetPInvokeMethodMetadata().Name;
+ if(!String.IsNullOrEmpty(entrypointName))
+ {
+ realMethodName = entrypointName;
+ }
+ }
+ else if (!method.IsPInvoke && method is TypeSystem.Ecma.EcmaMethod)
{
realMethodName = ((TypeSystem.Ecma.EcmaMethod)method).GetRuntimeImportName() ?? method.Name;
}
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs
index ad6bc1c78..5bbfc2906 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs
@@ -51,8 +51,9 @@ namespace Internal.IL
try
{
string mangledName;
- // TODO: We should use the startup node to generate StartupCodeMain and avoid special casing here
- if (methodCodeNodeNeedingCode.Method.Signature.IsStatic && methodCodeNodeNeedingCode.Method.Name == "Main")
+
+ // TODO: Better detection of the StartupCodeMain method
+ if (methodCodeNodeNeedingCode.Method.Signature.IsStatic && methodCodeNodeNeedingCode.Method.Name == "StartupCodeMain")
{
mangledName = "StartupCodeMain";
}
@@ -96,6 +97,17 @@ namespace Internal.IL
//methodCodeNodeNeedingCode.SetCode(sb.ToString(), Array.Empty<Object>());
}
+ // Uncomment the block below to get specific method failures when LLVM fails for cryptic reasons
+#if false
+ LLVMBool result = LLVM.VerifyFunction(ilImporter._llvmFunction, LLVMVerifierFailureAction.LLVMPrintMessageAction);
+ if (result.Value != 0)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"Error compliling {method.OwningType}.{method}");
+ Console.ResetColor();
+ }
+#endif // false
+
// Ensure dependencies show up regardless of exceptions to avoid breaking LLVM
methodCodeNodeNeedingCode.SetDependencies(ilImporter.GetDependencies());
}
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs
index 29a6a26cd..2bf071588 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs
@@ -225,6 +225,19 @@ namespace ILCompiler.DependencyAnalysis
throw new NotImplementedException();
}
+ private void EmitReadyToRunHeaderCallback()
+ {
+ LLVMTypeRef intPtr = LLVM.PointerType(LLVM.Int32Type(), 0);
+ LLVMTypeRef intPtrPtr = LLVM.PointerType(intPtr, 0);
+ var callback = LLVM.AddFunction(Module, "RtRHeaderWrapper", LLVM.FunctionType(intPtrPtr, new LLVMTypeRef[0], false));
+ var builder = LLVM.CreateBuilder();
+ var block = LLVM.AppendBasicBlock(callback, "Block");
+ LLVM.PositionBuilderAtEnd(builder, block);
+
+ LLVMValueRef rtrHeaderPtr = GetSymbolValuePointer(Module, _nodeFactory.ReadyToRunHeader, _nodeFactory.NameMangler, false);
+ LLVMValueRef castRtrHeaderPtr = LLVM.BuildPointerCast(builder, rtrHeaderPtr, intPtrPtr, "castRtrHeaderPtr");
+ LLVM.BuildRet(builder, castRtrHeaderPtr);
+ }
private void EmitNativeMain()
{
@@ -255,14 +268,24 @@ namespace ILCompiler.DependencyAnalysis
var shadowStack = LLVM.BuildMalloc(builder, LLVM.ArrayType(LLVM.Int8Type(), 1000000), String.Empty);
var castShadowStack = LLVM.BuildPointerCast(builder, shadowStack, LLVM.PointerType(LLVM.Int8Type(), 0), String.Empty);
LLVM.BuildStore(builder, castShadowStack, shadowStackTop);
+
+ // Pass on main arguments
+ var argcSlot = LLVM.BuildPointerCast(builder, shadowStack, LLVM.PointerType(LLVM.Int32Type(), 0), "argcSlot");
+ LLVM.BuildStore(builder, LLVM.GetParam(mainFunc, 0), argcSlot);
+ var argvSlot = LLVM.BuildGEP(builder, castShadowStack, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), 4, LLVMMisc.False) }, "argvSlot");
+ LLVM.BuildStore(builder, LLVM.GetParam(mainFunc, 1), LLVM.BuildPointerCast(builder, argvSlot, LLVM.PointerType(LLVM.PointerType(LLVM.Int8Type(), 0), 0), ""));
+
+ // StartupCodeMain will always return a value whether the user's main does or not
+ LLVMValueRef returnValueSlot = LLVM.BuildAlloca(builder, LLVM.Int32Type(), "returnValue");
+
LLVM.BuildCall(builder, managedMain, new LLVMValueRef[]
{
castShadowStack,
- LLVM.ConstPointerNull(LLVM.PointerType(LLVM.Int8Type(), 0))
+ LLVM.BuildPointerCast(builder, returnValueSlot, LLVM.PointerType(LLVM.Int8Type(), 0), String.Empty)
},
String.Empty);
- LLVM.BuildRet(builder, LLVM.ConstInt(LLVM.Int32Type(), 42, LLVMMisc.False));
+ LLVM.BuildRet(builder, LLVM.BuildLoad(builder, returnValueSlot, String.Empty));
LLVM.SetLinkage(mainFunc, LLVMLinkage.LLVMExternalLinkage);
}
@@ -705,6 +728,7 @@ namespace ILCompiler.DependencyAnalysis
try
{
+ objectWriter.EmitReadyToRunHeaderCallback();
//ObjectNodeSection managedCodeSection = null;
var listOfOffsets = new List<int>();