internal void ProcessStoreLoc(FunctionContext funcContext, BuilderStackItem stackItem, int localVariableIndex) { var localVariableType = funcContext.LocalVariableTypes[localVariableIndex]; var localVariable = funcContext.LocalVariables[localVariableIndex]; //TODO: Need a better way to compare... if (localVariableType.IsPointer) { var resolvePtrType = Context.TypeResolver.Resolve(localVariableType); var store = ProcessStore(funcContext, LLVM.BuildIntToPtr(funcContext.Builder, stackItem.ValRef.Value, resolvePtrType, "IntPtr"), localVariable); Context.CLRLogger.Debug( $"[Stloc_{localVariableIndex}] -> Popped {stackItem.ValRef.Value.TypeOf()} and Stored {store}"); } else { var store = ProcessStore(funcContext, stackItem.ValRef.Value, localVariable); Context.CLRLogger.Debug( $"[Stloc_{localVariableIndex}] -> Popped {stackItem.ValRef.Value.TypeOf()} and Stored {store}"); } }
public override BuildResult Build(Instruction instruction, FunctionContext funcContext) { if (instruction.OpCode == OpCodes.Ldloca_S) { var def = (VariableDefinition)instruction.Operand; var stackItem = new BuilderStackItem(funcContext.MethodDef.Body.Variables[def.Index].VariableType, funcContext.LocalVariables[def.Index]); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Ldloca_S {def.Index}] -> Pushed Local Variable {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldloc_S) { var def = (VariableDefinition)instruction.Operand; var stackItem = new BuilderStackItem(funcContext.MethodDef.Body.Variables[def.Index].VariableType, LLVM.BuildLoad(funcContext.Builder, funcContext.LocalVariables[def.Index], "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Ldloc_S {def.Index}] -> Pushed Local Variable {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldloc_0) { var stackItem = new BuilderStackItem(funcContext.MethodDef.Body.Variables[0].VariableType, LLVM.BuildLoad(funcContext.Builder, funcContext.LocalVariables[0], "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug($"[Ldloc_0] -> Pushed Local Variable {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldloc_1) { var stackItem = new BuilderStackItem(funcContext.MethodDef.Body.Variables[1].VariableType, LLVM.BuildLoad(funcContext.Builder, funcContext.LocalVariables[1], "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug($"[Ldloc_1] -> Pushed Local Variable {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldloc_2) { var stackItem = new BuilderStackItem(funcContext.MethodDef.Body.Variables[2].VariableType, LLVM.BuildLoad(funcContext.Builder, funcContext.LocalVariables[2], "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug($"[Ldloc_2] -> Pushed Local Variable {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldloc_3) { var stackItem = new BuilderStackItem(funcContext.MethodDef.Body.Variables[3].VariableType, LLVM.BuildLoad(funcContext.Builder, funcContext.LocalVariables[3], "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug($"[Ldloc_3] -> Pushed Local Variable {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Stloc_0) { var val = funcContext.BuilderStack.Pop(); ProcessStoreLoc(funcContext, val, 0); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Stloc_1) { var val = funcContext.BuilderStack.Pop(); ProcessStoreLoc(funcContext, val, 1); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Stloc_2) { var val = funcContext.BuilderStack.Pop(); ProcessStoreLoc(funcContext, val, 2); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Stloc_3) { var val = funcContext.BuilderStack.Pop(); ProcessStoreLoc(funcContext, val, 3); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Stloc_S) { var index = (VariableDefinition)instruction.Operand; var val = funcContext.BuilderStack.Pop(); ProcessStoreLoc(funcContext, val, index.Index); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Stind_I1) { var val = funcContext.BuilderStack.Pop(); var cast = LLVM.BuildZExt(funcContext.Builder, val.ValRef.Value, LLVM.Int8Type(), ""); var address = funcContext.BuilderStack.Pop(); var ptr = address.ValRef.Value; if (address.ValRef.Value.TypeOf().TypeKind != LLVMTypeKind.LLVMPointerTypeKind) { ptr = LLVM.BuildIntToPtr(funcContext.Builder, address.ValRef.Value, LLVM.PointerType(LLVM.Int8Type(), 0), ""); } var store = ProcessStore(funcContext, cast, ptr); Context.CLRLogger.Debug( $"[Stind_I1] -> Popped {val.ValRef.Value} and {address.ValRef.Value} and Stored into address: {store}"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Stfld) { var fieldDef = (FieldDefinition)instruction.Operand; var value = funcContext.BuilderStack.Pop(); var structRef = funcContext.BuilderStack.Pop(); if (value.ValRef.Value.IsNull()) { throw new Exception( "The Value/Reference returned as null thus cannot be stored in Struct!"); } if (structRef.ValRef.Value.IsNull()) { throw new Exception( "The Value/Reference returned as null thus cannot be stored in Struct!"); } var index = (uint)Array.IndexOf( Context.FullSymbolToTypeRef[fieldDef.DeclaringType.FullName].CS_FieldDefs, Context.FullSymbolToTypeRef[fieldDef.DeclaringType.FullName].CS_FieldDefs .First(I => I.Name == fieldDef.Name)); var refToStruct = structRef.ValRef.Value; LLVMValueRef offset; if (fieldDef.DeclaringType.IsClass) { offset = LLVM.BuildLoad(funcContext.Builder, refToStruct, ""); } offset = LLVM.BuildStructGEP(funcContext.Builder, refToStruct, index, structRef.Type.Name); ProcessStore(funcContext, value.ValRef.Value, offset); Context.CLRLogger.Debug( $"[Stfld {fieldDef.FullName}] -> Popped {value.ValRef.Value} and {refToStruct.TypeOf()} and Store {value.ValRef.Value} into {offset}"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldfld) { var fieldDef = (FieldDefinition)instruction.Operand; var structRef = funcContext.BuilderStack.Pop(); if (!structRef.ValRef.HasValue) { throw new Exception( "The Value/Reference returned as null thus cannot be stored in Struct!"); } //var load = LLVM.BuildLoad(funcContext.Builder, structRef.ValRef.Value, $"Loaded_{structRef.Type.Name}"); var load = structRef.ValRef.Value; var offset = LLVM.BuildStructGEP(funcContext.Builder, load, (uint)Array.IndexOf( Context.FullSymbolToTypeRef[fieldDef.DeclaringType.FullName].CS_FieldDefs, Context.FullSymbolToTypeRef[fieldDef.DeclaringType.FullName].CS_FieldDefs .First(I => I.Name == fieldDef.Name)), $"Offset_{fieldDef.Name}"); var item = new BuilderStackItem(fieldDef.FieldType, LLVM.BuildLoad(funcContext.Builder, offset, "")); funcContext.BuilderStack.Push(item); Context.CLRLogger.Debug( $"[Ldfld {fieldDef.FullName}] -> Popped {structRef.ValRef.Value} off stack and pushed {item.ValRef.Value} to stack"); return(new BuildResult(true)); } return(new BuildResult(false)); }
public override BuildResult Build(Instruction instruction, FunctionContext funcContext) { if (instruction.OpCode == OpCodes.Conv_I) { var value = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.Int32Type, LLVM.BuildFPToUI(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_U1] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.Int32Type, LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_U1] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack"); } // TODO: Support Decimal Conversion To Int64 else { throw new Exception( "INTEGER 8 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Conv_U1) { var value = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.UInt8Type, LLVM.BuildFPToUI(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_U1] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.UInt8Type, LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_U1] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack"); } else { throw new Exception( "UNSIGNED INTEGER 1 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Conv_U2) { var value = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.UInt16Type, LLVM.BuildFPToUI(funcContext.Builder, value.ValRef.Value, LLVM.Int16Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_U2] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.UInt16Type, LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int16Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_U2] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack"); } else { throw new Exception( "UNSIGNED INTEGER 2 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Conv_U4) { var value = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.UInt32Type, LLVM.BuildFPToUI(funcContext.Builder, value.ValRef.Value, LLVM.Int32Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_U4] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.UInt32Type, LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int32Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_U4] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack"); } else { throw new Exception( "UNSIGNED INTEGER 4 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Conv_U8) { var value = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.UInt64Type, LLVM.BuildFPToUI(funcContext.Builder, value.ValRef.Value, LLVM.Int64Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_U8] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.UInt64Type, LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int64Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_U8] -> Popped {value.ValRef.Value} and Pushed As Unsigned Integer {stackItem.ValRef.Value} to Stack"); } else { throw new Exception( "UNSIGNED INTEGER 8 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Conv_I1) { var value = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.Int8Type, LLVM.BuildFPToSI(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_I1] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.Int8Type, LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int8Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_I1] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack"); } else { throw new Exception( "INTEGER 1 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Conv_I2) { var value = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.Int16Type, LLVM.BuildFPToSI(funcContext.Builder, value.ValRef.Value, LLVM.Int16Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_I2] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.Int16Type, LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int16Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_I2] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack"); } else { throw new Exception( "INTEGER 2 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Conv_I4) { var value = funcContext.BuilderStack.Pop(); if (value.Type.IsPointer) { var stackItem = new BuilderStackItem(MiniBCL.Int32Type, LLVM.BuildPtrToInt(funcContext.Builder, value.ValRef.Value, LLVM.Int32Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_I4] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.Int32Type, LLVM.BuildFPToSI(funcContext.Builder, value.ValRef.Value, LLVM.Int32Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_I4] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.Int32Type, LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int32Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_I4] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack"); } else { throw new Exception( "INTEGER 4 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Conv_I8) { var value = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.Int64Type, LLVM.BuildFPToSI(funcContext.Builder, value.ValRef.Value, LLVM.Int64Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_I8] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.Int64Type, LLVM.BuildZExt(funcContext.Builder, value.ValRef.Value, LLVM.Int64Type(), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_I8] -> Popped {value.ValRef.Value} and Pushed As Signed Integer {stackItem.ValRef.Value} to Stack"); } else { throw new Exception( "INTEGER 8 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Conv_R4) { var value = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.FloatType, LLVM.BuildSIToFP(funcContext.Builder, value.ValRef.Value, LLVM.FloatTypeInContext(Context.ContextRef), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_R4] -> Popped {value.ValRef.Value} and Pushed As Float {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.FloatType, LLVM.BuildFPCast(funcContext.Builder, value.ValRef.Value, LLVM.FloatTypeInContext(Context.ContextRef), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_R4] -> Popped {value.ValRef.Value} and Pushed As Float {stackItem.ValRef.Value} to Stack"); } else { throw new Exception( "REAL 4 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Conv_R8) { var value = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeAnInteger(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.DoubleType, LLVM.BuildSIToFP(funcContext.Builder, value.ValRef.Value, LLVM.DoubleTypeInContext(Context.ContextRef), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_R8] -> Popped {value.ValRef.Value} and Pushed As Float {stackItem.ValRef.Value} to Stack"); } else if (MiniBCL.IsTypeARealNumber(value.Type)) { var stackItem = new BuilderStackItem(MiniBCL.DoubleType, LLVM.BuildFPCast(funcContext.Builder, value.ValRef.Value, LLVM.DoubleTypeInContext(Context.ContextRef), "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Conv_R8] -> Popped {value.ValRef.Value} and Pushed As Float {stackItem.ValRef.Value} to Stack"); } else { throw new Exception( "REAL 8 BYTES CONVERSION IS NOT SUPPORTED"); } return(new BuildResult(true)); } return(new BuildResult(false)); }
public override BuildResult Build(Instruction instruction, FunctionContext funcContext) { if (instruction.OpCode == OpCodes.Ldind_U1) { var val = funcContext.BuilderStack.Pop(); LLVMValueRef cast; if (val.Type.IsPointer) { cast = LLVM.BuildPtrToInt(funcContext.Builder, LLVM.BuildLoad(funcContext.Builder, val.ValRef.Value, ""), LLVM.Int32Type(), ""); } else { cast = LLVM.BuildZExt(funcContext.Builder, LLVM.BuildLoad(funcContext.Builder, val.ValRef.Value, ""), LLVM.Int32Type(), ""); } funcContext.BuilderStack.Push(new BuilderStackItem { Type = MiniBCL.Int32Type, TypeRef = LLVM.Int32Type(), ValRef = cast }); Context.CLRLogger.Debug( $"[Ldind_U1] -> Popped Stack Item {val.ValRef.Value}, Loaded and Casted to Int32 Type {cast}"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldind_I) { var val = funcContext.BuilderStack.Pop(); // TODO: Support Native Integer conversion LLVMValueRef cast; if (val.Type.IsPointer) { cast = LLVM.BuildLoad(funcContext.Builder, val.ValRef.Value, ""); funcContext.BuilderStack.Push(new BuilderStackItem { Type = ((PointerType)val.Type).ElementType, TypeRef = cast.TypeOf(), ValRef = cast }); } else { cast = LLVM.BuildZExt(funcContext.Builder, LLVM.BuildLoad(funcContext.Builder, val.ValRef.Value, $"Load_{val.Type.Name}"), LLVM.Int64Type(), ""); funcContext.BuilderStack.Push(new BuilderStackItem { Type = MiniBCL.Int64Type, TypeRef = LLVM.Int64Type(), ValRef = cast }); } Context.CLRLogger.Debug( $"[Ldind_I] -> Popped Stack Item {val.ValRef.Value} and Casted to Int64 Type {cast}"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4) { var operand = (int)instruction.Operand; var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), (ulong)operand, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4 {operand}] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_S) { var operand = (sbyte)instruction.Operand; var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), (ulong)operand, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_S {operand}] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_0) { var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), 0, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_0] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_1) { var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), 1, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_1] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_2) { var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), 2, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_2] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_3) { var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), 3, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_3] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_4) { var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), 4, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_4] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_5) { var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), 5, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_5] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_6) { var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), 6, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_6] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_7) { var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), 7, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_7] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_8) { var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), 8, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_8] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_I4_M1) { unchecked { var stackItem = LLVM.ConstInt(LLVM.Int32TypeInContext(Context.ContextRef), (ulong)-1, true); funcContext.BuilderStack.Push(new BuilderStackItem(MiniBCL.Int32Type, stackItem)); Context.CLRLogger.Debug($"[Ldc_I4_M1] -> Pushed {stackItem} to Stack"); return(new BuildResult(true)); } } if (instruction.OpCode == OpCodes.Ldc_I8) { var stackItem = new BuilderStackItem(MiniBCL.Int64Type, LLVM.ConstInt(LLVM.Int64TypeInContext(Context.ContextRef), (ulong)instruction.Operand, new LLVMBool(1))); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug($"[Ldc_I8] -> Pushed {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_R4) { var stackItem = new BuilderStackItem(MiniBCL.FloatType, LLVM.ConstReal(LLVM.FloatTypeInContext(Context.ContextRef), (double)instruction.Operand)); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug($"[Ldc_R4] -> Pushed {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldc_R8) { var stackItem = new BuilderStackItem(MiniBCL.DoubleType, LLVM.ConstReal(LLVM.DoubleTypeInContext(Context.ContextRef), (double)instruction.Operand)); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug($"[Ldc_R8] -> Pushed {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldnull) { var stackItem = new BuilderStackItem(MiniBCL.Int64Type, LLVM.ConstNull(LLVM.PointerType(LLVM.Int8Type(), 0))); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug($"[Ldnull] -> Pushed {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldftn) { var operand = (MethodDefinition)instruction.Operand; var symbol = SymbolHelper.GetCSToLLVMSymbolName(operand); if (!Context.SymbolToCallableFunction.ContainsKey(symbol)) { Context.CLR.ProcessFunction(operand.Resolve(), false); } var stackItem = new BuilderStackItem(operand.ReturnType.Resolve(), Context.SymbolToCallableFunction[symbol]); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug($"[Ldftn {stackItem.Type}] -> Pushed {stackItem.ValRef.Value} to Stack"); return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Ldstr) { var val = (string)instruction.Operand; var ldstr = LLVM.BuildGlobalStringPtr(funcContext.Builder, val, ""); var stackItem = new BuilderStackItem(MiniBCL.StringType, ldstr); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug($"[Ldstr {val}] -> Pushed {ldstr.TypeOf()} to Stack"); return(new BuildResult(true)); } return(new BuildResult(false)); }
public override BuildResult Build(Instruction instruction, FunctionContext funcContext) { if (instruction.OpCode == OpCodes.Add) { // TODO: Support conversion between Floating Point and Integers var rval = funcContext.BuilderStack.Pop(); var lval = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeAnInteger(lval.Type) && MiniBCL.IsTypeAnInteger(rval.Type)) { // TODO: Need to determine the size of pointer. LLVMValueRef actualLVal; LLVMValueRef actualRVal; if (lval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind) { actualLVal = LLVM.BuildPtrToInt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval"); } else { actualLVal = LLVM.BuildZExt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval"); } if (rval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind) { actualRVal = LLVM.BuildPtrToInt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval"); } else { actualRVal = LLVM.BuildZExt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval"); } var stackItem = new BuilderStackItem(lval.Type, LLVM.BuildAdd(funcContext.Builder, actualLVal, actualRVal, "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Add] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value.TypeOf()} and Pushed {stackItem.ValRef.Value}"); } else if (MiniBCL.IsTypeARealNumber(lval.Type) && MiniBCL.IsTypeARealNumber(rval.Type)) { var stackItem = new BuilderStackItem(lval.Type, LLVM.BuildFAdd(funcContext.Builder, lval.ValRef.Value, rval.ValRef.Value, "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Add] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}"); } else { throw new Exception("Unknown type, thus cannot add!"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Sub) { // TODO: Support conversion between Floating Point and Integers var rval = funcContext.BuilderStack.Pop(); var lval = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeAnInteger(lval.Type) && MiniBCL.IsTypeAnInteger(rval.Type)) { // TODO: Need to determine the size of pointer. LLVMValueRef actualLVal; LLVMValueRef actualRVal; if (lval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind) { actualLVal = LLVM.BuildPtrToInt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval"); } else { actualLVal = LLVM.BuildZExt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval"); } if (rval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind) { actualRVal = LLVM.BuildPtrToInt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval"); } else { actualRVal = LLVM.BuildZExt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval"); } var stackItem = new BuilderStackItem(lval.Type, LLVM.BuildSub(funcContext.Builder, actualLVal, actualRVal, "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}"); } else if (MiniBCL.IsTypeARealNumber(lval.Type) && MiniBCL.IsTypeARealNumber(rval.Type)) { var stackItem = new BuilderStackItem(lval.Type, LLVM.BuildFSub(funcContext.Builder, lval.ValRef.Value, rval.ValRef.Value, "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}"); } else { throw new Exception("Unknown type, thus cannot add!"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Mul) { // TODO: Support conversion between Floating Point and Integers var rval = funcContext.BuilderStack.Pop(); var lval = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeAnInteger(lval.Type) && MiniBCL.IsTypeAnInteger(rval.Type)) { // TODO: Need to determine the size of pointer. LLVMValueRef actualLVal; LLVMValueRef actualRVal; if (lval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind) { actualLVal = LLVM.BuildPtrToInt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval"); } else { actualLVal = LLVM.BuildZExt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval"); } if (rval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind) { actualRVal = LLVM.BuildPtrToInt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval"); } else { actualRVal = LLVM.BuildZExt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval"); } var stackItem = new BuilderStackItem(lval.Type, LLVM.BuildMul(funcContext.Builder, actualLVal, actualRVal, "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}"); } else if (MiniBCL.IsTypeARealNumber(lval.Type) && MiniBCL.IsTypeARealNumber(rval.Type)) { var stackItem = new BuilderStackItem(lval.Type, LLVM.BuildFMul(funcContext.Builder, lval.ValRef.Value, rval.ValRef.Value, "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}"); } else { throw new Exception("Unknown type, thus cannot add!"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Div) { // TODO: Support conversion between Floating Point and Integers var rval = funcContext.BuilderStack.Pop(); var lval = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeAnInteger(lval.Type) && MiniBCL.IsTypeAnInteger(rval.Type)) { // TODO: Need to determine the size of pointer. LLVMValueRef actualLVal; LLVMValueRef actualRVal; if (lval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind) { actualLVal = LLVM.BuildPtrToInt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval"); } else { actualLVal = LLVM.BuildZExt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval"); } if (rval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind) { actualRVal = LLVM.BuildPtrToInt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval"); } else { actualRVal = LLVM.BuildZExt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval"); } var stackItem = new BuilderStackItem(lval.Type, LLVM.BuildSDiv(funcContext.Builder, actualLVal, actualRVal, "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}"); } else if (MiniBCL.IsTypeARealNumber(lval.Type) && MiniBCL.IsTypeARealNumber(rval.Type)) { var stackItem = new BuilderStackItem(lval.Type, LLVM.BuildFDiv(funcContext.Builder, lval.ValRef.Value, rval.ValRef.Value, "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}"); } else { throw new Exception("Unknown type, thus cannot add!"); } return(new BuildResult(true)); } if (instruction.OpCode == OpCodes.Rem) { // TODO: Support conversion between Floating Point and Integers var rval = funcContext.BuilderStack.Pop(); var lval = funcContext.BuilderStack.Pop(); if (MiniBCL.IsTypeAnInteger(lval.Type) && MiniBCL.IsTypeAnInteger(rval.Type)) { // TODO: Need to determine the size of pointer. LLVMValueRef actualLVal; LLVMValueRef actualRVal; if (lval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind) { actualLVal = LLVM.BuildPtrToInt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval"); } else { actualLVal = LLVM.BuildZExt(funcContext.Builder, lval.ValRef.Value, LLVM.Int32Type(), "lval"); } if (rval.ValRef.Value.TypeOf().TypeKind == LLVMTypeKind.LLVMPointerTypeKind) { actualRVal = LLVM.BuildPtrToInt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval"); } else { actualRVal = LLVM.BuildZExt(funcContext.Builder, rval.ValRef.Value, LLVM.Int32Type(), "rval"); } var stackItem = new BuilderStackItem(lval.Type, LLVM.BuildSRem(funcContext.Builder, actualLVal, actualRVal, "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}"); } else if (MiniBCL.IsTypeARealNumber(lval.Type) && MiniBCL.IsTypeARealNumber(rval.Type)) { var stackItem = new BuilderStackItem(lval.Type, LLVM.BuildFRem(funcContext.Builder, lval.ValRef.Value, rval.ValRef.Value, "")); funcContext.BuilderStack.Push(stackItem); Context.CLRLogger.Debug( $"[Sub] -> Popped {rval.ValRef.Value} and {lval.ValRef.Value} and Pushed {stackItem.ValRef.Value}"); } else { throw new Exception("Unknown type, thus cannot add!"); } return(new BuildResult(true)); } return(new BuildResult(false)); }
internal void ProcessCall(Instruction instruction, LLVMBuilderRef builder, Stack <BuilderStackItem> builderStack) { var methodToCall = (MethodReference)instruction.Operand; Context.CLRLogger.Debug(methodToCall.ToString()); var resolvedMethodToCall = methodToCall.Resolve(); if (methodToCall.HasThis && resolvedMethodToCall.DeclaringType?.BaseType != null && (resolvedMethodToCall.DeclaringType.BaseType.FullName == "System.Delegate" || resolvedMethodToCall.DeclaringType.BaseType.FullName == "System.MulticastDelegate")) { var refs = new LLVMValueRef[methodToCall.Parameters.Count]; if (refs.Length > 0) { for (var i = methodToCall.Parameters.Count - 1; i > -1; --i) { refs[i] = builderStack.Pop().ValRef.Value; } } var reference = builderStack.Pop(); var stackItem = new BuilderStackItem(methodToCall.ReturnType.Resolve(), LLVM.BuildCall(builder, reference.ValRef.Value, refs, "")); // We know this is a delegate, now to call it! builderStack.Push(stackItem); Context.CLRLogger.Debug( $"[{instruction.OpCode.Name} {methodToCall.FullName}] -> Determined as Delegate, Popped Reference {reference} and Push {stackItem.ValRef} to Stack"); } else { var refs = new LLVMValueRef[methodToCall.HasThis ? methodToCall.Parameters.Count + 1 : methodToCall.Parameters.Count]; var symbol = SymbolHelper.GetCSToLLVMSymbolName(methodToCall); if (refs.Length > (methodToCall.HasThis ? 1 : 0)) { for (var i = methodToCall.HasThis ? methodToCall.Parameters.Count : methodToCall.Parameters.Count - 1; i > (methodToCall.HasThis ? 0 : -1); --i) { refs[i] = builderStack.Pop().ValRef.Value; } } if (!Context.SymbolToCallableFunction.ContainsKey(SymbolHelper.GetCSToLLVMSymbolName(methodToCall))) { Context.CLRLogger.Debug("Resolving Function"); Context.CLR.ProcessFunction(methodToCall.Resolve(), false); } if (methodToCall.HasThis) { var reference = builderStack.Pop(); if (methodToCall.DeclaringType.FullName != reference.Type.FullName) { refs[0] = LLVM.BuildPointerCast(builder, reference.ValRef.Value, Context.SymbolToCallableFunction[symbol].GetFirstParam().TypeOf(), ""); } else { refs[0] = reference.ValRef.Value; } } if (methodToCall.ReturnType.FullName != "System.Void") { var stackItem = new BuilderStackItem(methodToCall.ReturnType.Resolve(), LLVM.BuildCall(builder, Context.SymbolToCallableFunction[SymbolHelper.GetCSToLLVMSymbolName(methodToCall)], refs, "")); builderStack.Push(stackItem); Context.CLRLogger.Debug( $"[{instruction.OpCode.Name} {methodToCall.FullName}] -> Push {stackItem.ValRef} to Stack"); return; } var call = LLVM.BuildCall(builder, Context.SymbolToCallableFunction[SymbolHelper.GetCSToLLVMSymbolName(methodToCall)], refs, ""); Context.CLRLogger.Debug($"[{instruction.OpCode.Name} {methodToCall.FullName}] -> Called {call}"); } }