public void Execute(LlvmWriter writer, OpCodePart opCode) { if (this.action != null) { this.action.Invoke(writer, opCode); } }
/// <summary> /// </summary> /// <param name="methodBase"> /// </param> /// <param name="opCodeMethodInfo"> /// </param> /// <param name="llvmWriter"> /// </param> public static void PreProcessCallParameters(this IMethod methodBase, OpCodePart opCodeMethodInfo, LlvmWriter llvmWriter) { // check if you need to cast parameter if (opCodeMethodInfo.OpCodeOperands == null) { return; } var writer = llvmWriter.Output; var parameters = methodBase.GetParameters(); var index = opCodeMethodInfo.OpCodeOperands.Count() - parameters.Count(); foreach (var parameter in parameters) { var operand = opCodeMethodInfo.OpCodeOperands[index]; var dynamicCastRequired = false; if (parameter.ParameterType.IsClassCastRequired(operand, out dynamicCastRequired)) { writer.WriteLine("; Cast of '{0}' parameter", parameter.Name); llvmWriter.WriteCast(operand, operand.Result, parameter.ParameterType); } operand.RequiredIncomingType = parameter.ParameterType; llvmWriter.AdjustOperandResultTypeToIncomingType(operand); index++; } }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <returns> /// </returns> public static IncrementalResult WriteAllocateException(this LlvmWriter llvmWriter, OpCodePart opCode) { var writer = llvmWriter.Output; writer.WriteLine("; Allocate exception"); var errorAllocationResultNumber = llvmWriter.WriteSetResultNumber(opCode, llvmWriter.ResolveType("System.Byte").ToPointerType()); writer.Write("call i8* @__cxa_allocate_exception(i32 {0})", LlvmWriter.PointerSize); writer.WriteLine(string.Empty); var newExceptionResult = opCode.OpCodeOperands[0].Result; opCode.OpCodeOperands[0].Result = opCode.Result; llvmWriter.WriteBitcast(opCode, opCode.Result, newExceptionResult.Type); writer.WriteLine("*"); opCode.OpCodeOperands[0].Result = newExceptionResult; llvmWriter.UnaryOper(writer, opCode, "store"); writer.Write(", "); opCode.OpCodeOperands[0].Result.Type.WriteTypePrefix(writer); writer.Write("* "); llvmWriter.WriteResult(opCode.Result); writer.WriteLine(string.Empty); return errorAllocationResultNumber; }
public static void WriteCreateInstanceFunction(this IMethod method, OpCodePart opCodeMethodInfo, LlvmWriter llvmWriter) { switch (method.MetadataName) { case "CreateInstance`1": // this is dummy function which is not used now as using Boxing before calling CreateInstance is enough for us var type = method.GetGenericArguments().First(); ////if (!type.IsStructureType()) ////{ //// opCodeMethodInfo.Result = llvmWriter.WriteNewCallingDefaultConstructor(llvmWriter.Output, type); ////} ////else ////{ //// llvmWriter.WriteInit(opCodeMethodInfo, type, opCodeMethodInfo.Destination); ////} opCodeMethodInfo.Result = new ConstValue(null, type); break; default: throw new NotImplementedException(); } }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="elementType"> /// </param> /// <param name="length"> /// </param> public static FullyDefinedReference WriteStringAllocationSize( this LlvmWriter llvmWriter, OpCodePart opCode, IType stringType, IType charType) { Debug.Assert(stringType.IsString, "This is for string only"); var writer = llvmWriter.Output; writer.WriteLine("; Calculate String allocation size"); object[] code; IList<object> tokenResolutions; IList<IType> locals; IList<IParameter> parameters; GetCalculationPartOfStringAllocationSizeMethodBody( llvmWriter, stringType, charType, out code, out tokenResolutions, out locals, out parameters); var constructedMethod = MethodBodyBank.GetMethodDecorator(null, code, tokenResolutions, locals, parameters); // actual write var opCodes = llvmWriter.WriteCustomMethodPart(constructedMethod, null); return opCodes.Last().Result; }
public void ProcessAlternativeValues(OpCodePart opCodePart) { // read all alternative values from other branches if (opCodePart.JumpDestination == null) { return; } var previousFlow = opCodePart.Previous != null ? opCodePart.Previous.OpCode.FlowControl : FlowControl.Break; var noMainEntry = previousFlow == FlowControl.Branch || previousFlow == FlowControl.Return || previousFlow == FlowControl.Throw || previousFlow == FlowControl.Break; var entires = opCodePart.JumpDestination.Where(opCode => opCode.IsJumpForward()); var entriesList = entires as IList<OpCodePart> ?? entires.ToList(); //if (entriesList.Count() <= (noMainEntry ? 1 : 0)) if (!entriesList.Any()) { return; } var values = entriesList.Where(opCode => opCode.BranchStackValue != null).Select(opCode => opCode.BranchStackValue); if (!values.Any()) { return; } var alternativeValues = GetPhiValues(values, !noMainEntry ? this.main.Peek() : null); if (alternativeValues == null) { return; } var firstValue = alternativeValues.Values.OrderByDescending(v => v.AddressStart).First(); if (alternativeValues.Values.Count() == 1) { // it just one value, we can push it back to stack if (!this.main.Any() || this.main.All(op => op.AddressStart != firstValue.AddressStart)) { this.main.Push(firstValue); } return; } opCodePart.AlternativeValues = alternativeValues; if (noMainEntry) { return; } while (this.main.Any() && alternativeValues.Values.Contains(this.main.Peek())) { this.main.Pop(); } this.main.Push(firstValue); }
/// <summary> /// </summary> /// <param name="method"> /// </param> /// <param name="opCodeMethodInfo"> /// </param> /// <param name="llvmWriter"> /// </param> /// <exception cref="NotImplementedException"> /// </exception> public static void WriteArrayFunction(this IMethod method, OpCodePart opCodeMethodInfo, LlvmWriter llvmWriter) { switch (method.Name) { case "get_Length": llvmWriter.WriteArrayGetLength(opCodeMethodInfo); break; default: throw new NotImplementedException(); } }
public void SaveBranchStackValue(OpCodePart opCode, BaseWriter baseWriter) { switch (opCode.ToCode()) { case Code.Br: case Code.Br_S: case Code.Beq: case Code.Beq_S: case Code.Blt: case Code.Blt_S: case Code.Bgt: case Code.Bgt_S: case Code.Ble: case Code.Ble_S: case Code.Bge: case Code.Bge_S: case Code.Blt_Un: case Code.Blt_Un_S: case Code.Bgt_Un: case Code.Bgt_Un_S: case Code.Ble_Un: case Code.Ble_Un_S: case Code.Bge_Un: case Code.Bge_Un_S: case Code.Bne_Un: case Code.Bne_Un_S: case Code.Brtrue: case Code.Brtrue_S: case Code.Brfalse: case Code.Brfalse_S: if (opCode.IsJumpForward() && this.main.Any()) { opCode.BranchStackValue = this.main.Peek(); } break; } }
public static void WriteInterlockedFunction(this IMethod method, OpCodePart opCodeMethodInfo, LlvmWriter llvmWriter) { switch (method.MetadataName) { case "Increment": opCodeMethodInfo.IncDecInterlockBase("atomicrmw add ", " acquire", llvmWriter); break; case "Decrement": opCodeMethodInfo.IncDecInterlockBase("atomicrmw sub ", " acquire", llvmWriter); break; case "Exchange`1": case "Exchange": opCodeMethodInfo.InterlockBase("atomicrmw xchg ", " acquire", false, llvmWriter); break; case "CompareExchange`1": case "CompareExchange": opCodeMethodInfo.InterlockBase("cmpxchg ", " acq_rel monotonic", llvmWriter.IsLlvm36OrHigher, llvmWriter); break; } }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="exceptionHandlingClause"> /// </param> /// <returns> /// </returns> private static IType WriteThrowInvoke(LlvmWriter llvmWriter, OpCodePart opCode, CatchOfFinallyClause exceptionHandlingClause) { var writer = llvmWriter.Output; var errorAllocationResultNumber = llvmWriter.WriteAllocateException(opCode); var exceptionPointerType = opCode.OpCodeOperands[0].Result.Type; writer.Write("invoke void @__cxa_throw(i8* {0}, i8* bitcast (", errorAllocationResultNumber); exceptionPointerType.WriteRttiPointerClassInfoDeclaration(writer); writer.WriteLine("* @\"{0}\" to i8*), i8* null)", exceptionPointerType.GetRttiPointerInfoName()); writer.Indent++; if (exceptionHandlingClause != null) { writer.Write("to label %.unreachable unwind label %.catch{0}", exceptionHandlingClause.Offset); } else { writer.Write("to label %.unreachable unwind label %.unwind_exception"); llvmWriter.needToWriteUnwindException = true; } llvmWriter.WriteDbgLine(opCode); writer.WriteLine(string.Empty); writer.Indent--; llvmWriter.needToWriteUnreachable = true; return exceptionPointerType; }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <returns> /// </returns> private static IType WriteThrowCall(LlvmWriter llvmWriter, OpCodePart opCode) { var writer = llvmWriter.Output; var errorAllocationResultNumber = llvmWriter.WriteAllocateException(opCode); var exceptionPointerType = opCode.OpCodeOperands[0].Result.Type; writer.Write("call void @__cxa_throw(i8* {0}, i8* bitcast (", errorAllocationResultNumber); exceptionPointerType.WriteRttiPointerClassInfoDeclaration(writer); writer.Write("* @\"{0}\" to i8*), i8* null)", exceptionPointerType.GetRttiPointerInfoName()); llvmWriter.WriteDbgLine(opCode); writer.WriteLine(string.Empty); writer.WriteLine("unreachable"); return exceptionPointerType; }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="exceptionHandlingClause"> /// </param> public static void WriteThrow(this LlvmWriter llvmWriter, OpCodePart opCode, CatchOfFinallyClause exceptionHandlingClause) { var writer = llvmWriter.Output; writer.WriteLine("; Throw"); var exceptionPointerType = exceptionHandlingClause != null ? WriteThrowInvoke(llvmWriter, opCode, exceptionHandlingClause) : WriteThrowCall(llvmWriter, opCode); llvmWriter.typeRttiPointerDeclRequired.Add(exceptionPointerType); llvmWriter.CheckIfExternalDeclarationIsRequired(exceptionPointerType); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="exceptionHandlingClause"> /// </param> /// <param name="upperLevelExceptionHandlingClause"> /// </param> public static void WriteRethrow( this LlvmWriter llvmWriter, OpCodePart opCode, CatchOfFinallyClause exceptionHandlingClause, CatchOfFinallyClause upperLevelExceptionHandlingClause) { var writer = llvmWriter.Output; writer.WriteLine("; Rethrow"); WriteRethrowInvoke(llvmWriter, exceptionHandlingClause); }
/// <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> public static void WriteLlvmLoad( this LlvmWriter llvmWriter, OpCodePart opCode, IType typeToLoad, IncrementalResult source, bool appendReference = true, bool structAsRef = false) { llvmWriter.WriteLlvmLoad(opCode, typeToLoad, new FullyDefinedReference(source.ToString(), source.Type), appendReference, structAsRef); }
/// <summary> /// </summary> /// <param name="opCode"> /// </param> public UsedByInfo(OpCodePart opCode) { this.OpCode = opCode; }
/// <summary> /// </summary> /// <param name="opCodes"> /// </param> public OpCodeBlock(OpCodePart[] opCodes) : base(OpCodesEmit.Nop, 0, 0) { this.OpCodes = opCodes; }
/// <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() : llvmWriter.ResolveType("System.Array"); 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 || toType.IsArray || toType.IsPointer || toType.IsByRef || bareType.IsDerivedFrom(toType) || (fromResult is ConstValue)) { llvmWriter.WriteSetResultNumber(opCode, toType, true); writer.Write("bitcast "); fromResult.Type.WriteTypePrefix(writer, true); writer.Write(' '); llvmWriter.WriteResult(fromResult); writer.Write(" to "); toType.WriteTypePrefix(writer, true); } 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="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(writer); writer.Write("* "); writer.Write(destination); }
/// <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); }
public static void WriteLlvmLoadPrimitiveFromStructure(this LlvmWriter llvmWriter, OpCodePart opCode, FullyDefinedReference source) { var writer = llvmWriter.Output; // write access to a field if (!llvmWriter.WriteFieldAccess( writer, 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 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( writer, 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="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="opCode"> /// </param> public static void WriteCatchProlog(this LlvmWriter llvmWriter, OpCodePart opCode) { var writer = llvmWriter.Output; writer.WriteLine("; Cacth Clauses - Prolog"); var handlerOffset = opCode.ExceptionHandlers.First().Offset; writer.Indent--; writer.WriteLine(".catch{0}:", handlerOffset); writer.Indent++; var catchTypes = opCode.ExceptionHandlers.Where(eh => eh.Flags == ExceptionHandlingClauseOptions.Clause).Select(eh => eh.Catch).ToArray(); var finallyOrFault = opCode.ExceptionHandlers.FirstOrDefault( eh => eh.Flags.HasFlag(ExceptionHandlingClauseOptions.Finally) || eh.Flags.HasFlag(ExceptionHandlingClauseOptions.Fault)); llvmWriter.WriteLandingPad(opCode, finallyOrFault != null ? LandingPadOptions.Cleanup : LandingPadOptions.None, finallyOrFault, catchTypes); writer.WriteLine(string.Empty); }
/// <summary> /// </summary> /// <param name="opCode"> /// </param> /// <param name="operandPosition"> /// </param> public UsedByInfo(OpCodePart opCode, int operandPosition) { this.OpCode = opCode; this.OperandPosition = operandPosition; }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="opCode"> /// </param> /// <param name="options"> /// </param> /// <param name="finallyOrFaultClause"> /// </param> /// <param name="catch"> /// </param> /// <param name="filter"> /// </param> /// <param name="exceptionAllocationResultNumber"> /// </param> public static void WriteLandingPad( this LlvmWriter llvmWriter, OpCodePart opCode, LandingPadOptions options, CatchOfFinallyClause finallyOrFaultClause, IType[] @catch = null, int[] filter = null, int? exceptionAllocationResultNumber = null) { var writer = llvmWriter.Output; llvmWriter.WriteLandingPadVariables(); var landingPadResult = llvmWriter.WriteSetResultNumber(opCode, llvmWriter.ResolveType("System.Byte").ToPointerType()); writer.WriteLine("landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)"); if (options.HasFlag(LandingPadOptions.Cleanup)) { writer.Indent++; writer.WriteLine("cleanup"); writer.Indent--; } if (options.HasFlag(LandingPadOptions.EmptyFilter)) { writer.Indent++; writer.WriteLine("filter [0 x i8*] zeroinitializer"); writer.Indent--; } if (@catch != null && @catch.Any()) { foreach (var catchType in @catch) { writer.Indent++; if (catchType != null) { writer.Write("catch i8* bitcast ("); catchType.WriteRttiPointerClassInfoDeclaration(writer); writer.WriteLine("* @\"{0}\" to i8*)", catchType.GetRttiPointerInfoName()); llvmWriter.typeRttiPointerDeclRequired.Add(catchType); llvmWriter.CheckIfExternalDeclarationIsRequired(catchType); } else { writer.Write("catch i8* null"); } writer.Indent--; } } else if (finallyOrFaultClause != null) { // default catch with rethrowing it writer.Indent++; writer.WriteLine("catch i8* null"); writer.Indent--; finallyOrFaultClause.EmptyFinallyRethrowRequired = true; } var getErrorObjectResultNumber = llvmWriter.WriteSetResultNumber(opCode, llvmWriter.ResolveType("System.Byte").ToPointerType()); writer.WriteLine("extractvalue {1} {0}, 0", landingPadResult, "{ i8*, i32 }"); writer.WriteLine("store i8* {0}, i8** %.error_object", getErrorObjectResultNumber); var getErrorTypeIdResultNumber = llvmWriter.WriteSetResultNumber(opCode, llvmWriter.ResolveType("System.Int32")); writer.WriteLine("extractvalue {1} {0}, 1", landingPadResult, "{ i8*, i32 }"); writer.Write("store i32 {0}, i32* %.error_typeid", getErrorTypeIdResultNumber); if (exceptionAllocationResultNumber.HasValue) { writer.WriteLine(string.Empty); writer.Write("call void @__cxa_free_exception(i8* {0})", exceptionAllocationResultNumber.Value); } opCode.Result = landingPadResult; }
private static bool JumpOrLabelPoint(OpCodePart current, out bool startOrEnd) { if ((current.OpCode.FlowControl == FlowControl.Cond_Branch || current.OpCode.FlowControl == FlowControl.Branch) && !current.Any(Code.Leave, Code.Leave_S)) { startOrEnd = false; return true; } if (current.JumpDestination != null && current.JumpDestination.Any()) { startOrEnd = true; return true; } startOrEnd = false; return false; }
/// <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="fromType"> /// </param> /// <param name="custromName"> /// </param> /// <param name="toType"> /// </param> /// <param name="appendReference"> /// </param> /// <param name="doNotConvert"> /// </param> /// <exception cref="NotImplementedException"> /// </exception> public static void WriteCast( this LlvmWriter llvmWriter, OpCodePart opCode, IType fromType, string custromName, IType toType, bool appendReference = false, bool doNotConvert = false) { // TODO: remove this one. use anather one var writer = llvmWriter.Output; if (!fromType.IsInterface && toType.IsInterface) { throw new NotImplementedException(); ////opCode.Result = res; ////this.WriteInterfaceAccess(writer, opCode, fromType, toType); } else { llvmWriter.WriteSetResultNumber(opCode, toType); writer.Write("bitcast "); fromType.WriteTypePrefix(writer, true); writer.Write(' '); writer.Write(custromName); writer.Write(" to "); toType.WriteTypePrefix(writer, true); if (appendReference) { // result should be array writer.Write('*'); } } writer.WriteLine(string.Empty); }
/// <summary> /// </summary> /// <param name="llvmWriter"> /// </param> /// <param name="method"> /// </param> private static void WriteDelegateInvoke(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; // write access to a field 1 llvmWriter.WriteFieldAccess(writer, opCode, method.DeclaringType, method.DeclaringType.BaseType.BaseType, 0, thisResult); writer.WriteLine(string.Empty); var objectMemberAccessResultNumber = opCode.Result; // load value 1 opCode.Result = null; llvmWriter.WriteLlvmLoad(opCode, objectMemberAccessResultNumber.Type, objectMemberAccessResultNumber); writer.WriteLine(string.Empty); var objectResultNumber = opCode.Result; // write access to a field 2 llvmWriter.WriteFieldAccess(writer, opCode, method.DeclaringType, method.DeclaringType.BaseType.BaseType, 1, thisResult); writer.WriteLine(string.Empty); // additional step to extract value from IntPtr structure llvmWriter.WriteFieldAccess(writer, opCode, opCode.Result.Type, opCode.Result.Type, 0, opCode.Result); writer.WriteLine(string.Empty); // load value 2 var methodMemberAccessResultNumber = opCode.Result; // load value 1 opCode.Result = null; llvmWriter.WriteLlvmLoad(opCode, methodMemberAccessResultNumber.Type, methodMemberAccessResultNumber); writer.WriteLine(string.Empty); var methodResultNumber = opCode.Result; // switch code if method is static var compareResult = llvmWriter.WriteSetResultNumber(opCode, llvmWriter.ResolveType("System.Boolean")); writer.Write("icmp ne "); objectResultNumber.Type.WriteTypePrefix(writer); writer.Write(" "); writer.Write(objectResultNumber); writer.WriteLine(", null"); llvmWriter.WriteCondBranch(writer, compareResult, "normal", "static"); // normal brunch var callResult = llvmWriter.WriteCallInvokeMethod(objectResultNumber, methodResultNumber, method, false); var returnNormal = new OpCodePart(OpCodesEmit.Ret, 0, 0); returnNormal.OpCodeOperands = new[] { OpCodePart.CreateNop }; returnNormal.OpCodeOperands[0].Result = callResult; llvmWriter.WriteReturn(writer, returnNormal, method.ReturnType); writer.WriteLine(string.Empty); // static brunch llvmWriter.WriteLabel(writer, "static"); var callStaticResult = llvmWriter.WriteCallInvokeMethod(objectResultNumber, methodResultNumber, method, true); var returnStatic = new OpCodePart(OpCodesEmit.Ret, 0, 0); returnStatic.OpCodeOperands = new[] { OpCodePart.CreateNop }; returnStatic.OpCodeOperands[0].Result = callStaticResult; llvmWriter.WriteReturn(writer, returnStatic, method.ReturnType); writer.WriteLine(string.Empty); writer.Indent--; writer.WriteLine("}"); }
/// <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.ResolveType("System.Int32")); llvmWriter.WriteLlvmLoad(opCodeNope, llvmWriter.ResolveType("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, llvmWriter.catchScopes.Count > 0 ? llvmWriter.catchScopes.Peek() : null, 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.ResolveType("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)) { if (nextOp != null && nextOp.CatchOrFinallyBegin == null || opCode.Any(Code.Leave, Code.Leave_S) || llvmWriter.OpsByAddressStart.Values.Any(op => op.ToCode() == Code.Ret)) { 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"); } }