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

Cil llvm trans #32

Merged
merged 1 commit into from
Aug 3, 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
2 changes: 1 addition & 1 deletion mcs/class/Mono.Compiler/Mono.Compiler.BigStep/BigStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public CompilationResult CompileMethod (MethodInfo methodInfo, out NativeCodeHan
try
{
BitCodeEmitter processor = new BitCodeEmitter (RuntimeInfo, methodInfo) {
// PrintDebugInfo = true,
//PrintDebugInfo = true,
VerifyGeneratedCode = true
};
CILSymbolicExecutor exec = new CILSymbolicExecutor (processor, RuntimeInfo, methodInfo);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,12 @@ private void Pass2 ()
opParam = iter.DecodeParamI ();
operands.Add (args[opParam]);
break;
case Opcode.LdelemI4:
// Assumption: the first operand is an array. CLR should guarantee this.
Type t = tempOds[0].Type.AsSystemType;
t = t.GetElementType();
output = new TempOperand (this, RuntimeInformation.ClrTypeFromType(t));
break;
case Opcode.Ldsfld:
int token = iter.DecodeParamI ();
FieldInfo fieldInfo = runtime.GetFieldInfoForToken (methodInfo, token);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,38 @@ public void Process (OperationInfo opInfo)
return new NamedTempValue (tmp, tempName);
});
break;
case Opcode.LdelemI1:
// load element from array
// tmp (array), tmp (index) => tmp
InvokeOperation (op, exop, operands,
vm => {
return GetIntArrayElement(operands[0].Type, 1, tempName, vm.Temp0, vm.Temp1);
});
break;
case Opcode.LdelemI2:
// load element from array
// tmp (array), tmp (index) => tmp
InvokeOperation (op, exop, operands,
vm => {
return GetIntArrayElement(operands[0].Type, 2, tempName, vm.Temp0, vm.Temp1);
});
break;
case Opcode.LdelemI4:
// load element from array
// tmp (array), tmp (index) => tmp
InvokeOperation (op, exop, operands,
vm => {
return GetIntArrayElement(operands[0].Type, 4, tempName, vm.Temp0, vm.Temp1);
});
break;
case Opcode.LdelemI8:
// load element from array
// tmp (array), tmp (index) => tmp
InvokeOperation (op, exop, operands,
vm => {
return GetIntArrayElement(operands[0].Type, 8, tempName, vm.Temp0, vm.Temp1);
});
break;
case Opcode.Ldsfld:
// const => tmp
int token = (operands[0] as Int32ConstOperand).Value;
Expand Down Expand Up @@ -630,6 +662,27 @@ private void AllocateArgsAndLocals (LLVMTypeRef[] args, IList<LocalVariableInfo>
}
}

private NamedTempValue GetIntArrayElement(
ClrType arrayClrType, uint elementSize, string resultValueName, LLVMValueRef arrayBaseAddr, LLVMValueRef index)
{
// Get array's base address
// The trick is to treat the metadata also as array elements and use GEP to perform pointer arithmetics
LLVMValueRef offset = LLVM.ConstInt(
LLVM.Int32Type(), RuntimeInfo.GetArrayBaseOffset(arrayClrType) / elementSize, false);
LLVMValueRef basePtr = LLVM.BuildGEP (
builder, arrayBaseAddr, new LLVMValueRef[] { offset }, this.NextTempName);

// Array access is translated to two LLVM operations:
// (1) get element address
// %tmpPtr = getelementptr i32, i32* %tmp0, i64 %tmp1
// (2) get element data
// %result = load i32, i32* %tmpPtr
LLVMValueRef tmpPtr = LLVM.BuildGEP (builder, basePtr, new LLVMValueRef[] { index }, this.NextTempName);
//LLVM.ConstPtrToInt()
LLVMValueRef tmp = LLVM.BuildLoad (builder, tmpPtr, resultValueName);
return new NamedTempValue (tmp, resultValueName);
}

