public Type(TypeReference typeReference, TypeDefinition typeDefinition, TypeRef dataType, TypeRef valueType, TypeRef objectType, StackValueType stackType) { TypeReferenceCecil = typeReference; TypeDefinitionCecil = typeDefinition; DataTypeLLVM = dataType; ObjectTypeLLVM = objectType; StackType = stackType; ValueTypeLLVM = valueType; DefaultTypeLLVM = stackType == StackValueType.Object ? LLVM.PointerType(ObjectTypeLLVM, 0) : DataTypeLLVM; switch (stackType) { case StackValueType.NativeInt: TypeOnStackLLVM = LLVM.PointerType(LLVM.Int8TypeInContext(LLVM.GetTypeContext(dataType)), 0); break; case StackValueType.Float: TypeOnStackLLVM = LLVM.DoubleTypeInContext(LLVM.GetTypeContext(dataType)); break; case StackValueType.Int32: TypeOnStackLLVM = LLVM.Int32TypeInContext(LLVM.GetTypeContext(dataType)); break; case StackValueType.Int64: TypeOnStackLLVM = LLVM.Int64TypeInContext(LLVM.GetTypeContext(dataType)); break; case StackValueType.Value: case StackValueType.Object: case StackValueType.Reference: TypeOnStackLLVM = DefaultTypeLLVM; break; } }
private ValueRef AllocateObject(Type type, StackValueType stackValueType = StackValueType.Unknown) { if (stackValueType == StackValueType.Unknown) { stackValueType = type.StackType; } // Resolve class var @class = GetClass(type); if (stackValueType != StackValueType.Object) { // Value types are allocated on the stack return(LLVM.BuildAlloca(builder, type.DataType, string.Empty)); } // TODO: Improve performance (better inlining, etc...) // Invoke malloc var typeSize = LLVM.BuildIntCast(builder, LLVM.SizeOf(type.ObjectType), int32Type, string.Empty); var allocatedData = LLVM.BuildCall(builder, allocObjectFunction, new[] { typeSize }, string.Empty); var allocatedObject = LLVM.BuildPointerCast(builder, allocatedData, LLVM.PointerType(type.ObjectType, 0), string.Empty); // Store vtable global into first field of the object var indices = new[] { LLVM.ConstInt(int32Type, 0, false), // Pointer indirection LLVM.ConstInt(int32Type, (int)ObjectFields.RuntimeTypeInfo, false), // Access RTTI }; var vtablePointer = LLVM.BuildInBoundsGEP(builder, allocatedObject, indices, string.Empty); LLVM.BuildStore(builder, @class.GeneratedRuntimeTypeInfoGlobal, vtablePointer); return(allocatedObject); }
public void Push(StackValueType vtype, long *obj) { *(long *)Esp->VPoint = *obj; Esp->ValueType = vtype; Esp++; EspI++; }
private ValueRef LoadValue(StackValueType stackType, ValueRef value, InstructionFlags instructionFlags) { // Load value from local (indirect values are kept as pointer) if (stackType == StackValueType.Value) { // Option1: Make a copy // TODO: Optimize stack allocation (reuse alloca slots, with help of FunctionStack) var result = LLVM.BuildAlloca(builderAlloca, LLVM.GetElementType(LLVM.TypeOf(value)), string.Empty); var valueCopy = LLVM.BuildLoad(builder, value, string.Empty); LLVM.BuildStore(builder, valueCopy, result); SetInstructionFlags(valueCopy, instructionFlags); return result; // Option2: Return pointer as is //return value; } else { var result = LLVM.BuildLoad(builder, value, string.Empty); SetInstructionFlags(result, instructionFlags); return result; } }
public void EvaluationStack_Push(StackValueType vtype, object value) { switch (vtype) { case StackValueType.Ref: EvaluationStack_Push(value); break; case StackValueType.Ptr: EvaluationStack_Push(value); break; case StackValueType.i8: EvaluationStack_Push((long)value); break; case StackValueType.r8: EvaluationStack_Push((double)value); break; case StackValueType.i4: EvaluationStack_Push((int)value); break; case StackValueType.r4: EvaluationStack_Push((float)value); break; } }
public void Push(StackValueType vtype, int *obj) { Esp->ValueType = vtype; *Esp->VPoint = *obj; Esp++; EspI++; }
public Type(TypeReference typeReference, TypeRef dataType, TypeRef objectType, StackValueType stackType) { TypeReference = typeReference; DataType = dataType; ObjectType = objectType; StackType = stackType; DefaultType = stackType == StackValueType.Object ? LLVM.PointerType(ObjectType, 0) : DataType; StackType = stackType; switch (stackType) { case StackValueType.NativeInt: TypeOnStack = LLVM.PointerType(LLVM.Int8TypeInContext(LLVM.GetTypeContext(dataType)), 0); break; case StackValueType.Float: TypeOnStack = LLVM.DoubleTypeInContext(LLVM.GetTypeContext(dataType)); break; case StackValueType.Int32: TypeOnStack = LLVM.Int32TypeInContext(LLVM.GetTypeContext(dataType)); break; case StackValueType.Int64: TypeOnStack = LLVM.Int64TypeInContext(LLVM.GetTypeContext(dataType)); break; case StackValueType.Value: case StackValueType.Object: case StackValueType.Reference: TypeOnStack = DefaultType; break; } }
public void Push(StackValueType vtype, int value) { var p = EvaluationStack[Esp++]; p.ValueType = vtype; p.IntValue = value; }
private void StoreValue(StackValueType stackType, ValueRef value, ValueRef dest, InstructionFlags instructionFlags) { if (stackType == StackValueType.Value) value = LLVM.BuildLoad(builder, value, string.Empty); var store = LLVM.BuildStore(builder, value, dest); SetInstructionFlags(store, instructionFlags); }
public Type(TypeReference typeReference, TypeRef dataType, TypeRef objectType, StackValueType stackType) { TypeReference = typeReference; DataType = dataType; ObjectType = objectType; StackType = stackType; DefaultType = stackType == StackValueType.Object ? LLVM.PointerType(ObjectType, 0) : DataType; StackType = stackType; }
public void EvaluationStack_Push(StackValueType vtype, object value) { if (vtype == StackValueType.i4) { Stack.Push(vtype, (int)value); } else { Stack.Push(vtype, value); } }
public void CopyFrom(StackItem stackItem) { Index = stackItem.Index; IntValue = stackItem.IntValue; LValue = stackItem.LValue; Ptr = stackItem.Ptr; #if JS VPoint = stackItem.VPoint; #endif ValueType = stackItem.ValueType; }
public virtual void Ldc(ref StackValueType vtype, ref object value) #endif { if (value is string) { value = Extensions.GetValueFromStr(value as string, vtype); } { EvaluationStack_Push(vtype, value); } }
/// <summary> /// 将位于指定数组索引处的 int8 类型的元素作为 int32 加载到计算堆栈的顶部。 /// </summary> /// <param name="type"></param> public void Ldelem(StackValueType type) { var vs = EvaluationStack_Pop(2); #if JS var array = (vs).Ptr.Object as Array; var index = (vs + 1).IntValue; #else var array = ((StackObject)(vs)->Ptr.Target).Object as Array; var index = (vs + 1)->IntValue; #endif EvaluationStack_Push(type, array.GetValue(index)); }
/// <summary> /// 存储所提供地址处的对象引用值 /// </summary> /// <param name="type"></param> public void Stind(StackValueType type) { var vs = Stack.Pop(2); var vsv = vs + 1; #if JS switch (vs.ValueType) { case StackValueType.Array: { var array = vs.Ptr.Object as Array; array.SetValue(vsv.Value, vs.Index); break; } case StackValueType.i4: case StackValueType.r4: case StackValueType.i8: case StackValueType.r8: case StackValueType.Ref: { break; } default: throw new NotSupportedException(); } #else switch (vs->ValueType) { case StackValueType.Array: { var array = ((StackObject)vs->Ptr.Target).Object as Array; array.SetValue(vsv->Value, vs->Index); break; } case StackValueType.i4: case StackValueType.r4: case StackValueType.i8: case StackValueType.r8: case StackValueType.Ref: { break; } default: throw new NotSupportedException(); } #endif }
public void Push(StackValueType vtype, object value) { var p = EvaluationStack[Esp++]; if (vtype == StackValueType.Ref || vtype == StackValueType.i4) { throw new NotSupportedException(); } else { p.ValueType = vtype; p.VPoint = value; } }
/// <summary> /// 将 int8 类型的值作为 int32 间接加载到计算堆栈上。 /// </summary> /// <param name="type"></param> public void Ldind(StackValueType type) { var vs = Stack.Top(); #if JS switch (vs.ValueType) { case StackValueType.Array: { var array = vs.Ptr.Object as Array; vs.SetValue(type, array.GetValue(vs.Index)); break; } case StackValueType.i4: case StackValueType.r4: case StackValueType.i8: case StackValueType.r8: case StackValueType.Ref: { break; } default: throw new NotSupportedException(); } #else switch (vs->ValueType) { case StackValueType.Array: { var array = ((StackObject)vs->Ptr.Target).Object as Array; vs->SetValue(type, array.GetValue(vs->Index)); break; } case StackValueType.i4: case StackValueType.r4: case StackValueType.i8: case StackValueType.r8: case StackValueType.Ref: { break; } default: throw new NotSupportedException(); } #endif }
private ValueRef[] BuildFieldIndices(Field field, StackValueType stackValueType, Type type) { // Build indices for GEP var indices = new List <ValueRef>(3); if (stackValueType == StackValueType.Reference || stackValueType == StackValueType.Object || stackValueType == StackValueType.NativeInt) { // First pointer indirection indices.Add(LLVM.ConstInt(int32Type, 0, false)); } if (stackValueType == StackValueType.Object) { // Access data indices.Add(LLVM.ConstInt(int32Type, (int)ObjectFields.Data, false)); // For now, go through hierarchy and check that type match // Other options: // - cast // - store class depth (and just do a substraction) int depth = 0; var @class = GetClass(type); while (@class != null) { if (@class == field.DeclaringClass) { break; } @class = @class.BaseType; depth++; } if (@class == null) { throw new InvalidOperationException(string.Format("Could not find field {0} in hierarchy of {1}", field.FieldDefinition, type.TypeReference)); } // Apply GEP indices to find right object (parent is always stored in first element) for (int i = 0; i < depth; ++i) { indices.Add(LLVM.ConstInt(int32Type, 0, false)); } } // Access the appropriate field indices.Add(LLVM.ConstInt(int32Type, (uint)field.StructIndex, false)); return(indices.ToArray()); }
public StackValueOperation(StackValueOperationType type, StackValueType valueType, IEnumerable <StackValue> operands) { ProcessedValue = true; ValueType = valueType; if (operands == null) { Operands = new List <StackValue>(); } else { Operands = new List <StackValue>(operands); } OperationType = type; }
public StackValueOperation(StackValueOperationType type, StackValueType valueType, IEnumerable<StackValue> operands) { ProcessedValue = true; ValueType = valueType; if (operands == null) { Operands = new List<StackValue>(); } else { Operands = new List<StackValue>(operands); } OperationType = type; }
/// <summary> /// 用计算堆栈上的 native int 值替换给定索引处的数组元素。 /// </summary> public void Stelem(StackValueType type) { var vs = EvaluationStack_Pop(3); #if JS var array = vs.Ptr.Object as Array; var index = (vs + 1).IntValue; var optr = (vs + 1 + 1); switch (optr.ValueType) { case StackValueType.Ref: { var obj = optr.Ptr.Object; array.SetValue(obj, index); break; } default: { var obj = optr.Value; array.SetValue(obj, index); break; } } #else var array = ((StackObject)(vs)->Ptr.Target).Object as Array; var index = (vs + 1)->IntValue; var optr = (vs + 1 + 1); switch (optr->ValueType) { case StackValueType.Ref: { var obj = ((StackObject)optr->Ptr.Target).Object; array.SetValue(obj, index); break; } default: { var obj = optr->Value; array.SetValue(obj, index); break; } } #endif }
public void SetValue(StackValueType vtype, object value) { switch (vtype) { case StackValueType.i4: { IntValue = (int)value; break; } case StackValueType.r4: case StackValueType.i8: case StackValueType.r8: VPoint = value; break; } }
public void SetValue(StackValueType vtype, object value, bool settype = false) { switch (vtype) { case StackValueType.i4: { IntValue = (int)value; break; } case StackValueType.r4: { var v = (float)value; *(float *)VPoint = v; break; } case StackValueType.i8: { var v = (long)value; *(long *)VPoint = v; break; } case StackValueType.r8: { var v = (double)value; *(double *)VPoint = v; break; } case StackValueType.Ref: { Ptr = StackObject.NewObject(value); break; } } if (settype) { ValueType = vtype; } }
public Class(Type type, TypeReference typeReference, TypeRef dataType, TypeRef objectType, StackValueType stackType) { Type = type; TypeReference = typeReference; DataType = dataType; ObjectType = objectType; StackType = stackType; DefaultType = stackType == StackValueType.Object ? LLVM.PointerType(ObjectType, 0) : DataType; Fields = new Dictionary <FieldDefinition, Field>(); VirtualTable = new List <Function>(); Functions = new List <Function>(); Interfaces = new HashSet <Class>(); switch (stackType) { case StackValueType.NativeInt: TypeOnStack = LLVM.PointerType(LLVM.Int8TypeInContext(LLVM.GetTypeContext(dataType)), 0); break; case StackValueType.Float: TypeOnStack = LLVM.DoubleTypeInContext(LLVM.GetTypeContext(dataType)); break; case StackValueType.Int32: TypeOnStack = LLVM.Int32TypeInContext(LLVM.GetTypeContext(dataType)); break; case StackValueType.Int64: TypeOnStack = LLVM.Int64TypeInContext(LLVM.GetTypeContext(dataType)); break; case StackValueType.Value: case StackValueType.Object: TypeOnStack = DefaultType; break; default: throw new NotImplementedException(); } }
public static object GetValueFromStr(string str, StackValueType vtype) { object value = null; switch (vtype) { case StackValueType.i8: value = long.Parse(str); break; case StackValueType.r8: value = double.Parse(str); break; case StackValueType.i4: if (str.StartsWith("0x")) { value = System.Convert.ToInt32(str, 16); } else if (str.StartsWith("M") || str.StartsWith("m")) { value = (-int.Parse(str)); } else { value = int.Parse(str); } break; case StackValueType.r4: value = float.Parse(str); break; } return(value); }
public void PushType(StackValueType vtype) { Esp->ValueType = vtype; }
private ValueRef AllocateObject(Type type, StackValueType stackValueType = StackValueType.Unknown) { if (stackValueType == StackValueType.Unknown) stackValueType = type.StackType; // Resolve class var @class = GetClass(type); if (stackValueType != StackValueType.Object) { // Value types are allocated on the stack return LLVM.BuildAlloca(builderAlloca, type.DataTypeLLVM, string.Empty); } // TODO: Improve performance (better inlining, etc...) // Invoke malloc var typeSize = LLVM.BuildIntCast(builder, LLVM.SizeOf(type.ObjectTypeLLVM), nativeIntLLVM, string.Empty); var allocatedData = LLVM.BuildCall(builder, allocObjectFunctionLLVM, new[] { typeSize }, string.Empty); var allocatedObject = LLVM.BuildPointerCast(builder, allocatedData, LLVM.PointerType(type.ObjectTypeLLVM, 0), string.Empty); SetupVTable(allocatedObject, @class); return allocatedObject; }
/// <summary> /// 存储所提供地址处的对象引用值 /// </summary> /// <param name="type"></param> public void Stind(StackValueType type) { var vs = Stack.Pop(2); var vsv = vs + 1; #if JS switch (vs.ValueType) { case StackValueType.Array: { var array = vs.Ptr.Object as Array; array.SetValue(vsv.Value, vs.Index); break; } case StackValueType.i4: case StackValueType.r4: case StackValueType.i8: case StackValueType.r8: case StackValueType.Ref: { break; } default: throw new NotSupportedException(); } #else if (vs->ValueType == StackValueType.Ref) { var value = StackObject.ToObject(vs); if (value is IntPtr) { var si = (StackItem *)((IntPtr)value).ToPointer(); vs = si; } else { } } switch (vs->ValueType) { case StackValueType.Array: { var array = ((StackObject)vs->Ptr.Target).Object as Array; array.SetValue(vsv->Value, vs->Index); break; } case StackValueType.i4: case StackValueType.r4: case StackValueType.i8: case StackValueType.r8: { vs->SetValue(vsv->ValueType, vsv->Value, true); break; } case StackValueType.Ref: { break; } default: throw new NotSupportedException(); } #endif }
/// <summary> /// 将 int8 类型的值作为 int32 间接加载到计算堆栈上。 /// </summary> /// <param name="type"></param> public void Ldind(StackValueType type) { var vs = Stack.Pop(); #if JS switch (vs.ValueType) { case StackValueType.Array: { var array = vs.Ptr.Object as Array; vs.SetValue(type, array.GetValue(vs.Index)); break; } case StackValueType.i4: case StackValueType.r4: case StackValueType.i8: case StackValueType.r8: case StackValueType.Ref: { break; } default: throw new NotSupportedException(); } #else if (vs->ValueType == StackValueType.Ref) { var value = StackObject.ToObject(vs); if (value is IntPtr) { var si = (StackItem *)((IntPtr)value).ToPointer(); vs = si; } else { } } switch (vs->ValueType) { case StackValueType.Array: { var array = ((StackObject)vs->Ptr.Target).Object as Array; vs->SetValue(type, array.GetValue(vs->Index)); break; } case StackValueType.i4: EvaluationStack_Push((int)(vs)->Value); break; case StackValueType.r4: EvaluationStack_Push((float)(vs)->Value); break; case StackValueType.i8: EvaluationStack_Push((long)(vs)->Value); break; case StackValueType.r8: { EvaluationStack_Push((double)(vs)->Value); break; } case StackValueType.Ref: { break; } default: throw new NotSupportedException(); } #endif }
/// <summary> /// 将位于计算堆栈顶部的值转换为Type /// </summary> /// <param name="type"></param> public void Conv(StackValueType type) { var v = EvaluationStack_Pop(); #if JS object value = v.IntValue; if (v.ValueType != StackValueType.i4) { value = v.VPoint; } #if !BRIDGE value = Convert.ChangeType(value, conveTypes[(int)type]); #else switch (type) { case StackValueType.u1: switch (v.ValueType) { case StackValueType.i4: value = (int)(byte)v.IntValue; break; case StackValueType.i8: value = (int)(byte)v.ValueLong; break; case StackValueType.r4: value = (int)(byte)v.ValueFloat; break; case StackValueType.r8: value = (int)(byte)v.ValueDouble; break; } break; case StackValueType.i1: switch (v.ValueType) { case StackValueType.i4: value = (int)(sbyte)v.IntValue; break; case StackValueType.i8: value = (int)(sbyte)v.ValueLong; break; case StackValueType.r4: value = (int)(sbyte)v.ValueFloat; break; case StackValueType.r8: value = (int)(sbyte)v.ValueDouble; break; } break; case StackValueType.u2: switch (v.ValueType) { case StackValueType.i4: value = (int)(ushort)v.IntValue; break; case StackValueType.i8: value = (int)(ushort)v.ValueLong; break; case StackValueType.r4: value = (int)(ushort)v.ValueFloat; break; case StackValueType.r8: value = (int)(ushort)v.ValueDouble; break; } break; case StackValueType.i2: switch (v.ValueType) { case StackValueType.i4: value = (int)(short)v.IntValue; break; case StackValueType.i8: value = (int)(short)v.ValueLong; break; case StackValueType.r4: value = (int)(short)v.ValueFloat; break; case StackValueType.r8: value = (int)(short)v.ValueDouble; break; } break; case StackValueType.u4: switch (v.ValueType) { case StackValueType.i4: value = (int)(uint)v.IntValue; break; case StackValueType.i8: value = (int)(uint)v.ValueLong; break; case StackValueType.r4: value = (int)(uint)v.ValueFloat; break; case StackValueType.r8: value = (int)(uint)v.ValueDouble; break; } break; case StackValueType.i4: switch (v.ValueType) { case StackValueType.i4: value = (int)v.IntValue; break; case StackValueType.i8: value = (int)v.ValueLong; break; case StackValueType.r4: value = (int)v.ValueFloat; break; case StackValueType.r8: value = (int)v.ValueDouble; break; } break; case StackValueType.r4: switch (v.ValueType) { case StackValueType.i4: { value = (float)v.IntValue; break; } case StackValueType.i8: { value = (float)v.ValueLong; break; } case StackValueType.r4: { value = (float)v.ValueFloat; break; } case StackValueType.r8: { value = (float)v.ValueDouble; break; } } break; case StackValueType.u8: switch (v.ValueType) { case StackValueType.i4: { value = (ulong)v.IntValue; break; } case StackValueType.i8: { value = (ulong)v.ValueLong; break; } case StackValueType.r4: { value = (ulong)v.ValueFloat; break; } case StackValueType.r8: { value = (ulong)v.ValueDouble; break; } } break; case StackValueType.i8: switch (v.ValueType) { case StackValueType.i4: { value = (long)v.IntValue; break; } case StackValueType.i8: { value = (long)v.ValueLong; break; } case StackValueType.r4: { value = (long)v.ValueFloat; break; } case StackValueType.r8: { value = (long)v.ValueDouble; break; } } break; case StackValueType.r8: switch (v.ValueType) { case StackValueType.i4: { value = (double)v.IntValue; break; } case StackValueType.i8: { value = (double)v.ValueLong; break; } case StackValueType.r4: { value = (double)v.ValueFloat; break; } case StackValueType.r8: { value = (double)v.ValueDouble; break; } } break; } #endif switch (type) { case StackValueType.i8: case StackValueType.r8: case StackValueType.r4: EvaluationStack_Push(type, value); break; default: EvaluationStack_Push(type, (int)value); break; } #else var rv = new StackItem(); rv.VPoint = &rv.IntValue; switch (type) { case StackValueType.u1: switch (v->ValueType) { case StackValueType.i4: rv.IntValue = (byte)v->IntValue; break; case StackValueType.i8: rv.IntValue = (byte)v->ValueLong; break; case StackValueType.r4: rv.IntValue = (byte)v->ValueFloat; break; case StackValueType.r8: rv.IntValue = (byte)v->ValueDouble; break; } break; case StackValueType.i1: switch (v->ValueType) { case StackValueType.i4: rv.IntValue = (sbyte)v->IntValue; break; case StackValueType.i8: rv.IntValue = (sbyte)v->ValueLong; break; case StackValueType.r4: rv.IntValue = (sbyte)v->ValueFloat; break; case StackValueType.r8: rv.IntValue = (sbyte)v->ValueDouble; break; } break; case StackValueType.u2: switch (v->ValueType) { case StackValueType.i4: rv.IntValue = (ushort)v->IntValue; break; case StackValueType.i8: rv.IntValue = (ushort)v->ValueLong; break; case StackValueType.r4: rv.IntValue = (ushort)v->ValueFloat; break; case StackValueType.r8: rv.IntValue = (ushort)v->ValueDouble; break; } break; case StackValueType.i2: switch (v->ValueType) { case StackValueType.i4: rv.IntValue = (short)v->IntValue; break; case StackValueType.i8: rv.IntValue = (short)v->ValueLong; break; case StackValueType.r4: rv.IntValue = (short)v->ValueFloat; break; case StackValueType.r8: rv.IntValue = (short)v->ValueDouble; break; } break; case StackValueType.u4: switch (v->ValueType) { case StackValueType.i4: rv.IntValue = (int)(uint)v->IntValue; break; case StackValueType.i8: rv.IntValue = (int)(uint)v->ValueLong; break; case StackValueType.r4: rv.IntValue = (int)(uint)v->ValueFloat; break; case StackValueType.r8: rv.IntValue = (int)(uint)v->ValueDouble; break; } break; case StackValueType.i4: switch (v->ValueType) { case StackValueType.i4: rv.IntValue = (int)v->IntValue; break; case StackValueType.i8: rv.IntValue = (int)v->ValueLong; break; case StackValueType.r4: rv.IntValue = (int)v->ValueFloat; break; case StackValueType.r8: rv.IntValue = (int)v->ValueDouble; break; } break; case StackValueType.r4: switch (v->ValueType) { case StackValueType.i4: { var f = (float)v->IntValue; rv.VPoint = (int *)&f; break; } case StackValueType.i8: { var f = (float)v->ValueLong; rv.VPoint = (int *)&f; break; } case StackValueType.r4: { var f = (float)v->ValueFloat; rv.VPoint = (int *)&f; break; } case StackValueType.r8: { var f = (float)v->ValueDouble; rv.VPoint = (int *)&f; break; } } break; case StackValueType.u8: switch (v->ValueType) { case StackValueType.i4: { var f = (ulong)v->IntValue; rv.VPoint = (int *)&f; break; } case StackValueType.i8: { var f = (ulong)v->ValueLong; rv.VPoint = (int *)&f; break; } case StackValueType.r4: { var f = (ulong)v->ValueFloat; rv.VPoint = (int *)&f; break; } case StackValueType.r8: { var f = (ulong)v->ValueDouble; rv.VPoint = (int *)&f; break; } } break; case StackValueType.i8: switch (v->ValueType) { case StackValueType.i4: { var f = (long)v->IntValue; rv.VPoint = (int *)&f; break; } case StackValueType.i8: { var f = (long)v->ValueLong; rv.VPoint = (int *)&f; break; } case StackValueType.r4: { var f = (long)v->ValueFloat; rv.VPoint = (int *)&f; break; } case StackValueType.r8: { var f = (long)v->ValueDouble; rv.VPoint = (int *)&f; break; } } break; case StackValueType.r8: switch (v->ValueType) { case StackValueType.i4: { var f = (double)v->IntValue; rv.VPoint = (int *)&f; break; } case StackValueType.i8: { var f = (double)v->ValueLong; rv.VPoint = (int *)&f; break; } case StackValueType.r4: { var f = (double)v->ValueFloat; rv.VPoint = (int *)&f; break; } case StackValueType.r8: { var f = (double)v->ValueDouble; rv.VPoint = (int *)&f; break; } } break; } EvaluationStack_Push(&rv); #endif }
private ValueRef[] BuildFieldIndices(Field field, StackValueType stackValueType, Type type) { // Build indices for GEP var indices = new List<ValueRef>(3); if (stackValueType == StackValueType.Reference || stackValueType == StackValueType.Object || stackValueType == StackValueType.NativeInt) { // First pointer indirection indices.Add(LLVM.ConstInt(int32Type, 0, false)); } if (stackValueType == StackValueType.Object) { // Access data indices.Add(LLVM.ConstInt(int32Type, (int)ObjectFields.Data, false)); // For now, go through hierarchy and check that type match // Other options: // - cast // - store class depth (and just do a substraction) int depth = 0; var @class = GetClass(type); while (@class != null) { if (@class == field.DeclaringClass) break; @class = @class.BaseType; depth++; } if (@class == null) throw new InvalidOperationException(string.Format("Could not find field {0} in hierarchy of {1}", field.FieldDefinition, type.TypeReference)); // Apply GEP indices to find right object (parent is always stored in first element) for (int i = 0; i < depth; ++i) indices.Add(LLVM.ConstInt(int32Type, 0, false)); } // Access the appropriate field indices.Add(LLVM.ConstInt(int32Type, (uint)field.StructIndex, false)); return indices.ToArray(); }
public StackValue(StackValueType stackType, Type type, ValueRef value) { StackType = stackType; Type = type; Value = value; }
private ValueRef ComputeFieldAddress(BuilderRef builder, Field field, StackValueType objectStackType, ValueRef objectValue, ref InstructionFlags instructionFlags) { objectValue = ConvertReferenceToExpectedType(builder, objectStackType, objectValue, field.DeclaringType); Type type = field.DeclaringType; // Build indices for GEP var indices = new List<ValueRef>(3); if (objectStackType == StackValueType.Reference || objectStackType == StackValueType.Object || objectStackType == StackValueType.Value || objectStackType == StackValueType.NativeInt) { // First pointer indirection indices.Add(LLVM.ConstInt(int32LLVM, 0, false)); } bool isCustomLayout = IsCustomLayout(type.TypeDefinitionCecil); if (objectStackType == StackValueType.Object) { // Access data indices.Add(LLVM.ConstInt(int32LLVM, (int)ObjectFields.Data, false)); if (!isCustomLayout) { // For now, go through hierarchy and check that type match // Other options: // - cast // - store class depth (and just do a substraction) int depth = 0; var @class = GetClass(type); while (@class != null) { if (@class.Type == field.DeclaringType) break; @class = @class.BaseType; depth++; } if (@class == null) throw new InvalidOperationException(string.Format("Could not find field {0} in hierarchy of {1}", field.FieldDefinition, type.TypeReferenceCecil)); // Apply GEP indices to find right object (parent is always stored in first element) for (int i = 0; i < depth; ++i) indices.Add(LLVM.ConstInt(int32LLVM, 0, false)); } } // Access the appropriate field indices.Add(LLVM.ConstInt(int32LLVM, (uint)field.StructIndex, false)); // Find field address using GEP var fieldAddress = LLVM.BuildInBoundsGEP(builder, objectValue, indices.ToArray(), string.Empty); // Cast to real field type (if stored in a custom layout array) if (isCustomLayout) { fieldAddress = LLVM.BuildPointerCast(builder, fieldAddress, LLVM.PointerType(field.Type.DefaultTypeLLVM, 0), string.Empty); // Check if non aligned if (field.StructIndex % 4 != 0) instructionFlags = InstructionFlags.Unaligned; } return fieldAddress; }
private ValueRef AllocateObject(Type type, StackValueType stackValueType = StackValueType.Unknown) { if (stackValueType == StackValueType.Unknown) stackValueType = type.StackType; // Resolve class var @class = GetClass(type); if (stackValueType != StackValueType.Object) { // Value types are allocated on the stack return LLVM.BuildAlloca(builder, type.DataType, string.Empty); } // TODO: Improve performance (better inlining, etc...) // Invoke malloc var typeSize = LLVM.BuildIntCast(builder, LLVM.SizeOf(type.ObjectType), int32Type, string.Empty); var allocatedData = LLVM.BuildCall(builder, allocObjectFunction, new[] { typeSize }, string.Empty); var allocatedObject = LLVM.BuildPointerCast(builder, allocatedData, LLVM.PointerType(type.ObjectType, 0), string.Empty); // Store vtable global into first field of the object var indices = new[] { LLVM.ConstInt(int32Type, 0, false), // Pointer indirection LLVM.ConstInt(int32Type, (int)ObjectFields.RuntimeTypeInfo, false), // Access RTTI }; var vtablePointer = LLVM.BuildInBoundsGEP(builder, allocatedObject, indices, string.Empty); LLVM.BuildStore(builder, @class.GeneratedRuntimeTypeInfoGlobal, vtablePointer); return allocatedObject; }
/// <summary> /// 压入数据 压入Evaluation Stack中 /// </summary> /// <param name="vtype"></param> /// <param name="value"></param> #if BRIDGE public virtual void Ldc(StackValueType vtype, object value)
/// <summary> /// 合并指令 把一个值压入局部变量 /// </summary> /// <param name="type">压入类型</param> /// <param name="lv">值</param> /// <param name="si">局部变量索引</param> public virtual void LdcStloc(ref StackValueType vtype, ref object value, ref int si) { long ptr = 0; long *pvalue = &ptr; if (value is string) { var str = value as string; switch (vtype) { case StackValueType.i8: value = long.Parse(str); *pvalue = (long)value; break; case StackValueType.r8: value = double.Parse(str); break; case StackValueType.i4: if (str.StartsWith("0x")) { value = System.Convert.ToInt32(str, 16); } else if (str.StartsWith("M") || str.StartsWith("m")) { value = (-int.Parse(str)); } else { value = int.Parse(str); } break; case StackValueType.r4: value = float.Parse(str); break; } } { switch (vtype) { case StackValueType.i8: *pvalue = (long)value; break; case StackValueType.r8: { var dv = (double)value; pvalue = (long *)&dv; } break; case StackValueType.i4: { var dv = (int)value; pvalue = (long *)&dv; } break; case StackValueType.r4: { var dv = (float)value; pvalue = (long *)&dv; } break; } } #if JS CallStack[(Csp + si)].IntValue = lv; #else *(long *)(Csp + si)->VPoint = *pvalue; (Csp + si)->ValueType = vtype; #endif }
private ValueRef ConvertReferenceToExpectedType(BuilderRef builder, StackValueType stackValueType, ValueRef value, Type type) { var expectedType = stackValueType == StackValueType.Object ? LLVM.PointerType(type.ObjectTypeLLVM, 0) : LLVM.PointerType(type.ValueTypeLLVM, 0); if (LLVM.TypeOf(value) == expectedType) return value; return LLVM.BuildPointerCast(builder, value, expectedType, string.Empty); }