Example #1
0
        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");
        }
Example #2
0
        /// <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;
        }
Example #3
0
        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);
            }
        }
Example #5
0
        /// <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;
        }
Example #6
0
        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*/);
        }
Example #7
0
 /// <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;
 }
Example #8
0
        /// <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;
        }
Example #9
0
        /// <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);
        }
Example #10
0
        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*/);
        }
Example #11
0
        /// <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);
        }
Example #12
0
        /// <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*/);
        }
Example #13
0
        /// <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);
            }
        }
Example #14
0
        /// <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);
        }
Example #15
0
        /// <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");
        }
Example #17
0
        /// <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);
        }
Example #18
0
        /// <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);
            }
        }
Example #19
0
        /// <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(")");
        }
Example #20
0
        /// <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;
        }
Example #21
0
        /// <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();
        }
Example #22
0
        /// <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;
        }
Example #23
0
        /// <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*");
        }
Example #24
0
        /// <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);
        }
Example #25
0
        /// <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");
        }
Example #26
0
 /// <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;
 }
Example #27
0
        /// <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);
        }
Example #28
0
        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");
        }
Example #29
0
        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);
            }
        }
Example #30
0
        /// <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();
        }
Example #32
0
        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);
        }
Example #33
0
        /// <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*");
        }
Example #34
0
        /// <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");
            }
        }
Example #35
0
        /// <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);
        }
Example #36
0
        /// <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);
        }
Example #37
0
        /// <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*");
        }
Example #38
0
        /// <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);
            }
        }
Example #39
0
        /// <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);
        }
Example #40
0
        /// <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);
            }
        }
Example #41
0
        /// <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;
        }
Example #42
0
        /// <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);
        }
Example #43
0
        /// <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);
        }
Example #44
0
        /// <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(")");
        }
Example #45
0
        /// <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");
            }
        }
Example #47
0
        /// <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*/);
        }
Example #48
0
        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*/);
        }
Example #49
0
        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*/);
        }