private void InitGlobalVariable(AstVariableDecl decl, HashSet <AstVariableDecl> visited)
        {
            if (visited.Contains(decl))
            {
                return;
            }

            if (decl.Dependencies != null)
            {
                foreach (var dep in decl.Dependencies)
                {
                    if (dep is AstVariableDecl v)
                    {
                        InitGlobalVariable(v, visited);
                    }
                }
            }
            visited.Add(decl);

            // Don't emit global variables that aren't even used
            if (dontEmitUnusedDeclarations && !decl.IsUsed)
            {
                return;
            }

            // create vars
            var type = CheezTypeToLLVMType(decl.Type);

            var name = decl.Name.Name;

            if (decl.TryGetDirective("linkname", out var linkname))
            {
                name = linkname.Arguments[0].Value as string;
            }


            var varPtr = module.AddGlobal(type, name);

            varPtr.SetLinkage(LLVMLinkage.LLVMInternalLinkage);
            if (decl.HasDirective("thread_local"))
            {
                varPtr.SetThreadLocal(true);
            }
            //varPtr.SetLinkage(LLVMLinkage.LLVMExternalLinkage);// TODO?

            if (decl.HasDirective("extern"))
            {
                varPtr.SetLinkage(LLVMLinkage.LLVMExternalLinkage);
            }
            else
            {
                LLVMValueRef initializer = LLVM.ConstNull(CheezTypeToLLVMType(decl.Type));
                varPtr.SetInitializer(initializer);
            }

            valueMap[decl] = varPtr;

            // do initialization TODO: other patterns
            if (decl.Initializer != null)
            {
                var x = GenerateExpression(decl.Initializer, true);
                builder.CreateStore(x, varPtr);
            }
        }