Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static field load for int32 fields for new backend #29

Merged
merged 4 commits into from
Jul 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions mcs/class/Mono.Compiler/Mono.Compiler.BigStep/BigStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ public CompilationResult CompileMethod (MethodInfo methodInfo, out NativeCodeHan
result = NativeCodeHandle.Invalid;
try
{
BitCodeEmitter processor = new BitCodeEmitter(methodInfo){
BitCodeEmitter processor = new BitCodeEmitter (RuntimeInfo, methodInfo) {
// PrintDebugInfo = true,
VerifyGeneratedCode = true
};
CILSymbolicExecutor exec = new CILSymbolicExecutor(processor, RuntimeInfo, methodInfo);
CILSymbolicExecutor exec = new CILSymbolicExecutor (processor, RuntimeInfo, methodInfo);
exec.Execute();
result = processor.Yield();
return CompilationResult.Ok;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace Mono.Compiler.BigStep {
public class CILSymbolicExecutor : INameGenerator {
private IOperationProcessor processor;
private IRuntimeInformation runtime;
private MethodInfo methodInfo;
private MethodBody body;

private Stack<TempOperand> stack;
Expand All @@ -40,6 +41,7 @@ public CILSymbolicExecutor(IOperationProcessor processor, IRuntimeInformation ru
{
this.processor = processor;
this.runtime = runtime;
this.methodInfo = methodInfo;
this.body = methodInfo.Body;

this.stack = new Stack<TempOperand>();
Expand Down Expand Up @@ -309,6 +311,12 @@ private void Pass2 ()
operands.Add (locals[opParam]);
break;
// TODO: ExtendedOpcode.Stloc
case Opcode.Ldsfld:
int token = iter.DecodeParamI ();
FieldInfo fieldInfo = runtime.GetFieldInfoForToken (methodInfo, token);
operands.Add (new Int32ConstOperand (token));
output = new TempOperand (this, runtime.Int32Type); /* FIXME: look up the field info! */
break;
}

// 2) Determine the result type for values to push into stack
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ public class BitCodeEmitter : IOperationProcessor {
public bool PrintDebugInfo { get; set; }
public bool VerifyGeneratedCode { get; set; }

public BitCodeEmitter (MethodInfo method)
internal MethodInfo MethodInfo { get; }
internal IRuntimeInformation RuntimeInfo { get; }

public BitCodeEmitter (IRuntimeInformation runtimeInfo, MethodInfo method)
{
RuntimeInfo = runtimeInfo;
MethodInfo = method;
int seq = Interlocked.Increment (ref s_moduleSeq);
string modName = "llvmmodule_" + seq;
module = LLVM.ModuleCreateWithName(modName);
Expand Down Expand Up @@ -200,6 +205,22 @@ public void Process (OperationInfo opInfo)
return new NamedTempValue (tmp, tempName);
});
break;
case Opcode.Ldsfld:
// const => tmp
int token = (operands[0] as Int32ConstOperand).Value;
InvokeOperation (op, exop, operands,
vm => {
// TODO: It would be nice if operand[0] just carried the fieldInfo here
FieldInfo fieldInfo = RuntimeInfo.GetFieldInfoForToken (MethodInfo, token);

LLVMValueRef fieldAddress = GetConstValue (RuntimeInfo.ComputeFieldAddress (fieldInfo));

LLVMTypeRef fieldType = LLVM.Int32Type (); /* FIXME: get from field info */
LLVMValueRef address = LLVM.ConstIntToPtr (fieldAddress, LLVM.PointerType (fieldType, 0));
LLVMValueRef tmp = LLVM.BuildLoad (builder, address, tempName);
return new NamedTempValue (tmp, tempName);
});
break;
case Opcode.Add:
case Opcode.AddOvf: // TODO - Handle overflow
case Opcode.AddOvfUn: // TODO - Handle overflow, unsigned
Expand Down Expand Up @@ -456,6 +477,11 @@ private LLVMValueRef GetConstValue (IOperand operand)
throw new Exception ("Unexpected. The const operand is tno recognized.");
}

private LLVMValueRef GetConstValue (IntPtr constant)
{
return LLVM.ConstInt (TranslateType (RuntimeInformation.NativeIntType), (ulong)constant, true);
}

private static LLVMTypeRef TranslateType (ClrType ctyp)
{
if (ctyp == RuntimeInformation.BoolType) {
Expand All @@ -480,6 +506,7 @@ private static LLVMTypeRef TranslateType (ClrType ctyp)
return LLVM.FloatType ();
}
if (ctyp == RuntimeInformation.NativeIntType || ctyp == RuntimeInformation.NativeUnsignedIntType) {
/* FIXME: target platform dependent */
return LLVM.Int64Type ();
}
if (ctyp == RuntimeInformation.StringType) {
Expand Down
1 change: 1 addition & 0 deletions mcs/class/Mono.Compiler/Mono.Compiler.dll.sources
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Mono.Compiler/CompilationResult.cs
Mono.Compiler/ICompiler.cs
Mono.Compiler/IRuntimeInformation.cs
Mono.Compiler/InstalledRuntimeCode.cs
Mono.Compiler/FieldInfo.cs
Mono.Compiler/ManagedJIT.cs
Mono.Compiler/MethodInfo.cs
Mono.Compiler/NativeCodeHandle.cs
Expand Down
22 changes: 22 additions & 0 deletions mcs/class/Mono.Compiler/Mono.Compiler/FieldInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;

namespace Mono.Compiler
{
public class FieldInfo
{
internal System.Reflection.FieldInfo srFieldInfo;
public ClassInfo Parent { get; }

internal FieldInfo (System.Reflection.FieldInfo srfi) {
this.srFieldInfo = srfi;
this.Parent = ClassInfo.FromType (srfi.DeclaringType);
}

public bool IsStatic {
get {
return srFieldInfo.IsStatic;
}
}

}
}
4 changes: 4 additions & 0 deletions mcs/class/Mono.Compiler/Mono.Compiler/IRuntimeInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public interface IRuntimeInformation

MethodInfo GetMethodInfoFor (ClassInfo classInfo, string methodName);

FieldInfo GetFieldInfoForToken (MethodInfo mi, int token);

IntPtr ComputeFieldAddress (FieldInfo fi);

ClrType VoidType { get; }

ClrType Int32Type { get; }
Expand Down
17 changes: 17 additions & 0 deletions mcs/class/Mono.Compiler/Mono.Compiler/RuntimeInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ public MethodInfo GetMethodInfoFor (ClassInfo classInfo, string methodName) {
return classInfo.GetMethodInfoFor (methodName);
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
static extern System.Reflection.FieldInfo GetSRFieldInfoForToken (RuntimeMethodHandle handle, int token);

public FieldInfo GetFieldInfoForToken (MethodInfo mi, int token) {
System.Reflection.FieldInfo srfi = GetSRFieldInfoForToken (mi.RuntimeMethodHandle, token);
return new FieldInfo (srfi);
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
static extern IntPtr ComputeStaticFieldAddress (RuntimeFieldHandle handle);

public IntPtr ComputeFieldAddress (FieldInfo fi) {
if (!fi.IsStatic)
throw new InvalidOperationException ("field isn't static");
return ComputeStaticFieldAddress (fi.srFieldInfo.FieldHandle);
}

/* Primitive types */
public ClrType VoidType { get => ClrTypeFromType (typeof (void)); }
public ClrType Int32Type { get => ClrTypeFromType (typeof (System.Int32)); }
Expand Down
4 changes: 4 additions & 0 deletions mcs/class/Mono.Compiler/SimpleJit.Metadata/ClrType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,9 @@ public override int GetHashCode ()
return !left.Equals (right);
}

public static ClrType MakePointerType (ClrType ty)
{
return new ClrType (ty.AsSystemType.MakePointerType ().TypeHandle);
}
}
}
20 changes: 20 additions & 0 deletions mcs/class/Mono.Compiler/Test/ICompilerInterfaceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public static int AddMethod3 (int a, int b, int c) {
return a + b + c;
}

public static int staticField = 0x1337;
public static int StaticFieldReadMethod () {
return staticField;
}

[Test]
public void TestAddMethod () {
ClassInfo ci = runtimeInfo.GetClassInfoFor (typeof (ICompilerTests).AssemblyQualifiedName);
Expand Down Expand Up @@ -184,5 +189,20 @@ public unsafe void TestIdentity () {
Assert.AreEqual (typeof(int), o.GetType ());
Assert.AreEqual (42, (int)o);
}

[Test]
public unsafe void TestStaticFieldRead () {
ClassInfo ci = runtimeInfo.GetClassInfoFor (typeof (ICompilerTests).AssemblyQualifiedName);
MethodInfo mi = runtimeInfo.GetMethodInfoFor (ci, "StaticFieldReadMethod");

NativeCodeHandle nativeCode;

var result = compiler.CompileMethod (runtimeInfo, mi, CompilationFlags.None, out nativeCode);
InstalledRuntimeCode irc = runtimeInfo.InstallCompilationResult (result, mi, nativeCode);
var o = runtimeInfo.ExecuteInstalledMethod (irc);
Assert.IsNotNull (o);
Assert.AreEqual (typeof(int), o.GetType ());
Assert.AreEqual (0x1337, (int)o);
}
}
}
4 changes: 4 additions & 0 deletions mono/metadata/icall-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ HANDLES(ICALL(NATIVEMETHODS_9, "SetProcessWorkingSetSize", ves_icall_Microsoft_W
HANDLES(ICALL(NATIVEMETHODS_10, "TerminateProcess", ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess))
HANDLES(ICALL(NATIVEMETHODS_11, "WaitForInputIdle", ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle))

ICALL_TYPE(COMPILERRTINFO, "Mono.Compiler.RuntimeInformation", COMPILERRTINFO_1)
HANDLES(ICALL(COMPILERRTINFO_1, "ComputeStaticFieldAddress", ves_icall_Mono_Compiler_RuntimeInformation_ComputeStaticFieldAddress))
HANDLES(ICALL(COMPILERRTINFO_2, "GetSRFieldInfoForToken", ves_icall_Mono_Compiler_RuntimeInformation_GetSRFieldInfoForToken))

#ifndef DISABLE_COM
ICALL_TYPE(COMPROX, "Mono.Interop.ComInteropProxy", COMPROX_1)
HANDLES(ICALL(COMPROX_1, "AddProxy", ves_icall_Mono_Interop_ComInteropProxy_AddProxy))
Expand Down
28 changes: 28 additions & 0 deletions mono/metadata/icall.c
Original file line number Diff line number Diff line change
Expand Up @@ -5681,6 +5681,34 @@ ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname, gboolea
g_free (aname);
}

ICALL_EXPORT MonoReflectionFieldHandle
ves_icall_Mono_Compiler_RuntimeInformation_GetSRFieldInfoForToken (MonoMethod *method, int token, MonoError *error)
{
MonoGenericContext generic_context;
MonoClass *klass = NULL;
MonoImage *image = m_class_get_image (method->klass);

MonoClassField *field = mono_field_from_token_checked (image, token, &klass, &generic_context, error);
g_assert (field);

return mono_field_get_object_handle (mono_domain_get (), field->parent, field, error);
}

ICALL_EXPORT gpointer
ves_icall_Mono_Compiler_RuntimeInformation_ComputeStaticFieldAddress (MonoClassField *field)
{
// TODO: check mono_class_static_field_address in jit-icalls.c
ERROR_DECL (error);
MonoDomain *domain = mono_domain_get ();

mono_class_init (field->parent);
MonoVTable *vtable = mono_class_vtable_checked (domain, field->parent, error);

gpointer addr = ((char *) mono_vtable_get_static_field_data (vtable) + field->offset);
// g_print ("the address: %p, value: %p\n", addr, *(guint64 *) addr);
return addr;
}

ICALL_EXPORT void
ves_icall_Mono_Runtime_DisableMicrosoftTelemetry (MonoError *error)
{
Expand Down