示例#1
0
        /// <summary>
        /// Declares the function type for the given method in the given module.
        /// </summary>
        /// <param name="Method">The method to find a function type for.</param>
        /// <param name="Module">The module that declares the function.</param>
        /// <returns>A function type.</returns>
        public LLVMTypeRef DeclarePrototype(IMethod Method)
        {
            LLVMTypeRef result;

            if (!declaredPrototypes.TryGetValue(Method, out result))
            {
                var abi            = LLVMSymbolTypeMember.GetLLVMAbi(Method, assembly);
                var paramArr       = Method.GetParameters();
                int thisParamCount = Method.IsStatic ? 0 : 1;
                var extParamTypes  = new LLVMTypeRef[paramArr.Length > 0 ? thisParamCount + paramArr.Length : 1];
                if (!Method.IsStatic)
                {
                    extParamTypes[0] = PointerType(Int8Type(), 0);
                }
                for (int i = 0; i < paramArr.Length; i++)
                {
                    extParamTypes[i + thisParamCount] = Declare(paramArr[i].ParameterType);
                }
                result = FunctionType(
                    Declare(Method.ReturnType),
                    out extParamTypes[0],
                    (uint)(paramArr.Length + thisParamCount),
                    false);
                declaredPrototypes[Method] = result;
            }
            return(result);
        }
示例#2
0
        /// <summary>
        /// Declares the given method if it was not declared already.
        /// A value that corresponds to the declaration is returned.
        /// </summary>
        /// <param name="Method">The method to declare.</param>
        /// <returns>An LLVM function.</returns>
        public LLVMValueRef Declare(IMethod Method)
        {
            LLVMValueRef result;

            if (!declaredMethods.TryGetValue(Method, out result))
            {
                if (!TryDeclareIntrinsic(Method, out result))
                {
                    var    abi        = LLVMSymbolTypeMember.GetLLVMAbi(Method, assembly);
                    string methodName = abi.Mangler.Mangle(Method, true);
                    result = GetNamedFunction(module, methodName);
                    if (result.Pointer == IntPtr.Zero ||
                        !Method.HasAttribute(
                            PrimitiveAttributes.Instance.ImportAttribute.AttributeType))
                    {
                        // Only declare imported methods if they haven't been declared
                        // already.
                        //
                        // It's tempting to think that a valid assembly declares
                        // methods only once, but it's not true: sometimes, the same
                        // function is imported multiple times by different classes.
                        var funcType = DeclarePrototype(Method);
                        result = AddFunction(module, methodName, funcType);
                        result.SetUnnamedAddr(true);

                        AddParameterAttributes(result, Method);

                        if (Method.HasAttribute(NoAliasAttribute.AttributeType))
                        {
                            AddAttributeAtIndex(
                                result,
                                LLVMAttributeIndex.LLVMAttributeReturnIndex,
                                CreateEnumAttribute("noalias"));
                        }
                        if (Method.HasAttribute(NoThrowAttribute.AttributeType))
                        {
                            AddAttributeAtIndex(
                                result,
                                LLVMAttributeIndex.LLVMAttributeFunctionIndex,
                                CreateEnumAttribute("nounwind"));
                        }
                        if (Method.HasAttribute(ReadNoneAttribute.AttributeType))
                        {
                            AddAttributeAtIndex(
                                result,
                                LLVMAttributeIndex.LLVMAttributeFunctionIndex,
                                CreateEnumAttribute("readnone"));
                        }
                    }
                }
                declaredMethods[Method] = result;
            }
            return(result);
        }
示例#3
0
        /// <summary>
        /// Declares the given field if it is static and has not been declared
        /// already. An LLVM value that corresponds to the declaration is returned.
        /// </summary>
        /// <param name="Field">The field to declare.</param>
        /// <returns>An LLVM global.</returns>
        public LLVMValueRef DeclareGlobal(IField Field)
        {
            if (!Field.IsStatic)
            {
                throw new InvalidOperationException(
                          "Instance field '" + Field.Name +
                          "' cannot be declared as a global.");
            }

            LLVMValueRef result;

            if (!declaredGlobals.TryGetValue(Field, out result))
            {
                // Declare the global.
                var abiMangler = LLVMSymbolTypeMember.GetLLVMAbi(Field, assembly).Mangler;
                result = DeclareGlobal(Declare(Field.FieldType), abiMangler.Mangle(Field, true));

                if (Field is LLVMField)
                {
                    var llvmField = (LLVMField)Field;

                    // Set the field's linkage.
                    result.SetLinkage(llvmField.Linkage);

                    if (!llvmField.IsImport)
                    {
                        // Zero-initialize it.
                        var codeGenerator     = new Codegen.LLVMCodeGenerator(null);
                        var defaultValueBlock = (Codegen.CodeBlock)codeGenerator.EmitDefaultValue(Field.FieldType);
                        var defaultValueRef   = defaultValueBlock.Emit(
                            new Codegen.BasicBlockBuilder(
                                new Codegen.FunctionBodyBuilder(this, default(LLVMValueRef)),
                                default(LLVMBasicBlockRef)));
                        LLVMSharp.LLVM.SetInitializer(result, defaultValueRef.Value);
                    }
                }

                // Store it in the dictionary.
                declaredGlobals[Field] = result;
            }
            return(result);
        }
示例#4
0
        private LLVMValueRef DeclareArrayLength(IMethod Method)
        {
            var arrayType = Method.DeclaringType.AsArrayType();

            // Declare T[,...].Length.
            var abi      = LLVMSymbolTypeMember.GetLLVMAbi(Method, assembly);
            var funcType = DeclarePrototype(Method);
            var funcDef  = AddFunction(module, abi.Mangler.Mangle(Method, true), funcType);

            funcDef.SetLinkage(LLVMLinkage.LLVMWeakODRLinkage);
            AddAttributeAtIndex(
                funcDef,
                LLVMAttributeIndex.LLVMAttributeFunctionIndex,
                CreateEnumAttribute("nounwind"));

            // Define T[,...].Length's body.
            var codeGenerator = new Codegen.LLVMCodeGenerator(Method);

            // T[,...].Length computes the product of all dimensions.
            var dimensions = new ICodeBlock[arrayType.ArrayRank];

            for (int i = 0; i < dimensions.Length; i++)
            {
                dimensions[i] = codeGenerator.EmitDereferencePointer(
                    new Codegen.GetDimensionPtrBlock(
                        codeGenerator,
                        (Codegen.CodeBlock)codeGenerator.GetThis().EmitGet(),
                        i));
            }

            var body = (Codegen.CodeBlock)codeGenerator.EmitReturn(codeGenerator.EmitProduct(dimensions));

            // Emit T[,...].Length's body.
            var bodyBuilder       = new Codegen.FunctionBodyBuilder(this, funcDef);
            var entryPointBuilder = bodyBuilder.AppendBasicBlock("entry");

            entryPointBuilder = codeGenerator.Prologue.Emit(entryPointBuilder);
            body.Emit(entryPointBuilder);

            return(funcDef);
        }