public static void WriteLlvmSavePrimitiveIntoStructure( this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source, FullyDefinedReference destination) { var writer = llvmWriter.Output; writer.WriteLine("; Copy primitive data into a structure"); // write access to a field if (!llvmWriter.WriteFieldAccess( opCode, destination.Type.ToClass(), destination.Type.ToClass(), 0, destination)) { writer.WriteLine("; No data"); return; } writer.WriteLine(string.Empty); llvmWriter.SaveToField(opCode, opCode.Result.Type, 0); writer.WriteLine(string.Empty); writer.WriteLine("; End of Copy primitive data"); }
/// <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; }
public static void WriteLlvmLoadPrimitiveFromStructure( this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source) { var writer = llvmWriter.Output; // write access to a field if (!llvmWriter.WriteFieldAccess( opCode, source.Type.ToClass(), source.Type.ToClass(), 0, source)) { writer.WriteLine("; No data"); return; } writer.WriteLine(string.Empty); llvmWriter.WriteLlvmLoad(opCode, opCode.Result.Type, opCode.Result); writer.WriteLine(string.Empty); }
public static void WriteAllocateMemory( this LlvmWriter llvmWriter, OpCodePart opCodePart, FullyDefinedReference size, bool doNotTestNullValue) { var writer = llvmWriter.Output; var mallocResult = llvmWriter.WriteSetResultNumber( opCodePart, llvmWriter.System.System_Byte.ToPointerType()); writer.Write("call i8* @{0}(", llvmWriter.GetAllocator()); size.Type.WriteTypePrefix(llvmWriter); writer.Write(" "); llvmWriter.WriteResult(size); writer.WriteLine(")"); if (!doNotTestNullValue) { llvmWriter.WriteTestNullValueAndThrowException( writer, opCodePart, mallocResult, "System.OutOfMemoryException", "new_obj"); } if (!llvmWriter.Gc) { llvmWriter.WriteMemSet(mallocResult, size); writer.WriteLine(string.Empty); } }
/// <summary> /// </summary> /// <param name="methodInfo"> /// </param> /// <param name="opCodeMethodInfo"> /// </param> /// <param name="thisType"> /// </param> /// <param name="methodAddressResultNumber"> /// </param> /// <param name="llvmWriter"> /// </param> public static void WriteFunctionCallLoadFunctionAddress( this IMethod methodInfo, OpCodePart opCodeMethodInfo, IType thisType, ref FullyDefinedReference methodAddressResultNumber, LlvmWriter llvmWriter) { if (!methodInfo.IsUnmanagedMethodReference) { return; } var writer = llvmWriter.Output; // if this is external method reference we need to load reference first // %4 = load i32 ()** @__glewCreateProgram, align 4 // load pointer llvmWriter.WriteSetResultNumber( opCodeMethodInfo, llvmWriter.System.System_Byte.ToPointerType().ToPointerType()); writer.Write("load "); llvmWriter.WriteMethodPointerType(writer, methodInfo, thisType); writer.Write("* "); llvmWriter.WriteMethodDefinitionName(writer, methodInfo); writer.Write(", align {0}", LlvmWriter.PointerSize); writer.WriteLine(string.Empty); methodAddressResultNumber = opCodeMethodInfo.Result; }
public static void WriteMemCopy(this LlvmWriter llvmWriter, FullyDefinedReference op1, FullyDefinedReference op2, FullyDefinedReference size) { var writer = llvmWriter.Output; writer.WriteLine( "call void @llvm.memcpy.p0i8.p0i8.i32(i8* {0}, i8* {1}, i32 {2}, i32 {3}, i1 false)", op1, op2, size, LlvmWriter.PointerSize /*Align*/); }
/// <summary> /// </summary> /// <param name="writer"> /// </param> /// <param name="objectResult"> /// </param> /// <param name="methodResult"> /// </param> /// <param name="invokeMethod"> /// </param> /// <param name="isStatic"> /// </param> public SynthesizedInvokeMethod( LlvmWriter writer, FullyDefinedReference objectResult, FullyDefinedReference methodResult, IMethod invokeMethod, bool isStatic) { this.writer = writer; this.objectResult = objectResult; this.MethodResult = methodResult; this.invokeMethod = invokeMethod; this.isStatic = isStatic; }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="type"> /// </param> /// <param name="operandType"> /// </param> public static void WriteGetTypeStaticObject(this LlvmWriter llvmWriter, OpCodePart opCode, IType type, IType operandType) { var writer = llvmWriter.Output; llvmWriter.WriteLlvmLoad(opCode, operandType, new FullyDefinedReference(type.GetTypeStaticFieldName(), operandType)); writer.WriteLine(string.Empty); var result = opCode.Result; var testNullResultNumber = llvmWriter.WriteTestNull(writer, opCode, opCode.Result); llvmWriter.WriteBranchSwitchToExecute( writer, opCode, testNullResultNumber, operandType.FullName, "gettype", "new", () => { // TODO: here send predifined byte array data with info for Type var runtimeType = llvmWriter.ResolveType("System.RuntimeType"); var byteType = llvmWriter.ResolveType("System.Byte"); var byteArrayType = byteType.ToArrayType(1); var bytes = type.GenerateTypeInfoBytes(); var bytesIndex = llvmWriter.GetBytesIndex(bytes); var firstParameterValue = new FullyDefinedReference( llvmWriter.GetArrayTypeReference(string.Format("@.bytes{0}", bytesIndex), byteType, bytes.Length), byteArrayType); opCode.Result = null; var newObjectResult = llvmWriter.WriteNewWithCallingConstructor(opCode, runtimeType, byteArrayType, firstParameterValue); writer.WriteLine(string.Empty); // call cmp exchnage var noOpCmpXchg = OpCodePart.CreateNop; noOpCmpXchg.OpCodeOperands = new[] { OpCodePart.CreateNop, OpCodePart.CreateNop, OpCodePart.CreateNop }; noOpCmpXchg.OpCodeOperands[0].Result = new FullyDefinedReference(type.GetTypeStaticFieldName(), operandType.ToPointerType()); noOpCmpXchg.OpCodeOperands[1].Result = new ConstValue(null, operandType); noOpCmpXchg.OpCodeOperands[2].Result = newObjectResult; noOpCmpXchg.InterlockBase("cmpxchg ", llvmWriter.IsLlvm34OrLower ? " acq_rel" : " acq_rel monotonic", !llvmWriter.IsLlvm35 && !llvmWriter.IsLlvm34OrLower, llvmWriter); writer.WriteLine(string.Empty); // load again opCode.Result = null; llvmWriter.WriteLlvmLoad(opCode, operandType, new FullyDefinedReference(type.GetTypeStaticFieldName(), operandType)); writer.WriteLine(string.Empty); writer.Write("ret "); opCode.Result.Type.WriteTypePrefix(writer); writer.Write(" "); llvmWriter.WriteResult(opCode.Result); writer.WriteLine(string.Empty); }); opCode.Result = result; }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="fromResult"> /// </param> /// <param name="toType"> /// </param> /// <param name="throwExceptionIfNull"> /// </param> /// <returns> /// </returns> public static bool WriteCast( this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference fromResult, IType toType, bool throwExceptionIfNull = false) { var writer = llvmWriter.Output; var bareType = !fromResult.Type.IsArray ? fromResult.Type.ToBareType() : fromResult.Type; if (toType.IsInterface && !(fromResult is ConstValue)) { if (bareType.GetAllInterfaces().Contains(toType)) { opCode.Result = fromResult; llvmWriter.WriteInterfaceAccess(writer, opCode, bareType, toType); } else { llvmWriter.WriteDynamicCast(writer, opCode, fromResult, toType, true, throwExceptionIfNull); } } else if (fromResult.Type.IntTypeBitSize() == LlvmWriter.PointerSize * 8 && (toType.IsPointer || toType.IsByRef)) { LlvmConvert(llvmWriter, opCode, string.Empty, string.Empty, toType, true); } else if (fromResult.Type.IsArray || (fromResult.Type.IsPointer && bareType.TypeEquals(llvmWriter.System.System_Void)) || toType.IsArray || toType.IsPointer || toType.IsByRef || bareType.IsDerivedFrom(toType) || (fromResult is ConstValue)) { llvmWriter.WriteSetResultNumber(opCode, toType); writer.Write("bitcast "); fromResult.Type.WriteTypePrefix(llvmWriter); writer.Write(' '); llvmWriter.WriteResult(fromResult); writer.Write(" to "); toType.WriteTypePrefix(llvmWriter, toType.IsStructureType()); } else { Debug.Assert(fromResult.Type.IntTypeBitSize() == 0); llvmWriter.WriteDynamicCast(writer, opCode, fromResult, toType, true, throwExceptionIfNull); } writer.WriteLine(string.Empty); return(true); }
public static void WriteMemSet(this LlvmWriter llvmWriter, FullyDefinedReference op1, FullyDefinedReference size) { var writer = llvmWriter.Output; writer.Write("call void @llvm.memset.p0i8.i32(i8* {0}, i8 0, ", op1); size.Type.WriteTypePrefix(writer); writer.Write(" "); llvmWriter.WriteResult(size); writer.Write(", i32 {0}, i1 false)", LlvmWriter.PointerSize /*Align*/); }
/// <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="type"> /// </param> /// <param name="op1"> /// </param> public static void WriteMemSet(this LlvmWriter llvmWriter, IType type, FullyDefinedReference op1) { var writer = llvmWriter.Output; writer.Write( "call void @llvm.memset.p0i8.i32(i8* {0}, i8 0, i32 {1}, i32 {2}, i1 false)", op1, type.GetTypeSize(type.IsPrimitiveType() && !type.UseAsClass), LlvmWriter.PointerSize /*Align*/); }
/// <summary> /// </summary> /// <param name="methodInfo"> /// </param> /// <param name="methodAddressResultNumber"> /// </param> /// <param name="ownerOfExplicitInterface"> /// </param> /// <param name="llvmWriter"> /// </param> public static void WriteFunctionNameExpression( this IMethod methodInfo, FullyDefinedReference methodAddressResultNumber, IType ownerOfExplicitInterface, LlvmWriter llvmWriter) { var writer = llvmWriter.Output; var isIndirectMethodCall = methodAddressResultNumber != null; if (isIndirectMethodCall || methodInfo.IsUnmanagedMethodReference) { llvmWriter.WriteResult(methodAddressResultNumber); } else { // default method name llvmWriter.WriteMethodDefinitionName(writer, methodInfo, ownerOfExplicitInterface); } }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="source"> /// </param> /// <param name="toType"> /// </param> public static void WriteBitcast( this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source, IType toType, bool asReference = true) { var writer = llvmWriter.Output; llvmWriter.WriteSetResultNumber(opCode, toType); writer.Write("bitcast "); source.Type.WriteTypePrefix(llvmWriter, asReference); writer.Write(" "); llvmWriter.WriteResult(source); writer.Write(" to "); toType.WriteTypePrefix(llvmWriter, asReference); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="source"> /// </param> /// <param name="toType"> /// </param> public static void WriteIntToPtr( this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source, IType toType) { var writer = llvmWriter.Output; Debug.Assert(!source.Type.IsPointer && !source.Type.IsByRef); llvmWriter.WriteSetResultNumber(opCode, toType); writer.Write("inttoptr "); source.Type.WriteTypePrefix(llvmWriter); writer.Write(" "); llvmWriter.WriteResult(source); writer.Write(" to "); toType.WriteTypePrefix(llvmWriter, true); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCodePart"> /// </param> /// <param name="declaringTypeIn"> /// </param> /// <param name="objectSource"> /// </param> public static void WriteInit( this LlvmWriter llvmWriter, OpCodePart opCodePart, IType declaringTypeIn, FullyDefinedReference objectSource) { var writer = llvmWriter.Output; var declaringTypeNormal = declaringTypeIn.ToNormal(); var declaringTypeClass = declaringTypeIn.IsValueType ? declaringTypeIn.ToClass() : declaringTypeIn; writer.WriteLine("; Init obj"); if (declaringTypeNormal.IsValueType) { llvmWriter.WriteBitcast(opCodePart, objectSource, llvmWriter.System.System_Byte.ToPointerType()); writer.WriteLine(string.Empty); llvmWriter.WriteMemSet(declaringTypeNormal, opCodePart.Result); writer.WriteLine(string.Empty); if (declaringTypeNormal.IsStructureType()) { // init now opCodePart.Result = objectSource; declaringTypeClass.WriteCallInitObjectMethod(llvmWriter, opCodePart); writer.WriteLine(string.Empty); } } else { // this is type reference, initialize it with null llvmWriter.WriteBitcast( opCodePart, objectSource, llvmWriter.System.System_Byte.ToPointerType().ToPointerType()); writer.WriteLine(string.Empty); writer.WriteLine("store i8* null, i8** {0}", opCodePart.Result); } writer.Write("; end of init obj"); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="typeToSave"> /// </param> /// <param name="operandIndex"> /// </param> /// <param name="destination"> /// </param> public static void WriteLlvmSave( this LlvmWriter llvmWriter, OpCodePart opCode, IType typeToSave, int operandIndex, FullyDefinedReference destination) { var writer = llvmWriter.Output; llvmWriter.ProcessOperator( writer, opCode, "store", typeToSave, options: LlvmWriter.OperandOptions.CastPointersToBytePointer | LlvmWriter.OperandOptions.AdjustIntTypes, operand1: operandIndex, operand2: -1); llvmWriter.WriteOperandResult(writer, opCode, operandIndex); writer.Write(", "); typeToSave.WriteTypePrefix(llvmWriter); writer.Write("* "); writer.Write(destination); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="typeToLoad"> /// </param> /// <param name="source"> /// </param> /// <param name="appendReference"> /// </param> /// <param name="structAsRef"> /// </param> /// <param name="indirect"> /// </param> public static void WriteLlvmLoad( this LlvmWriter llvmWriter, OpCodePart opCode, IType typeToLoad, FullyDefinedReference source, bool appendReference = true, bool structAsRef = false, bool indirect = false) { // TODO: review the whole proc. var writer = llvmWriter.Output; var isStruct = typeToLoad.ToNormal().IsStructureType(); Debug.Assert( structAsRef || !isStruct || typeToLoad.IsByRef || isStruct && !typeToLoad.IsByRef && opCode.HasResult); if (!isStruct || typeToLoad.IsByRef || structAsRef || !opCode.HasResult || (indirect && !isStruct)) { ////Debug.Assert(source.Type.IsPointer); var dereferencedType = source.Type.IsPointer ? source.Type.GetElementType() : null; var effectiveSource = source; // check if you need bitcast pointer type if (!typeToLoad.IsPointer && dereferencedType != null && typeToLoad.TypeNotEquals(dereferencedType)) { // check if you need cast here llvmWriter.WriteBitcast(opCode, source, typeToLoad); writer.WriteLine(string.Empty); effectiveSource = opCode.Result; } if (indirect && !source.Type.IsPointer && !source.Type.IsByRef && source.Type.IntTypeBitSize() > 0) { // check if you need cast here llvmWriter.WriteIntToPtr(opCode, source, typeToLoad); writer.WriteLine(string.Empty); effectiveSource = opCode.Result; } llvmWriter.WriteSetResultNumber(opCode, typeToLoad); // last part writer.Write("load "); typeToLoad.WriteTypePrefix(llvmWriter, structAsRef); if (appendReference) { // add reference to type writer.Write('*'); } writer.Write(' '); writer.Write(effectiveSource.ToString()); // TODO: optional do we need to calculate it propertly? writer.Write(", align " + LlvmWriter.PointerSize); } else { llvmWriter.WriteCopyStruct(writer, opCode, typeToLoad, source, opCode.Result); } }
/// <summary> /// </summary> /// <param name="parameterInfos"> /// </param> /// <param name="used"> /// </param> /// <param name="isVirtual"> /// </param> /// <param name="hasThis"> /// </param> /// <param name="isCtor"> /// </param> /// <param name="resultNumberForThis"> /// </param> /// <param name="thisType"> /// </param> /// <param name="resultNumberForReturn"> /// </param> /// <param name="returnType"> /// </param> /// <param name="llvmWriter"> /// </param> public static void WriteFunctionCallArguments( this IEnumerable<IParameter> parameterInfos, OpCodePart[] used, bool @isVirtual, bool hasThis, bool isCtor, FullyDefinedReference resultNumberForThis, IType thisType, FullyDefinedReference resultNumberForReturn, IType returnType, LlvmWriter llvmWriter, bool varArg) { var writer = llvmWriter.Output; writer.Write("("); var index = 0; var returnIsStruct = returnType != null && returnType.IsStructureType(); var comaRequired = false; // allocate space for structure if return type is structure if (returnIsStruct) { returnType.WriteTypePrefix(llvmWriter, returnType.IsStructureType()); writer.Write(' '); if (resultNumberForReturn != null) { llvmWriter.WriteResult(resultNumberForReturn); } comaRequired = true; } if (hasThis) { if (comaRequired) { writer.Write(", "); } thisType.ToClass().WriteTypePrefix(llvmWriter); writer.Write(' '); if (resultNumberForThis != null) { llvmWriter.WriteResult(resultNumberForThis); } else if (used != null && used.Length > 0) { llvmWriter.WriteResult(used[0].Result); } comaRequired = true; } llvmWriter.CheckIfExternalDeclarationIsRequired(returnType); var argsContainsThisArg = used != null ? (used.Length - parameterInfos.Count()) > 0 : false; var argShift = @isVirtual || (hasThis && !isCtor && argsContainsThisArg) ? 1 : 0; // add parameters foreach (var parameter in parameterInfos) { var effectiveIndex = index + argShift; var usedItem = used[effectiveIndex]; if (comaRequired) { writer.Write(", "); } llvmWriter.WriteFunctionCallParameterArgument(usedItem, parameter); comaRequired = true; index++; } if (varArg) { // VarArgs while (index < used.Length) { var effectiveIndex = index + argShift; var usedItem = used[effectiveIndex]; if (comaRequired) { writer.Write(", "); } llvmWriter.WriteFunctionCallVarArgument(usedItem, usedItem.Result.Type); comaRequired = true; index++; } } writer.Write(")"); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="type"> /// </param> /// <param name="operandType"> /// </param> public static void WriteGetTypeStaticObject(this LlvmWriter llvmWriter, OpCodePart opCode, IType type, IType operandType) { var writer = llvmWriter.Output; llvmWriter.WriteLlvmLoad(opCode, operandType, new FullyDefinedReference(type.GetTypeStaticFieldName(), operandType)); writer.WriteLine(string.Empty); var result = opCode.Result; var testNullResultNumber = llvmWriter.WriteTestNull(writer, opCode, opCode.Result); llvmWriter.WriteBranchSwitchToExecute( writer, opCode, testNullResultNumber, operandType.FullName, "gettype", "new", () => { // TODO: here send predifined byte array data with info for Type var runtimeType = llvmWriter.ResolveType("System.RuntimeType"); var byteType = llvmWriter.ResolveType("System.Byte"); var byteArrayType = byteType.ToArrayType(1); var bytes = type.GenerateTypeInfoBytes(); var bytesIndex = llvmWriter.GetBytesIndex(bytes); var firstParameterValue = new FullyDefinedReference( llvmWriter.GetArrayTypeReference(string.Format("@.bytes{0}", bytesIndex), byteType, bytes.Length), byteArrayType); opCode.Result = null; var newObjectResult = llvmWriter.WriteNewWithCallingConstructor(opCode, runtimeType, byteArrayType, firstParameterValue); writer.WriteLine(string.Empty); // call cmp exchnage var noOpCmpXchg = OpCodePart.CreateNop; noOpCmpXchg.OpCodeOperands = new[] { OpCodePart.CreateNop, OpCodePart.CreateNop, OpCodePart.CreateNop }; noOpCmpXchg.OpCodeOperands[0].Result = new FullyDefinedReference(type.GetTypeStaticFieldName(), operandType.ToPointerType()); noOpCmpXchg.OpCodeOperands[1].Result = new ConstValue(null, operandType); noOpCmpXchg.OpCodeOperands[2].Result = newObjectResult; noOpCmpXchg.InterlockBase("cmpxchg ", llvmWriter.IsLlvm34OrLower ? " acq_rel" : " acq_rel monotonic", !llvmWriter.IsLlvm35 && !llvmWriter.IsLlvm34OrLower, llvmWriter); writer.WriteLine(string.Empty); // load again opCode.Result = null; llvmWriter.WriteLlvmLoad(opCode, operandType, new FullyDefinedReference(type.GetTypeStaticFieldName(), operandType)); writer.WriteLine(string.Empty); writer.Write("ret "); opCode.Result.Type.WriteTypePrefix(writer); writer.Write(" "); llvmWriter.WriteResult(opCode.Result); writer.WriteLine(string.Empty); }); opCode.Result = result; }
/// <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(); }
/// <summary> /// </summary> /// <param name="methodInfo"> /// </param> /// <param name="opCodeMethodInfo"> /// </param> /// <param name="thisType"> /// </param> /// <param name="methodAddressResultNumber"> /// </param> /// <param name="llvmWriter"> /// </param> public static void WriteFunctionCallLoadFunctionAddress( this IMethod methodInfo, OpCodePart opCodeMethodInfo, IType thisType, ref FullyDefinedReference methodAddressResultNumber, LlvmWriter llvmWriter) { if (!methodInfo.IsUnmanagedMethodReference) { return; } var writer = llvmWriter.Output; // if this is external method reference we need to load reference first // %4 = load i32 ()** @__glewCreateProgram, align 4 // load pointer llvmWriter.WriteSetResultNumber( opCodeMethodInfo, llvmWriter.System.System_Byte.ToPointerType().ToPointerType()); writer.Write("load "); llvmWriter.WriteMethodPointerType(writer, methodInfo, thisType); writer.Write("* "); llvmWriter.WriteMethodDefinitionName(writer, methodInfo); writer.Write(", align {0}", LlvmWriter.PointerSize); writer.WriteLine(string.Empty); methodAddressResultNumber = opCodeMethodInfo.Result; }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="result"> /// </param> public static void WriteBitcast(this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference result) { var writer = llvmWriter.Output; llvmWriter.WriteSetResultNumber(opCode, llvmWriter.ResolveType("System.Byte").ToPointerType()); writer.Write("bitcast "); result.Type.WriteTypePrefix(writer, true); writer.Write(" "); llvmWriter.WriteResult(result); writer.Write(" to i8*"); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCodeMethodInfo"> /// </param> /// <param name="methodInfo"> /// </param> /// <param name="isVirtual"> /// </param> /// <param name="hasThis"> /// </param> /// <param name="isCtor"> /// </param> /// <param name="thisResultNumber"> /// </param> /// <param name="tryClause"> /// </param> public static void WriteCall( this LlvmWriter llvmWriter, OpCodePart opCodeMethodInfo, IMethod methodInfo, bool isVirtual, bool hasThis, bool isCtor, FullyDefinedReference thisResultNumber, TryClause tryClause) { var writer = llvmWriter.Output; llvmWriter.CheckIfExternalDeclarationIsRequired(methodInfo); llvmWriter.CheckIfExternalDeclarationIsRequired(methodInfo.DeclaringType); IType thisType; bool hasThisArgument; OpCodePart opCodeFirstOperand; BaseWriter.ReturnResult resultOfFirstOperand; bool isIndirectMethodCall; IType ownerOfExplicitInterface; IType requiredType; methodInfo.WriteFunctionCallProlog( opCodeMethodInfo, isVirtual, hasThis, llvmWriter, out thisType, out hasThisArgument, out opCodeFirstOperand, out resultOfFirstOperand, out isIndirectMethodCall, out ownerOfExplicitInterface, out requiredType); if (hasThisArgument) { opCodeMethodInfo.WriteFunctionCallPrepareThisExpression(thisType, opCodeFirstOperand, resultOfFirstOperand, llvmWriter); } FullyDefinedReference methodAddressResultNumber = null; if (isIndirectMethodCall) { methodAddressResultNumber = llvmWriter.GenerateVirtualCall( opCodeMethodInfo, methodInfo, thisType, opCodeFirstOperand, resultOfFirstOperand, ref requiredType); } methodInfo.WriteFunctionCallLoadFunctionAddress(opCodeMethodInfo, thisType, ref methodAddressResultNumber, llvmWriter); methodInfo.PreProcessCallParameters(opCodeMethodInfo, llvmWriter); if (llvmWriter.ProcessPluggableMethodCall(opCodeMethodInfo, methodInfo)) { return; } var returnFullyDefinedReference = methodInfo.WriteFunctionCallResult(opCodeMethodInfo, llvmWriter); writer.WriteFunctionCall(tryClause); methodInfo.WriteFunctionCallAttributes(writer); if (methodInfo.CallingConvention.HasFlag(CallingConventions.VarArgs)) { llvmWriter.WriteMethodPointerType(writer, methodInfo); writer.Write(" "); } else { methodInfo.WriteFunctionCallReturnType(llvmWriter); writer.Write(' '); // extra support if (methodInfo.IsExternalLibraryMethod()) { writer.Write("(...)* "); } } methodInfo.WriteFunctionNameExpression(methodAddressResultNumber, ownerOfExplicitInterface, llvmWriter); methodInfo.GetParameters() .WriteFunctionCallArguments( opCodeMethodInfo.OpCodeOperands, isVirtual, hasThis, isCtor, thisResultNumber, thisType, returnFullyDefinedReference, methodInfo != null ? methodInfo.ReturnType : null, llvmWriter, methodInfo.CallingConvention.HasFlag(CallingConventions.VarArgs)); tryClause.WriteFunctionCallUnwind(opCodeMethodInfo, llvmWriter); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCodePart"> /// </param> /// <param name="declaringTypeIn"> /// </param> /// <param name="objectSource"> /// </param> public static void WriteInit(this LlvmWriter llvmWriter, OpCodePart opCodePart, IType declaringTypeIn, FullyDefinedReference objectSource) { var writer = llvmWriter.Output; var declaringTypeNormal = declaringTypeIn.ToNormal(); var declaringTypeClass = declaringTypeIn.IsValueType ? declaringTypeIn.ToClass() : declaringTypeIn; writer.WriteLine("; Init obj"); if (declaringTypeNormal.IsValueType) { llvmWriter.WriteBitcast(opCodePart, objectSource, llvmWriter.ResolveType("System.Byte").ToPointerType()); writer.WriteLine(string.Empty); llvmWriter.WriteMemSet(declaringTypeNormal, opCodePart.Result); writer.WriteLine(string.Empty); if (declaringTypeNormal.IsStructureType()) { // init now opCodePart.Result = objectSource; declaringTypeClass.WriteCallInitObjectMethod(llvmWriter, opCodePart); writer.WriteLine(string.Empty); } } else { // this is type reference, initialize it with null llvmWriter.WriteBitcast(opCodePart, objectSource, llvmWriter.ResolveType("System.Byte").ToPointerType().ToPointerType()); writer.WriteLine(string.Empty); writer.WriteLine("store i8* null, i8** {0}", opCodePart.Result); } writer.Write("; end of init obj"); }
/// <summary> /// </summary> /// <param name="writer"> /// </param> /// <param name="objectResult"> /// </param> /// <param name="methodResult"> /// </param> /// <param name="invokeMethod"> /// </param> /// <param name="isStatic"> /// </param> public SynthesizedInvokeMethod( LlvmWriter writer, FullyDefinedReference objectResult, FullyDefinedReference methodResult, IMethod invokeMethod, bool isStatic) { this.writer = writer; this.objectResult = objectResult; this.MethodResult = methodResult; this.invokeMethod = invokeMethod; this.isStatic = isStatic; }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="typeToSave"> /// </param> /// <param name="operandIndex"> /// </param> /// <param name="destination"> /// </param> public static void WriteLlvmSave( this LlvmWriter llvmWriter, OpCodePart opCode, IType typeToSave, int operandIndex, FullyDefinedReference destination) { var writer = llvmWriter.Output; llvmWriter.ProcessOperator( writer, opCode, "store", typeToSave, options: LlvmWriter.OperandOptions.CastPointersToBytePointer | LlvmWriter.OperandOptions.AdjustIntTypes, operand1: operandIndex, operand2: -1); llvmWriter.WriteOperandResult(writer, opCode, operandIndex); writer.Write(", "); typeToSave.WriteTypePrefix(llvmWriter); writer.Write("* "); writer.Write(destination); }
public static void WriteLlvmSavePrimitiveIntoStructure( this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source, FullyDefinedReference destination) { var writer = llvmWriter.Output; writer.WriteLine("; Copy primitive data into a structure"); // write access to a field if (!llvmWriter.WriteFieldAccess( opCode, destination.Type.ToClass(), destination.Type.ToClass(), 0, destination)) { writer.WriteLine("; No data"); return; } writer.WriteLine(string.Empty); llvmWriter.SaveToField(opCode, opCode.Result.Type, 0); writer.WriteLine(string.Empty); writer.WriteLine("; End of Copy primitive data"); }
public static void WriteAllocateMemory(this LlvmWriter llvmWriter, OpCodePart opCodePart, FullyDefinedReference size, bool doNotTestNullValue) { var writer = llvmWriter.Output; var mallocResult = llvmWriter.WriteSetResultNumber(opCodePart, llvmWriter.ResolveType("System.Byte").ToPointerType()); writer.Write("call i8* @{0}(", llvmWriter.GetAllocator()); size.Type.WriteTypePrefix(writer); writer.Write(" "); llvmWriter.WriteResult(size); writer.WriteLine(")"); if (!doNotTestNullValue) { llvmWriter.WriteTestNullValueAndThrowException(writer, opCodePart, mallocResult, "System.OutOfMemoryException", "new_obj"); } if (!llvmWriter.Gc) { llvmWriter.WriteMemSet(mallocResult, size); writer.WriteLine(string.Empty); } }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="result"> /// </param> public static void WriteBitcast(this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference result) { var writer = llvmWriter.Output; llvmWriter.WriteSetResultNumber(opCode, llvmWriter.ResolveType("System.Byte").ToPointerType()); writer.Write("bitcast "); result.Type.WriteTypePrefix(writer, true); writer.Write(" "); llvmWriter.WriteResult(result); writer.Write(" to i8*"); }
/// <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( 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(); }
public static void WriteLlvmLoadPrimitiveFromStructure( this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source) { var writer = llvmWriter.Output; // write access to a field if (!llvmWriter.WriteFieldAccess( opCode, source.Type.ToClass(), source.Type.ToClass(), 0, source)) { writer.WriteLine("; No data"); return; } writer.WriteLine(string.Empty); llvmWriter.WriteLlvmLoad(opCode, opCode.Result.Type, opCode.Result); writer.WriteLine(string.Empty); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="result"> /// </param> public static void WriteBitcast(this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference result) { var writer = llvmWriter.Output; llvmWriter.WriteSetResultNumber(opCode, llvmWriter.System.System_Byte.ToPointerType()); writer.Write("bitcast "); result.Type.WriteTypePrefix(llvmWriter, !result.Type.IsByRef && result.Type.IsValueType()); writer.Write(" "); llvmWriter.WriteResult(result); writer.Write(" to i8*"); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="exceptionHandlingClause"> /// </param> /// <param name="upperLevelExceptionHandlingClause"> /// </param> public static void WriteCatchEnd( this LlvmWriter llvmWriter, OpCodePart opCode, CatchOfFinallyClause exceptionHandlingClause, CatchOfFinallyClause upperLevelExceptionHandlingClause) { var writer = llvmWriter.Output; var isFinally = exceptionHandlingClause.Flags.HasFlag(ExceptionHandlingClauseOptions.Finally); if (isFinally) { writer.WriteLine("; End of Finally Handler Body"); } else { writer.WriteLine("; End of Catch Handler Body"); } if (isFinally) { // process Leave jumps var index = 0; var opCodeNope = OpCodePart.CreateNop; var fullyDefinedRef = new FullyDefinedReference( string.Concat("%.finally_jump", exceptionHandlingClause.Offset), llvmWriter.System.System_Int32); llvmWriter.WriteLlvmLoad(opCodeNope, llvmWriter.System.System_Int32, fullyDefinedRef); writer.WriteLine(string.Empty); writer.WriteLine( "switch i32 {1}, label %.finally_exit{0} [", exceptionHandlingClause.Offset, opCodeNope.Result); writer.Indent++; writer.WriteLine("i32 {0}, label %.finally_exit{1}", index++, exceptionHandlingClause.Offset); foreach (var leave in exceptionHandlingClause.FinallyJumps) { writer.WriteLine("i32 {0}, label %{1}", index++, leave); } writer.Indent--; writer.WriteLine("]"); llvmWriter.WriteLabel(writer, string.Concat(".finally_exit", exceptionHandlingClause.Offset)); if (exceptionHandlingClause.EmptyFinallyRethrowRequired) { // rethrow exception in empty finally block var opCodeNop = OpCodePart.CreateNop; llvmWriter.WriteRethrow( opCodeNop, upperLevelExceptionHandlingClause, llvmWriter.tryScopes.Count > 0 ? llvmWriter.tryScopes.Peek().Catches.First() : null); } } var startOfHandlerAddress = exceptionHandlingClause.Offset; var endOfHandlerAddress = exceptionHandlingClause.Offset + exceptionHandlingClause.Length; if (exceptionHandlingClause.RethrowCatchWithCleanUpRequired) { llvmWriter.WriteLabel( writer, string.Format(".catch_with_cleanup_{0}_{1}", startOfHandlerAddress, endOfHandlerAddress)); var opCodeNop = OpCodePart.CreateNop; llvmWriter.WriteLandingPad( opCodeNop, LandingPadOptions.Cleanup, null, new[] { upperLevelExceptionHandlingClause != null ? upperLevelExceptionHandlingClause.Catch : llvmWriter.System.System_Exception }); writer.WriteLine(string.Empty); } else { writer.WriteLine("store i32 0, i32* %.error_typeid"); } writer.WriteLine("call void @__cxa_end_catch()"); if (!exceptionHandlingClause.RethrowCatchWithCleanUpRequired || upperLevelExceptionHandlingClause == null) { var isLeave = opCode.Any(Code.Leave, Code.Leave_S); var nextOp = opCode.Next; if (!isLeave && (nextOp == null || nextOp.JumpDestination == null || !nextOp.JumpDestination.Any() || nextOp.GroupAddressStart != endOfHandlerAddress)) { var noNext = nextOp == null; var isNextCatchBlock = nextOp != null && nextOp.CatchOrFinallyBegin != null; var hasExit = llvmWriter.OpsByAddressStart.Values.Any(op => op.ToCode() == Code.Ret); if (!isNextCatchBlock && !noNext && (isLeave || hasExit)) { writer.WriteLine("br label %.exit{0}", endOfHandlerAddress); llvmWriter.WriteLabel(writer, string.Concat(".exit", endOfHandlerAddress)); writer.WriteLine(string.Empty); } else { writer.WriteLine("unreachable"); } } else { if (isLeave) { writer.WriteLine("br label %.a{0}", opCode.JumpAddress()); } else { writer.WriteLine("br label %.a{0}", nextOp.GroupAddressStart); } } } else { if (!upperLevelExceptionHandlingClause.Flags.HasFlag(ExceptionHandlingClauseOptions.Finally)) { writer.WriteLine("br label %.exception_switch{0}", upperLevelExceptionHandlingClause.Offset); } else { writer.WriteLine("br label %.finally_no_error_entry{0}", upperLevelExceptionHandlingClause.Offset); } } if (isFinally) { writer.WriteLine("; End of Finally"); } else { writer.WriteLine("; End of Catch"); } }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="source"> /// </param> /// <param name="toType"> /// </param> public static void WriteBitcast( this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source, IType toType, bool asReference = true) { var writer = llvmWriter.Output; llvmWriter.WriteSetResultNumber(opCode, toType); writer.Write("bitcast "); source.Type.WriteTypePrefix(llvmWriter, asReference); writer.Write(" "); llvmWriter.WriteResult(source); writer.Write(" to "); toType.WriteTypePrefix(llvmWriter, asReference); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCodeMethodInfo"> /// </param> /// <param name="methodInfo"> /// </param> /// <param name="thisType"> /// </param> /// <param name="opCodeFirstOperand"> /// </param> /// <param name="resultOfirstOperand"> /// </param> /// <param name="requiredType"> /// </param> /// <returns> /// </returns> public static FullyDefinedReference GenerateVirtualCall( this LlvmWriter llvmWriter, OpCodePart opCodeMethodInfo, IMethod methodInfo, IType thisType, OpCodePart opCodeFirstOperand, BaseWriter.ReturnResult resultOfirstOperand, ref IType requiredType) { var writer = llvmWriter.Output; FullyDefinedReference virtualMethodAddressResultNumber = null; if (thisType.IsInterface && resultOfirstOperand.Type.TypeNotEquals(thisType)) { // we need to extract interface from an object requiredType = thisType; } // get pointer to Virtual Table and call method // 1) get pointer to virtual table writer.WriteLine("; Get Virtual Table"); IType requiredInterface; var effectiveType = requiredType ?? thisType; var methodIndex = effectiveType.GetVirtualMethodIndex(methodInfo, llvmWriter, out requiredInterface); if (requiredInterface != null) { llvmWriter.WriteInterfaceAccess(writer, opCodeMethodInfo.OpCodeOperands[0], effectiveType, requiredInterface); opCodeMethodInfo.Result = opCodeMethodInfo.OpCodeOperands[0].Result; requiredType = requiredInterface; } llvmWriter.UnaryOper(writer, opCodeMethodInfo, "bitcast", requiredType ?? thisType); writer.Write(" to "); llvmWriter.WriteMethodPointerType(writer, methodInfo, thisType); writer.WriteLine("**"); var pointerToInterfaceVirtualTablePointersResultNumber = opCodeMethodInfo.Result; // load pointer llvmWriter.WriteSetResultNumber(opCodeMethodInfo, llvmWriter.ResolveType("System.Byte").ToPointerType().ToPointerType()); writer.Write("load "); llvmWriter.WriteMethodPointerType(writer, methodInfo, thisType); writer.Write("** "); llvmWriter.WriteResult(pointerToInterfaceVirtualTablePointersResultNumber); writer.Write(", align {0}", LlvmWriter.PointerSize); writer.WriteLine(string.Empty); var virtualTableOfMethodPointersResultNumber = opCodeMethodInfo.Result; // get address of a function writer.WriteLine("; Get Virtual Index of Method: {0}", methodInfo.FullName); llvmWriter.WriteSetResultNumber(opCodeMethodInfo, llvmWriter.ResolveType("System.Byte").ToPointerType()); writer.Write("getelementptr inbounds "); llvmWriter.WriteMethodPointerType(writer, methodInfo, thisType); writer.Write("* "); llvmWriter.WriteResult(virtualTableOfMethodPointersResultNumber); writer.WriteLine(", i64 {0}", methodIndex); var pointerToFunctionPointerResultNumber = opCodeMethodInfo.Result; // load method address llvmWriter.WriteSetResultNumber(opCodeMethodInfo, llvmWriter.ResolveType("System.Byte").ToPointerType()); writer.Write("load "); llvmWriter.WriteMethodPointerType(writer, methodInfo, thisType); writer.Write("* "); llvmWriter.WriteResult(pointerToFunctionPointerResultNumber); writer.WriteLine(string.Empty); // remember virtual method address result virtualMethodAddressResultNumber = opCodeMethodInfo.Result; if (thisType.IsInterface) { opCodeFirstOperand.Result = virtualTableOfMethodPointersResultNumber; llvmWriter.WriteGetThisPointerFromInterfacePointer( writer, opCodeMethodInfo, methodInfo, thisType, pointerToInterfaceVirtualTablePointersResultNumber); var thisPointerResultNumber = opCodeMethodInfo.Result; // set ot for Call op code opCodeMethodInfo.OpCodeOperands[0].Result = thisPointerResultNumber; } return(virtualMethodAddressResultNumber); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="result"> /// </param> public static void WriteBitcast(this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference result) { var writer = llvmWriter.Output; llvmWriter.WriteSetResultNumber(opCode, llvmWriter.System.System_Byte.ToPointerType()); writer.Write("bitcast "); result.Type.WriteTypePrefix(llvmWriter, !result.Type.IsByRef && result.Type.IsValueType()); writer.Write(" "); llvmWriter.WriteResult(result); writer.Write(" to i8*"); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="typeToLoad"> /// </param> /// <param name="source"> /// </param> /// <param name="appendReference"> /// </param> /// <param name="structAsRef"> /// </param> /// <param name="indirect"> /// </param> public static void WriteLlvmLoad( this LlvmWriter llvmWriter, OpCodePart opCode, IType typeToLoad, FullyDefinedReference source, bool appendReference = true, bool structAsRef = false, bool indirect = false) { // TODO: improve it, by checking if Source is Reference or Pointer var writer = llvmWriter.Output; var isStruct = typeToLoad.ToNormal().IsStructureType(); Debug.Assert(structAsRef || !isStruct || typeToLoad.IsByRef || isStruct && !typeToLoad.IsByRef && opCode.HasResult); if (!isStruct || typeToLoad.IsByRef || structAsRef || !opCode.HasResult || (indirect && !isStruct)) { ////Debug.Assert(source.Type.IsPointer); var dereferencedType = source.Type.IsPointer ? source.Type.GetElementType() : null; var effectiveSource = source; // check if you need bitcast pointer type if (!typeToLoad.IsPointer && dereferencedType != null && typeToLoad.TypeNotEquals(dereferencedType)) { // check if you need cast here llvmWriter.WriteBitcast(opCode, source, typeToLoad); writer.WriteLine(string.Empty); effectiveSource = opCode.Result; } if (indirect && !source.Type.IsPointer && !source.Type.IsByRef && source.Type.IntTypeBitSize() > 0) { // check if you need cast here llvmWriter.WriteIntToPtr(opCode, source, typeToLoad); writer.WriteLine(string.Empty); effectiveSource = opCode.Result; } llvmWriter.WriteSetResultNumber(opCode, typeToLoad); // last part writer.Write("load "); typeToLoad.WriteTypePrefix(writer, structAsRef); if (appendReference) { // add reference to type writer.Write('*'); } writer.Write(' '); writer.Write(effectiveSource.ToString()); // TODO: optional do we need to calculate it propertly? writer.Write(", align " + LlvmWriter.PointerSize); } else { llvmWriter.WriteCopyStruct(writer, opCode, typeToLoad, source, opCode.Result); } }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCodeMethodInfo"> /// </param> /// <param name="methodInfo"> /// </param> /// <param name="isVirtual"> /// </param> /// <param name="hasThis"> /// </param> /// <param name="isCtor"> /// </param> /// <param name="thisResultNumber"> /// </param> /// <param name="tryClause"> /// </param> public static void WriteCall( this LlvmWriter llvmWriter, OpCodePart opCodeMethodInfo, IMethod methodInfo, bool isVirtual, bool hasThis, bool isCtor, FullyDefinedReference thisResultNumber, TryClause tryClause) { var writer = llvmWriter.Output; IType thisType; bool hasThisArgument; OpCodePart opCodeFirstOperand; BaseWriter.ReturnResult resultOfFirstOperand; bool isIndirectMethodCall; IType ownerOfExplicitInterface; IType requiredType; methodInfo.WriteFunctionCallProlog( opCodeMethodInfo, isVirtual, hasThis, llvmWriter, out thisType, out hasThisArgument, out opCodeFirstOperand, out resultOfFirstOperand, out isIndirectMethodCall, out ownerOfExplicitInterface, out requiredType); llvmWriter.CheckIfMethodExternalDeclarationIsRequired(methodInfo, ownerOfExplicitInterface); llvmWriter.CheckIfExternalDeclarationIsRequired(methodInfo.DeclaringType); if (hasThisArgument) { opCodeMethodInfo.WriteFunctionCallPrepareThisExpression( thisType, opCodeFirstOperand, resultOfFirstOperand, llvmWriter); } FullyDefinedReference methodAddressResultNumber = null; if (isIndirectMethodCall) { methodAddressResultNumber = llvmWriter.GenerateVirtualCall( opCodeMethodInfo, methodInfo, thisType, opCodeFirstOperand, resultOfFirstOperand, ref requiredType); } methodInfo.WriteFunctionCallLoadFunctionAddress( opCodeMethodInfo, thisType, ref methodAddressResultNumber, llvmWriter); methodInfo.PreProcessCallParameters(opCodeMethodInfo, llvmWriter); if (llvmWriter.ProcessPluggableMethodCall(opCodeMethodInfo, methodInfo)) { return; } var returnFullyDefinedReference = methodInfo.WriteFunctionCallResult(opCodeMethodInfo, llvmWriter); writer.WriteFunctionCall(tryClause); methodInfo.WriteFunctionCallAttributes(writer); if (methodInfo.CallingConvention.HasFlag(CallingConventions.VarArgs)) { llvmWriter.WriteMethodPointerType(writer, methodInfo); writer.Write(" "); } else { methodInfo.WriteFunctionCallReturnType(llvmWriter); writer.Write(' '); // extra support if (methodInfo.IsExternalLibraryMethod()) { writer.Write("(...)* "); } } methodInfo.WriteFunctionNameExpression(methodAddressResultNumber, ownerOfExplicitInterface, llvmWriter); methodInfo.GetParameters() .WriteFunctionCallArguments( opCodeMethodInfo.OpCodeOperands, isVirtual, hasThis, isCtor, thisResultNumber, thisType, returnFullyDefinedReference, methodInfo != null ? methodInfo.ReturnType : null, llvmWriter, methodInfo.CallingConvention.HasFlag(CallingConventions.VarArgs)); tryClause.WriteFunctionCallUnwind(opCodeMethodInfo, llvmWriter); }
/// <summary> /// </summary> /// <param name="methodInfo"> /// </param> /// <param name="methodAddressResultNumber"> /// </param> /// <param name="ownerOfExplicitInterface"> /// </param> /// <param name="llvmWriter"> /// </param> public static void WriteFunctionNameExpression( this IMethod methodInfo, FullyDefinedReference methodAddressResultNumber, IType ownerOfExplicitInterface, LlvmWriter llvmWriter) { var writer = llvmWriter.Output; var isIndirectMethodCall = methodAddressResultNumber != null; if (isIndirectMethodCall || methodInfo.IsUnmanagedMethodReference) { llvmWriter.WriteResult(methodAddressResultNumber); } else { // default method name llvmWriter.WriteMethodDefinitionName(writer, methodInfo, ownerOfExplicitInterface); } }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="fromResult"> /// </param> /// <param name="toType"> /// </param> /// <param name="throwExceptionIfNull"> /// </param> /// <returns> /// </returns> public static bool WriteCast( this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference fromResult, IType toType, bool throwExceptionIfNull = false) { var writer = llvmWriter.Output; var bareType = !fromResult.Type.IsArray ? fromResult.Type.ToBareType() : fromResult.Type; if (toType.IsInterface && !(fromResult is ConstValue)) { if (bareType.GetAllInterfaces().Contains(toType)) { opCode.Result = fromResult; llvmWriter.WriteInterfaceAccess(writer, opCode, bareType, toType); } else { llvmWriter.WriteDynamicCast(writer, opCode, fromResult, toType, true, throwExceptionIfNull); } } else if (fromResult.Type.IntTypeBitSize() == LlvmWriter.PointerSize * 8 && (toType.IsPointer || toType.IsByRef)) { LlvmConvert(llvmWriter, opCode, string.Empty, string.Empty, toType, true); } else if (fromResult.Type.IsArray || (fromResult.Type.IsPointer && bareType.TypeEquals(llvmWriter.System.System_Void)) || toType.IsArray || toType.IsPointer || toType.IsByRef || bareType.IsDerivedFrom(toType) || (fromResult is ConstValue)) { llvmWriter.WriteSetResultNumber(opCode, toType); writer.Write("bitcast "); fromResult.Type.WriteTypePrefix(llvmWriter); writer.Write(' '); llvmWriter.WriteResult(fromResult); writer.Write(" to "); toType.WriteTypePrefix(llvmWriter, toType.IsStructureType()); } else { Debug.Assert(fromResult.Type.IntTypeBitSize() == 0); llvmWriter.WriteDynamicCast(writer, opCode, fromResult, toType, true, throwExceptionIfNull); } writer.WriteLine(string.Empty); return true; }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="source"> /// </param> /// <param name="toType"> /// </param> public static void WritePtrToInt(this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source, IType toType) { var writer = llvmWriter.Output; llvmWriter.WriteSetResultNumber(opCode, toType); writer.Write("ptrtoint "); source.Type.WriteTypePrefix(writer, true); writer.Write(" "); llvmWriter.WriteResult(source); writer.Write(" to "); toType.WriteTypePrefix(writer); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="source"> /// </param> /// <param name="toType"> /// </param> public static void WriteIntToPtr( this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source, IType toType) { var writer = llvmWriter.Output; Debug.Assert(!source.Type.IsPointer && !source.Type.IsByRef); llvmWriter.WriteSetResultNumber(opCode, toType); writer.Write("inttoptr "); source.Type.WriteTypePrefix(llvmWriter); writer.Write(" "); llvmWriter.WriteResult(source); writer.Write(" to "); toType.WriteTypePrefix(llvmWriter, true); }
/// <summary> /// </summary> /// <param name="parameterInfos"> /// </param> /// <param name="used"> /// </param> /// <param name="isVirtual"> /// </param> /// <param name="hasThis"> /// </param> /// <param name="isCtor"> /// </param> /// <param name="resultNumberForThis"> /// </param> /// <param name="thisType"> /// </param> /// <param name="resultNumberForReturn"> /// </param> /// <param name="returnType"> /// </param> /// <param name="llvmWriter"> /// </param> public static void WriteFunctionCallArguments( this IEnumerable <IParameter> parameterInfos, OpCodePart[] used, bool @isVirtual, bool hasThis, bool isCtor, FullyDefinedReference resultNumberForThis, IType thisType, FullyDefinedReference resultNumberForReturn, IType returnType, LlvmWriter llvmWriter, bool varArg) { var writer = llvmWriter.Output; writer.Write("("); var index = 0; var returnIsStruct = returnType != null && returnType.IsStructureType(); var comaRequired = false; // allocate space for structure if return type is structure if (returnIsStruct) { returnType.WriteTypePrefix(llvmWriter, returnType.IsStructureType()); writer.Write(' '); if (resultNumberForReturn != null) { llvmWriter.WriteResult(resultNumberForReturn); } comaRequired = true; } if (hasThis) { if (comaRequired) { writer.Write(", "); } thisType.ToClass().WriteTypePrefix(llvmWriter); writer.Write(' '); if (resultNumberForThis != null) { llvmWriter.WriteResult(resultNumberForThis); } else if (used != null && used.Length > 0) { llvmWriter.WriteResult(used[0].Result); } comaRequired = true; } llvmWriter.CheckIfExternalDeclarationIsRequired(returnType); var argsContainsThisArg = used != null ? (used.Length - parameterInfos.Count()) > 0 : false; var argShift = @isVirtual || (hasThis && !isCtor && argsContainsThisArg) ? 1 : 0; // add parameters foreach (var parameter in parameterInfos) { var effectiveIndex = index + argShift; var usedItem = used[effectiveIndex]; if (comaRequired) { writer.Write(", "); } llvmWriter.WriteFunctionCallParameterArgument(usedItem, parameter); comaRequired = true; index++; } if (varArg) { // VarArgs while (index < used.Length) { var effectiveIndex = index + argShift; var usedItem = used[effectiveIndex]; if (comaRequired) { writer.Write(", "); } llvmWriter.WriteFunctionCallVarArgument(usedItem, usedItem.Result.Type); comaRequired = true; index++; } } writer.Write(")"); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="source"> /// </param> /// <param name="toType"> /// </param> public static void WritePtrToInt(this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source, IType toType) { var writer = llvmWriter.Output; llvmWriter.WriteSetResultNumber(opCode, toType); writer.Write("ptrtoint "); source.Type.WriteTypePrefix(writer, true); writer.Write(" "); llvmWriter.WriteResult(source); writer.Write(" to "); toType.WriteTypePrefix(writer); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="exceptionHandlingClause"> /// </param> /// <param name="upperLevelExceptionHandlingClause"> /// </param> public static void WriteCatchEnd( this LlvmWriter llvmWriter, OpCodePart opCode, CatchOfFinallyClause exceptionHandlingClause, CatchOfFinallyClause upperLevelExceptionHandlingClause) { var writer = llvmWriter.Output; var isFinally = exceptionHandlingClause.Flags.HasFlag(ExceptionHandlingClauseOptions.Finally); if (isFinally) { writer.WriteLine("; End of Finally Handler Body"); } else { writer.WriteLine("; End of Catch Handler Body"); } if (isFinally) { // process Leave jumps var index = 0; var opCodeNope = OpCodePart.CreateNop; var fullyDefinedRef = new FullyDefinedReference( string.Concat("%.finally_jump", exceptionHandlingClause.Offset), llvmWriter.System.System_Int32); llvmWriter.WriteLlvmLoad(opCodeNope, llvmWriter.System.System_Int32, fullyDefinedRef); writer.WriteLine(string.Empty); writer.WriteLine( "switch i32 {1}, label %.finally_exit{0} [", exceptionHandlingClause.Offset, opCodeNope.Result); writer.Indent++; writer.WriteLine("i32 {0}, label %.finally_exit{1}", index++, exceptionHandlingClause.Offset); foreach (var leave in exceptionHandlingClause.FinallyJumps) { writer.WriteLine("i32 {0}, label %{1}", index++, leave); } writer.Indent--; writer.WriteLine("]"); llvmWriter.WriteLabel(writer, string.Concat(".finally_exit", exceptionHandlingClause.Offset)); if (exceptionHandlingClause.EmptyFinallyRethrowRequired) { // rethrow exception in empty finally block var opCodeNop = OpCodePart.CreateNop; llvmWriter.WriteRethrow( opCodeNop, upperLevelExceptionHandlingClause, llvmWriter.tryScopes.Count > 0 ? llvmWriter.tryScopes.Peek().Catches.First() : null); } } var startOfHandlerAddress = exceptionHandlingClause.Offset; var endOfHandlerAddress = exceptionHandlingClause.Offset + exceptionHandlingClause.Length; if (exceptionHandlingClause.RethrowCatchWithCleanUpRequired) { llvmWriter.WriteLabel( writer, string.Format(".catch_with_cleanup_{0}_{1}", startOfHandlerAddress, endOfHandlerAddress)); var opCodeNop = OpCodePart.CreateNop; llvmWriter.WriteLandingPad( opCodeNop, LandingPadOptions.Cleanup, null, new[] { upperLevelExceptionHandlingClause != null ? upperLevelExceptionHandlingClause.Catch : llvmWriter.System.System_Exception }); writer.WriteLine(string.Empty); } else { writer.WriteLine("store i32 0, i32* %.error_typeid"); } writer.WriteLine("call void @__cxa_end_catch()"); if (!exceptionHandlingClause.RethrowCatchWithCleanUpRequired || upperLevelExceptionHandlingClause == null) { var isLeave = opCode.Any(Code.Leave, Code.Leave_S); var nextOp = opCode.Next; if (!isLeave && (nextOp == null || nextOp.JumpDestination == null || !nextOp.JumpDestination.Any() || nextOp.GroupAddressStart != endOfHandlerAddress)) { var noNext = nextOp == null; var isNextCatchBlock = nextOp != null && nextOp.CatchOrFinallyBegin != null; var hasExit = llvmWriter.OpsByAddressStart.Values.Any(op => op.ToCode() == Code.Ret); if (!isNextCatchBlock && !noNext && (isLeave || hasExit)) { writer.WriteLine("br label %.exit{0}", endOfHandlerAddress); llvmWriter.WriteLabel(writer, string.Concat(".exit", endOfHandlerAddress)); writer.WriteLine(string.Empty); } else { writer.WriteLine("unreachable"); } } else { if (isLeave) { writer.WriteLine("br label %.a{0}", opCode.JumpAddress()); } else { writer.WriteLine("br label %.a{0}", nextOp.GroupAddressStart); } } } else { if (!upperLevelExceptionHandlingClause.Flags.HasFlag(ExceptionHandlingClauseOptions.Finally)) { writer.WriteLine("br label %.exception_switch{0}", upperLevelExceptionHandlingClause.Offset); } else { writer.WriteLine("br label %.finally_no_error_entry{0}", upperLevelExceptionHandlingClause.Offset); } } if (isFinally) { writer.WriteLine("; End of Finally"); } else { writer.WriteLine("; End of Catch"); } }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="type"> /// </param> /// <param name="op1"> /// </param> public static void WriteMemSet(this LlvmWriter llvmWriter, IType type, FullyDefinedReference op1) { var writer = llvmWriter.Output; writer.Write( "call void @llvm.memset.p0i8.i32(i8* {0}, i8 0, i32 {1}, i32 {2}, i1 false)", op1, type.GetTypeSize(llvmWriter, type.IsPrimitiveType() && !type.UseAsClass), LlvmWriter.PointerSize /*Align*/); }
public static void WriteMemCopy( this LlvmWriter llvmWriter, FullyDefinedReference op1, FullyDefinedReference op2, FullyDefinedReference size) { var writer = llvmWriter.Output; writer.WriteLine( "call void @llvm.memcpy.p0i8.p0i8.i32(i8* {0}, i8* {1}, i32 {2}, i32 {3}, i1 false)", op1, op2, size, LlvmWriter.PointerSize /*Align*/); }
public static void WriteMemSet( this LlvmWriter llvmWriter, FullyDefinedReference op1, FullyDefinedReference size, int align = 0) { var writer = llvmWriter.Output; writer.Write("call void @llvm.memset.p0i8.i32(i8* {0}, i8 0, ", op1); size.Type.WriteTypePrefix(llvmWriter); writer.Write(" "); llvmWriter.WriteResult(size); writer.Write(", i32 {0}, i1 false)", align > 0 ? align : LlvmWriter.PointerSize /*Align*/); }