private void GenerateFunctionHeader(AstFuncExpr function, bool forceEmitCode)
        {
            // Don't emit global functions that aren't even used
            if (!forceEmitCode && dontEmitUnusedDeclarations && !function.IsUsed)
            {
                return;
            }

            if (function.IsMacroFunction)
            {
                return;
            }

            var name = "";

            if (function.ImplBlock != null)
            {
                name += function.ImplBlock.TargetType + ".";
                if (function.ImplBlock.Trait != null)
                {
                    name += function.ImplBlock.Trait + ".";
                }
            }

            name += function.Name;

            if (function.PolymorphicTypes != null && function.PolymorphicTypes.Count > 0)
            {
                name += "." + string.Join(".", function.PolymorphicTypes.Select(p => $"{p.Key}.{p.Value}"));
            }
            if (function.ConstParameters != null && function.ConstParameters.Count > 0)
            {
                name += "." + string.Join(".", function.ConstParameters.Select(p => $"{p.Key}.{p.Value.type}.{p.Value.value}"));
            }

            if (function.Body != null)
            {
                name += ".che";
            }

            var linkname = function.GetDirective("linkname");

            LLVMValueRef lfunc = new LLVMValueRef();

            if (linkname != null)
            {
                name = linkname.Arguments[0].Value as string;

                lfunc = module.GetNamedFunction(name);
            }

            LLVMTypeRef ltype = FuncTypeToLLVMType(function.FunctionType);

            if (lfunc.Pointer.ToInt64() == 0)
            {
                lfunc = module.AddFunction(name, ltype);
            }

            // :temporary
            if (function.Body != null)
            {
                lfunc.SetLinkage(LLVMLinkage.LLVMInternalLinkage);
            }

            if (function.HasDirective("extern"))
            {
                lfunc.SetLinkage(LLVMLinkage.LLVMExternalLinkage);
            }

            // TODO

            if (function.HasDirective("noinline"))
            {
                lfunc.AddFunctionAttribute(context, LLVMAttributeKind.NoInline);
            }
            lfunc.AddFunctionAttribute(context, LLVMAttributeKind.NoUnwind);

            var ccDir = function.GetDirective("stdcall");

            if (ccDir != null)
            {
                LLVM.SetFunctionCallConv(lfunc, (int)LLVMCallConv.LLVMX86StdcallCallConv);
            }

            valueMap[function] = lfunc;
        }