Esempio n. 1
0
        public LLVMValueRef BuildCast(LLVMBuilderRef builder, LLVMValueRef elem, LLVMTypeRef targetType)
        {
            // Check if the type of the element equals the targe type
            if (CompareType(elem, targetType))
            {
                // There is no need to cast
                // Just return the element
                return(elem);
            }

            // Strings need special handling
            if (CompareType(targetType, StringType))
            {
                LLVMValueRef indices;
                var          gep = LLVM.BuildGEP(builder, elem, out indices, 0u, "tmpgep");
                var          ptr = LLVM.BuildPointerCast(builder, gep, StringType, "tmpptrcast");
                return(ptr);
            }

            string strtype1, strtype2;

            switch (targetType.TypeKind)
            {
            case LLVMTypeKind.LLVMIntegerTypeKind:

                // Check if the integer fits
                if (IsInteger(elem))
                {
                    var lwidth = elem.TypeOf().GetIntTypeWidth();
                    var rwidth = targetType.GetIntTypeWidth();
                    if (lwidth > rwidth)
                    {
                        // The width of the result type is higher
                        // than the width of the element type
                        // Throw an exception
                        strtype1 = elem.TypeOf().PrintTypeToString();
                        strtype2 = targetType.PrintTypeToString();
                        throw LoreException.Create(Visitor.Location)
                              .Describe($"Unable to cast element of type '{strtype1}' to '{strtype2}':")
                              .Describe($"The element is too big for the target integer type.");
                    }
                }

                // Perform a float to signed integer cast if needed
                else if (IsFloatOrDouble(elem))
                {
                    elem = LLVM.BuildFPToSI(builder, elem, targetType, "tmpfptosicast");
                }

                // Unsupported element type
                else
                {
                    // Unable to perform a meaningful cast
                    strtype1 = elem.TypeOf().PrintTypeToString();
                    strtype2 = targetType.PrintTypeToString();
                    throw LoreException.Create(Visitor.Location).Describe($"Unable to cast element of type '{strtype1}' to '{strtype2}':");
                }

                // Perform an integer cast
                return(LLVM.BuildIntCast(builder, elem, targetType, "tmpcast"));

            case LLVMTypeKind.LLVMFloatTypeKind:
            case LLVMTypeKind.LLVMDoubleTypeKind:

                // Perform a signed integer to float cast if needed
                if (IsInteger(elem))
                {
                    elem = LLVM.BuildSIToFP(builder, elem, targetType, "tmpsitofpcast");
                }
                return(LLVM.BuildFPCast(builder, elem, targetType, "tmpfcast"));
            }

            // Unable to perform a meaningful cast
            strtype1 = elem.TypeOf().PrintTypeToString();
            strtype2 = targetType.PrintTypeToString();
            throw LoreException.Create(Visitor.Location).Describe($"Unable to cast element of type '{strtype1}' to '{strtype2}':");
        }