/// <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); }
/// <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); }
/// <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); }
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); }