private Tuple<LLVMValueRef, LLVMBasicBlockRef, LLVMBasicBlockRef> CompareAndJumpTo (
LLVMRealPredicate rprd, LLVMIntPredicate prd, IOperand[] operands, ValueMappings vm, int pcIndex)
{
Expand Down Expand Up @@ -789,14 +842,18 @@ private LLVMValueRef GetConstValue (IOperand operand)
return LLVM.ConstReal (LLVM.FloatType (), ((Float64ConstOperand)cod).Value);
}

throw new Exception ("Unexpected. The const operand is tno recognized.");
throw new Exception ("Unexpected. The const operand is not recognized.");
}

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

/// Translate a CLR type to an LLVM type. Basically,
/// - Primitive types will be mapped to their counterparts in LLVM
/// - Non-array class types are all mapped to pointer types
/// - Array types are mapped to pointer types of the mapped element types
private static LLVMTypeRef TranslateType (ClrType ctyp)
{
if (ctyp == RuntimeInformation.BoolType) {
Expand All @@ -805,7 +862,7 @@ private static LLVMTypeRef TranslateType (ClrType ctyp)
if (ctyp == RuntimeInformation.Int8Type) {
return LLVM.Int8Type ();
}
if (ctyp == RuntimeInformation.Int16Type || ctyp == RuntimeInformation.Int8Type) {
if (ctyp == RuntimeInformation.Int16Type || ctyp == RuntimeInformation.UInt8Type) {
return LLVM.Int16Type ();
}
if (ctyp == RuntimeInformation.Int32Type || ctyp == RuntimeInformation.UInt16Type) {
Expand All @@ -832,6 +889,13 @@ private static LLVMTypeRef TranslateType (ClrType ctyp)
}

Type typ = ctyp.AsSystemType;
if (typ.IsArray) {
// If this is array, recursively call this method to drill down the subtypes. Our goal
// is to make an LLVM pointer type which maps exactly all the dimensions of the array.
typ = typ.GetElementType();
ctyp = RuntimeInformation.ClrTypeFromType(typ);
return LLVM.PointerType(TranslateType (ctyp), 0); // 0 = default address sapce
}
if (typ.IsClass) {
return LLVM.PointerType(LLVM.Int64Type (), 0); // 0 = default address sapce
}
Expand Down
3 changes: 3 additions & 0 deletions mcs/class/Mono.Compiler/Mono.Compiler/IRuntimeInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@ public interface IRuntimeInformation
FieldInfo GetFieldInfoForToken (MethodInfo mi, int token);

IntPtr ComputeFieldAddress (FieldInfo fi);

/// For a given array type, get the offset of the vector relative to the base address.
uint GetArrayBaseOffset(ClrType type);
}
}
11 changes: 11 additions & 0 deletions mcs/class/Mono.Compiler/Mono.Compiler/RuntimeInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ public FieldInfo GetFieldInfoForToken (MethodInfo mi, int token) {
return new FieldInfo (srfi);
}

/// (mono/metadata/object-internals.h)
/// struct _MonoArray { // Base
/// MonoObject obj; // 16 bytes
/// MonoArrayBounds *bounds; // 8 bytes
/// mono_array_size_t max_length; // 8 bytes
/// mono_64bitaligned_t vector [MONO_ZERO_LEN_ARRAY]; // Start of vector
/// }
public uint GetArrayBaseOffset(ClrType type){
return 32;
}

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

Expand Down
13 changes: 13 additions & 0 deletions mcs/class/Mono.Compiler/Test/ICompilerInterfaceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ public static int WhileLoop1 (int times, int unit) {
return result;
}

public static int ArrayAccess1 (int[] array, int index) {
int result = array[index];
return result;
}

[Test]
public void TestArrayAccess1 () {
int[] array = new int[]{4937, 5443, 6673, 7561};
InstalledRuntimeCode irc = CompileCode("ArrayAccess1");
int result = (int) runtimeInfo.ExecuteInstalledMethod (irc, array, 2);
Assert.AreEqual (6673, result);
}

[Test]
public void TestWhileLoop1 () {
InstalledRuntimeCode irc = CompileCode("WhileLoop1");
Expand Down