/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="objectResult"> /// </param> /// <param name="methodResult"> /// </param> /// <param name="invokeMethod"> /// </param> /// <param name="isStatic"> /// </param> /// <returns> /// </returns> public static FullyDefinedReference WriteCallInvokeMethod( this LlvmWriter llvmWriter, FullyDefinedReference objectResult, FullyDefinedReference methodResult, IMethod invokeMethod, bool isStatic) { var writer = llvmWriter.Output; var method = new SynthesizedInvokeMethod(llvmWriter, objectResult, methodResult, invokeMethod, isStatic); var opCodeNope = OpCodePart.CreateNop; opCodeNope.OpCodeOperands = Enumerable.Range(0, invokeMethod.GetParameters().Count()).Select(p => new OpCodeInt32Part(OpCodesEmit.Ldarg, 0, 0, p + 1)).ToArray(); foreach (var generatedOperand in opCodeNope.OpCodeOperands) { llvmWriter.ActualWrite(writer, generatedOperand); } writer.WriteLine(string.Empty); // bitcast object to method var opCodeNopeForBitCast = OpCodePart.CreateNop; opCodeNopeForBitCast.OpCodeOperands = new[] { OpCodePart.CreateNop }; opCodeNopeForBitCast.OpCodeOperands[0].Result = methodResult; llvmWriter.UnaryOper(writer, opCodeNopeForBitCast, "bitcast", methodResult.Type, options: LlvmWriter.OperandOptions.GenerateResult); writer.Write(" to "); llvmWriter.WriteMethodPointerType(writer, method); writer.WriteLine(string.Empty); method.MethodResult = opCodeNopeForBitCast.Result; // actual call llvmWriter.WriteCall(opCodeNope, method, false, !isStatic, false, objectResult, llvmWriter.tryScopes.Count > 0 ? llvmWriter.tryScopes.Peek() : null); writer.WriteLine(string.Empty); return opCodeNope.Result; }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="method"> /// </param> private static void WriteDelegateConstructor(this LlvmWriter llvmWriter, IMethod method) { var writer = llvmWriter.Output; writer.WriteLine(" {"); writer.Indent++; var opCode = OpCodePart.CreateNop; // create this variable llvmWriter.WriteArgumentCopyDeclaration(null, 0, method.DeclaringType, true); for (var i = 1; i <= llvmWriter.GetArgCount() + 1; i++) { llvmWriter.WriteArgumentCopyDeclaration(llvmWriter.GetArgName(i), i, llvmWriter.GetArgType(i)); } // load 'this' variable llvmWriter.WriteLlvmLoad(opCode, method.DeclaringType, new FullyDefinedReference(llvmWriter.GetThisName(), method.DeclaringType)); writer.WriteLine(string.Empty); var thisResult = opCode.Result; var delegateType = llvmWriter.ResolveType("System.Delegate"); // write access to a field 1 var _targetFieldIndex = llvmWriter.GetFieldIndex(delegateType, "_target"); llvmWriter.WriteFieldAccess(writer, opCode, method.DeclaringType, delegateType, _targetFieldIndex, thisResult); writer.WriteLine(string.Empty); // load value 1 opCode.OpCodeOperands = new[] { new OpCodePart(OpCodesEmit.Ldarg_1, 0, 0) }; llvmWriter.ActualWrite(writer, opCode.OpCodeOperands[0]); writer.WriteLine(string.Empty); // save value 1 llvmWriter.SaveToField(opCode, opCode.Result.Type, 0); writer.WriteLine(string.Empty); // write access to a field 2 var _methodPtrFieldIndex = llvmWriter.GetFieldIndex(delegateType, "_methodPtr"); llvmWriter.WriteFieldAccess(writer, opCode, method.DeclaringType, delegateType, _methodPtrFieldIndex, thisResult); writer.WriteLine(string.Empty); // load value 2 opCode.OpCodeOperands = new[] { new OpCodePart(OpCodesEmit.Ldarg_2, 0, 0) }; llvmWriter.ActualWrite(writer, opCode.OpCodeOperands[0]); writer.WriteLine(string.Empty); // save value 2 llvmWriter.SaveToField(opCode, opCode.Result.Type, 0); writer.WriteLine(string.Empty); writer.WriteLine("ret void"); writer.Indent--; writer.WriteLine("}"); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="declaringType"> /// </param> /// <param name="newObjectResult"> /// </param> /// <param name="callInit"> /// </param> public static void WriteBoxObject( this LlvmWriter llvmWriter, OpCodePart opCode, IType declaringType, FullyDefinedReference newObjectResult = null, bool callInit = false) { var writer = llvmWriter.Output; var valueLoadResult = opCode.Result; var isStruct = declaringType.ToNormal().IsStructureType(); opCode.Result = null; writer.WriteLine("; Boxing"); writer.WriteLine(string.Empty); llvmWriter.CheckIfExternalDeclarationIsRequired(declaringType); // call new if null if (newObjectResult == null) { declaringType.WriteCallNewObjectMethod(llvmWriter, opCode); newObjectResult = opCode.Result; } else { opCode.Result = newObjectResult; } writer.WriteLine(string.Empty); writer.WriteLine("; Copy data"); if (!isStruct) { // write access to a field if (!llvmWriter.WriteFieldAccess( writer, opCode, declaringType.ToClass(), declaringType.ToClass(), 0, opCode.Result)) { writer.WriteLine("; No data"); return; } writer.WriteLine(string.Empty); } var fieldType = declaringType.ToNormal(); opCode.OpCodeOperands = new[] { new OpCodePart(OpCodesEmit.Ldarg_0, 0, 0) }; opCode.OpCodeOperands[0].Result = valueLoadResult; if (valueLoadResult == null) { llvmWriter.ActualWrite(writer, opCode.OpCodeOperands[0]); } llvmWriter.SaveToField(opCode, fieldType, 0); writer.WriteLine(string.Empty); writer.WriteLine("; End of Copy data"); if (callInit) { opCode.Result = newObjectResult; declaringType.WriteCallInitObjectMethod(llvmWriter, opCode); writer.WriteLine(string.Empty); } opCode.Result = newObjectResult.ToClassType(); }