Beispiel #1
0
LLGlobalVariable * IrAggr::getInterfaceArraySymbol()
{
    if (classInterfacesArray)
        return classInterfacesArray;

    ClassDeclaration* cd = aggrdecl->isClassDeclaration();

    size_t n = stripModifiers(type)->irtype->isClass()->getNumInterfaceVtbls();
    assert(n > 0 && "getting ClassInfo.interfaces storage symbol, but we "
                    "don't implement any interfaces");

    VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
    LLType* InterfaceTy = DtoType(idx->type->nextOf());

    // create Interface[N]
    LLArrayType* array_type = llvm::ArrayType::get(InterfaceTy,n);

    // put it in a global
    std::string name("_D");
    name.append(cd->mangle());
    name.append("16__interfaceInfosZ");

    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
    classInterfacesArray = getOrCreateGlobal(cd->loc, *gIR->module,
        array_type, true, _linkage, NULL, name);

    return classInterfacesArray;
}
Beispiel #2
0
llvm::GlobalVariable* Module::moduleInfoSymbol()
{
    // create name
    std::string MIname("_D");
    MIname.append(mangle());
    MIname.append("12__ModuleInfoZ");

    if (gIR->dmodule != this) {
        LLType* moduleinfoTy = DtoType(moduleinfo->type);
        LLGlobalVariable *var = gIR->module->getGlobalVariable(MIname);
        if (!var)
            var = new llvm::GlobalVariable(*gIR->module, moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname);
        return var;
    }

    if (moduleInfoVar)
        return moduleInfoVar;

    // declare global
    // flags will be modified at runtime so can't make it constant
    moduleInfoVar = getOrCreateGlobal(loc, *gIR->module, moduleInfoType,
        false, llvm::GlobalValue::ExternalLinkage, NULL, MIname);

    return moduleInfoVar;
}
Beispiel #3
0
static LLConstant* build_offti_array(ClassDeclaration* cd, LLType* arrayT)
{
    IrAggr* iraggr = cd->ir.irAggr;

    size_t nvars = iraggr->varDecls.size();
    std::vector<LLConstant*> arrayInits(nvars);

    for (size_t i=0; i<nvars; i++)
    {
        arrayInits[i] = build_offti_entry(cd, iraggr->varDecls[i]);
    }

    LLConstant* size = DtoConstSize_t(nvars);
    LLConstant* ptr;

    if (nvars == 0)
        return LLConstant::getNullValue( arrayT );

    // array type
    LLArrayType* arrTy = llvm::ArrayType::get(arrayInits[0]->getType(), nvars);
    LLConstant* arrInit = LLConstantArray::get(arrTy, arrayInits);

    // mangle
    std::string name(cd->type->vtinfo->toChars());
    name.append("__OffsetTypeInfos");

    // create symbol
    llvm::GlobalVariable* gvar = getOrCreateGlobal(cd->loc, *gIR->module, arrTy,
                                 true,DtoInternalLinkage(cd),arrInit,name);
    ptr = DtoBitCast(gvar, getPtrToType(arrTy->getElementType()));

    return DtoConstSlice(size, ptr);
}
Beispiel #4
0
// build ModuleReference and register function, to register the module info in the global linked list
static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
{
    // build ctor type
    LLFunctionType* fty = LLFunctionType::get(LLType::getVoidTy(gIR->context()), std::vector<LLType*>(), false);

    // build ctor name
    std::string fname = "_D";
    fname += gIR->dmodule->mangle();
    fname += "16__moduleinfoCtorZ";

    // build a function that registers the moduleinfo in the global moduleinfo linked list
    LLFunction* ctor = LLFunction::Create(fty, LLGlobalValue::InternalLinkage, fname, gIR->module);

    // provide the default initializer
    LLStructType* modulerefTy = DtoModuleReferenceType();
    LLConstant* mrefvalues[] = {
        LLConstant::getNullValue(modulerefTy->getContainedType(0)),
        llvm::ConstantExpr::getBitCast(moduleinfo, modulerefTy->getContainedType(1))
    };
    LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, llvm::ArrayRef<LLConstant*>(mrefvalues));

    // create the ModuleReference node for this module
    std::string thismrefname = "_D";
    thismrefname += gIR->dmodule->mangle();
    thismrefname += "11__moduleRefZ";
    Loc loc;
    LLGlobalVariable* thismref = getOrCreateGlobal(loc, *gIR->module,
        modulerefTy, false, LLGlobalValue::InternalLinkage, thismrefinit,
        thismrefname);
    // make sure _Dmodule_ref is declared
    LLConstant* mref = gIR->module->getNamedGlobal("_Dmodule_ref");
    LLType *modulerefPtrTy = getPtrToType(modulerefTy);
    if (!mref)
        mref = new LLGlobalVariable(*gIR->module, modulerefPtrTy, false, LLGlobalValue::ExternalLinkage, NULL, "_Dmodule_ref");
    mref = DtoBitCast(mref, getPtrToType(modulerefPtrTy));

    // make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list
    llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "moduleinfoCtorEntry", ctor);
    IRBuilder<> builder(bb);

    // debug info
    gIR->DBuilder.EmitSubProgramInternal(fname.c_str(), fname.c_str());

    // get current beginning
    LLValue* curbeg = builder.CreateLoad(mref, "current");

    // put current beginning as the next of this one
    LLValue* gep = builder.CreateStructGEP(thismref, 0, "next");
    builder.CreateStore(curbeg, gep);

    // replace beginning
    builder.CreateStore(thismref, mref);

    // return
    builder.CreateRetVoid();

    return ctor;
}
Beispiel #5
0
LLGlobalVariable * IrAggr::getClassInfoSymbol()
{
    if (classInfo)
        return classInfo;

    // create the initZ symbol
    std::string initname("_D");
    initname.append(aggrdecl->mangle());

    if (aggrdecl->isInterfaceDeclaration())
        initname.append("11__InterfaceZ");
    else
        initname.append("7__ClassZ");

    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);

    ClassDeclaration* cinfo = ClassDeclaration::classinfo;
    DtoType(cinfo->type);
    IrTypeClass* tc = stripModifiers(cinfo->type)->irtype->isClass();
    assert(tc && "invalid ClassInfo type");

    // classinfos cannot be constants since they're used as locks for synchronized
    classInfo = getOrCreateGlobal(aggrdecl->loc,
        *gIR->module, tc->getMemoryLLType(), false, _linkage, NULL, initname);

    // Generate some metadata on this ClassInfo if it's for a class.
    ClassDeclaration* classdecl = aggrdecl->isClassDeclaration();
    if (classdecl && !aggrdecl->isInterfaceDeclaration()) {
        // Gather information
        LLType* type = DtoType(aggrdecl->type);
        LLType* bodyType = llvm::cast<LLPointerType>(type)->getElementType();
        bool hasDestructor = (classdecl->dtor != NULL);
        bool hasCustomDelete = (classdecl->aggDelete != NULL);
        // Construct the fields
        MDNodeField* mdVals[CD_NumFields];
        mdVals[CD_BodyType] = llvm::UndefValue::get(bodyType);
        mdVals[CD_Finalize] = LLConstantInt::get(LLType::getInt1Ty(gIR->context()), hasDestructor);
        mdVals[CD_CustomDelete] = LLConstantInt::get(LLType::getInt1Ty(gIR->context()), hasCustomDelete);
        // Construct the metadata and insert it into the module.
        llvm::SmallString<64> name;
        llvm::NamedMDNode* node = gIR->module->getOrInsertNamedMetadata(
            llvm::Twine(CD_PREFIX, initname).toStringRef(name));
        node->addOperand(llvm::MDNode::get(gIR->context(),
            llvm::makeArrayRef(mdVals, CD_NumFields)));
    }

    return classInfo;
}
Beispiel #6
0
LLGlobalVariable *IrAggr::getInitSymbol() {
  if (init) {
    return init;
  }

  // create the initZ symbol
  auto initname = getMangledInitSymbolName(aggrdecl);

  init =
      getOrCreateGlobal(aggrdecl->loc, gIR->module, getLLStructType(), true,
                        llvm::GlobalValue::ExternalLinkage, nullptr, initname);

  // set alignment
  init->setAlignment(DtoAlignment(type));

  return init;
}
Beispiel #7
0
LLGlobalVariable * IrAggr::getVtblSymbol()
{
    if (vtbl)
        return vtbl;

    // create the initZ symbol
    std::string initname("_D");
    initname.append(aggrdecl->mangle());
    initname.append("6__vtblZ");

    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);

    LLType* vtblTy = stripModifiers(type)->irtype->isClass()->getVtbl();

    vtbl = getOrCreateGlobal(aggrdecl->loc,
        *gIR->module, vtblTy, true, _linkage, NULL, initname);

    return vtbl;
}
Beispiel #8
0
LLGlobalVariable * IrAggr::getInitSymbol()
{
    if (init)
        return init;

    // create the initZ symbol
    std::string initname("_D");
    initname.append(mangle(aggrdecl));
    initname.append("6__initZ");

    init = getOrCreateGlobal(aggrdecl->loc,
        gIR->module, init_type, true, llvm::GlobalValue::ExternalLinkage, NULL, initname);

    // set alignment
    init->setAlignment(type->alignsize());
    StructDeclaration *sd = aggrdecl->isStructDeclaration();
    if (sd && sd->alignment != STRUCTALIGN_DEFAULT)
        init->setAlignment(sd->alignment);

    return init;
}
Beispiel #9
0
llvm::GlobalVariable *getRuntimeGlobal(Loc &loc, llvm::Module &target,
                                       const char *name) {
  LLGlobalVariable *gv = target.getNamedGlobal(name);
  if (gv) {
    return gv;
  }

  checkForImplicitGCCall(loc, name);

  if (!M) {
    initRuntime();
  }

  LLGlobalVariable *g = M->getNamedGlobal(name);
  if (!g) {
    error(loc, "Runtime global '%s' was not found", name);
    fatal();
    // return NULL;
  }

  LLPointerType *t = g->getType();
  return getOrCreateGlobal(loc, target, t->getElementType(), g->isConstant(),
                           g->getLinkage(), nullptr, g->getName());
}
Beispiel #10
0
llvm::GlobalVariable * IrAggr::getInterfaceVtbl(BaseClass * b, bool new_instance, size_t interfaces_index)
{
    ClassGlobalMap::iterator it = interfaceVtblMap.find(b->base);
    if (it != interfaceVtblMap.end())
        return it->second;

    IF_LOG Logger::println("Building vtbl for implementation of interface %s in class %s",
        b->base->toPrettyChars(), aggrdecl->toPrettyChars());
    LOG_SCOPE;

    ClassDeclaration* cd = aggrdecl->isClassDeclaration();
    assert(cd && "not a class aggregate");

    FuncDeclarations vtbl_array;
    b->fillVtbl(cd, &vtbl_array, new_instance);

    std::vector<llvm::Constant*> constants;
    constants.reserve(vtbl_array.dim);

    if (!b->base->isCPPinterface()) { // skip interface info for CPP interfaces
        // start with the interface info
        VarDeclarationIter interfaces_idx(ClassDeclaration::classinfo->fields, 3);

        // index into the interfaces array
        llvm::Constant* idxs[2] = {
            DtoConstSize_t(0),
            DtoConstSize_t(interfaces_index)
        };

        llvm::Constant* c = llvm::ConstantExpr::getGetElementPtr(
            getInterfaceArraySymbol(), idxs, true);

        constants.push_back(c);
    }

    // add virtual function pointers
    size_t n = vtbl_array.dim;
    for (size_t i = b->base->vtblOffset(); i < n; i++)
    {
        Dsymbol* dsym = static_cast<Dsymbol*>(vtbl_array.data[i]);
        if (dsym == NULL)
        {
            // FIXME
            // why is this null?
            // happens for mini/s.d
            constants.push_back(getNullValue(getVoidPtrType()));
            continue;
        }

        FuncDeclaration* fd = dsym->isFuncDeclaration();
        assert(fd && "vtbl entry not a function");

        assert((!fd->isAbstract() || fd->fbody) &&
            "null symbol in interface implementation vtable");

        fd->codegen(Type::sir);
        assert(fd->ir.irFunc && "invalid vtbl function");

        LLFunction *fn = fd->ir.irFunc->func;

        // If the base is a cpp interface, 'this' parameter is a pointer to
        // the interface not the underlying object as expected. Instead of
        // the function, we place into the vtable a small wrapper, called thunk,
        // that casts 'this' to the object and then pass it to the real function.
        if (b->base->isCPPinterface()) {
            TypeFunction *f = (TypeFunction*)fd->type->toBasetype();
            assert(f->fty.arg_this);

            // create the thunk function
            OutBuffer name;
            name.writestring("Th");
            name.printf("%i", b->offset);
            name.writestring(fd->mangle());
            LLFunction *thunk = LLFunction::Create(isaFunction(fn->getType()->getContainedType(0)),
                                                 DtoLinkage(fd), name.toChars(), gIR->module);

            // create entry and end blocks
            llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(gIR->context(), "entry", thunk);
            llvm::BasicBlock* endbb = llvm::BasicBlock::Create(gIR->context(), "endentry", thunk);
            gIR->scopes.push_back(IRScope(beginbb, endbb));

            // copy the function parameters, so later we can pass them to the real function
            std::vector<LLValue*> args;
            llvm::Function::arg_iterator iarg = thunk->arg_begin();
            for (; iarg != thunk->arg_end(); ++iarg)
                args.push_back(iarg);

            // cast 'this' to Object
            LLValue* &thisArg = args[(f->fty.arg_sret == 0) ? 0 : 1];
            LLType* thisType = thisArg->getType();
            thisArg = DtoBitCast(thisArg, getVoidPtrType());
            thisArg = DtoGEP1(thisArg, DtoConstInt(-b->offset));
            thisArg = DtoBitCast(thisArg, thisType);

            // call the real vtbl function.
            LLValue *retVal = gIR->ir->CreateCall(fn, args);

            // return from the thunk
            if (thunk->getReturnType() == LLType::getVoidTy(gIR->context()))
                llvm::ReturnInst::Create(gIR->context(), beginbb);
            else
                llvm::ReturnInst::Create(gIR->context(), retVal, beginbb);

            // clean up
            gIR->scopes.pop_back();
            thunk->getBasicBlockList().pop_back();

            fn = thunk;
        }

        constants.push_back(fn);
    }

    // build the vtbl constant
    llvm::Constant* vtbl_constant = LLConstantStruct::getAnon(gIR->context(), constants, false);

    // create the global variable to hold it
    llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);

    std::string mangle("_D");
    mangle.append(cd->mangle());
    mangle.append("11__interface");
    mangle.append(b->base->mangle());
    mangle.append("6__vtblZ");

    llvm::GlobalVariable* GV = getOrCreateGlobal(cd->loc,
        *gIR->module,
        vtbl_constant->getType(),
        true,
        _linkage,
        vtbl_constant,
        mangle
    );

    // insert into the vtbl map
    interfaceVtblMap.insert(std::make_pair(b->base, GV));

    return GV;
}
Beispiel #11
0
void TryCatchScope::emitCatchBodies(IRState &irs, llvm::Value *ehPtrSlot) {
  assert(catchBlocks.empty());

  auto &PGO = irs.funcGen().pgo;
  const auto entryCount = PGO.setCurrentStmt(stmt);

  struct CBPrototype {
    Type *t;
    llvm::BasicBlock *catchBB;
    uint64_t catchCount;
    uint64_t uncaughtCount;
  };
  llvm::SmallVector<CBPrototype, 8> cbPrototypes;
  cbPrototypes.reserve(stmt->catches->dim);

  for (auto c : *stmt->catches) {
    auto catchBB =
        irs.insertBBBefore(endbb, llvm::Twine("catch.") + c->type->toChars());
    irs.scope() = IRScope(catchBB);
    irs.DBuilder.EmitBlockStart(c->loc);
    PGO.emitCounterIncrement(c);

    bool isCPPclass = false;

    if (auto lp = c->langPlugin()) // CALYPSO
      lp->codegen()->toBeginCatch(irs, c);
    else
    {

    const auto cd = c->type->toBasetype()->isClassHandle();
    isCPPclass = cd->isCPPclass();

    const auto enterCatchFn = getRuntimeFunction(
        Loc(), irs.module,
        isCPPclass ? "__cxa_begin_catch" : "_d_eh_enter_catch");
    const auto ptr = DtoLoad(ehPtrSlot);
    const auto throwableObj = irs.ir->CreateCall(enterCatchFn, ptr);

    // For catches that use the Throwable object, create storage for it.
    // We will set it in the code that branches from the landing pads
    // (there might be more than one) to catchBB.
    if (c->var) {
      // This will alloca if we haven't already and take care of nested refs
      // if there are any.
      DtoDeclarationExp(c->var);

      // Copy the exception reference over from the _d_eh_enter_catch return
      // value.
      DtoStore(DtoBitCast(throwableObj, DtoType(c->var->type)),
               getIrLocal(c->var)->value);
    }
    }

    // Emit handler, if there is one. The handler is zero, for instance,
    // when building 'catch { debug foo(); }' in non-debug mode.
    if (isCPPclass) {
      // from DMD:

      /* C++ catches need to end with call to __cxa_end_catch().
       * Create:
       *   try { handler } finally { __cxa_end_catch(); }
       * Note that this is worst case code because it always sets up an
       * exception handler. At some point should try to do better.
       */
      FuncDeclaration *fdend =
          FuncDeclaration::genCfunc(nullptr, Type::tvoid, "__cxa_end_catch");
      Expression *efunc = VarExp::create(Loc(), fdend);
      Expression *ecall = CallExp::create(Loc(), efunc);
      ecall->type = Type::tvoid;
      Statement *call = ExpStatement::create(Loc(), ecall);
      Statement *stmt =
          c->handler ? TryFinallyStatement::create(Loc(), c->handler, call)
                     : call;
      Statement_toIR(stmt, &irs);
    } else {
      if (c->handler)
        Statement_toIR(c->handler, &irs);
    }

    if (!irs.scopereturned())
    {
      // CALYPSO FIXME: _cxa_end_catch won't be called if it has already returned
      if (auto lp = c->langPlugin())
        lp->codegen()->toEndCatch(irs, c);
      irs.ir->CreateBr(endbb);
    }

    irs.DBuilder.EmitBlockEnd();

    // PGO information, currently unused
    auto catchCount = PGO.getRegionCount(c);
    // uncaughtCount is handled in a separate pass below

    cbPrototypes.push_back({c->type->toBasetype(), catchBB, catchCount, 0}); // CALYPSO
  }

  // Total number of uncaught exceptions is equal to the execution count at
  // the start of the try block minus the one after the continuation.
  // uncaughtCount keeps track of the exception type mismatch count while
  // iterating through the catch block prototypes in reversed order.
  auto uncaughtCount = entryCount - PGO.getRegionCount(stmt);
  for (auto it = cbPrototypes.rbegin(), end = cbPrototypes.rend(); it != end;
       ++it) {
    it->uncaughtCount = uncaughtCount;
    // Add this catch block's match count to the uncaughtCount, because these
    // failed to match the remaining (lexically preceding) catch blocks.
    uncaughtCount += it->catchCount;
  }

  catchBlocks.reserve(stmt->catches->dim);

  auto c_it = stmt->catches->begin(); // CALYPSO
  for (const auto &p : cbPrototypes) {
    auto branchWeights =
        PGO.createProfileWeights(p.catchCount, p.uncaughtCount);
    LLGlobalVariable *ci;
    if (auto lp = (*c_it)->langPlugin()) // CALYPSO
      ci = lp->codegen()->toCatchScopeType(irs, p.t);
    else {
      ClassDeclaration *cd = p.t->isClassHandle();
      DtoResolveClass(cd);
      if (cd->isCPPclass()) {
        const char *name = Target::cppTypeInfoMangle(cd);
        auto cpp_ti = getOrCreateGlobal(
            cd->loc, irs.module, getVoidPtrType(), /*isConstant=*/true,
            LLGlobalValue::ExternalLinkage, /*init=*/nullptr, name);

        // Wrap std::type_info pointers inside a __cpp_type_info_ptr class instance so that
        // the personality routine may differentiate C++ catch clauses from D ones.
        OutBuffer mangleBuf;
        mangleBuf.writestring("_D");
        mangleToBuffer(cd, &mangleBuf);
        mangleBuf.printf("%d%s", 18, "_cpp_type_info_ptr");
        const auto wrapperMangle = getIRMangledVarName(mangleBuf.peekString(), LINKd);

        RTTIBuilder b(ClassDeclaration::cpp_type_info_ptr);
        b.push(cpp_ti);

        auto wrapperType = llvm::cast<llvm::StructType>(
            static_cast<IrTypeClass*>(ClassDeclaration::cpp_type_info_ptr->type->ctype)->getMemoryLLType());
        auto wrapperInit = b.get_constant(wrapperType);

        ci = getOrCreateGlobal(
            cd->loc, irs.module, wrapperType, /*isConstant=*/true,
            LLGlobalValue::LinkOnceODRLinkage, wrapperInit, wrapperMangle);
      } else {
        ci = getIrAggr(cd)->getClassInfoSymbol();
      }
    }
    catchBlocks.push_back({ci, p.catchBB, branchWeights});
    c_it++;
  }
}
Beispiel #12
0
void VarDeclaration::codegen(Ir* p)
{
    Logger::print("VarDeclaration::codegen(): %s | %s\n", toChars(), type->toChars());
    LOG_SCOPE;

    if (type->ty == Terror)
    {   error("had semantic errors when compiling");
        return;
    }

    // just forward aliases
    if (aliassym)
    {
        Logger::println("alias sym");
        toAlias()->codegen(p);
        return;
    }

    // output the parent aggregate first
    if (AggregateDeclaration* ad = isMember())
        ad->codegen(p);

    // global variable
    if (isDataseg() || (storage_class & (STCconst | STCimmutable) && init))
    {
        Logger::println("data segment");

    #if 0 // TODO:
        assert(!(storage_class & STCmanifest) &&
            "manifest constant being codegen'd!");
    #endif

        // don't duplicate work
        if (this->ir.resolved) return;
        this->ir.resolved = true;
        this->ir.declared = true;

        this->ir.irGlobal = new IrGlobal(this);

        Logger::println("parent: %s (%s)", parent->toChars(), parent->kind());

        const bool isLLConst = isConst() && init;
        const llvm::GlobalValue::LinkageTypes llLinkage = DtoLinkage(this);

        assert(!ir.initialized);
        ir.initialized = gIR->dmodule;
        std::string llName(mangle());

        // Since the type of a global must exactly match the type of its
        // initializer, we cannot know the type until after we have emitted the
        // latter (e.g. in case of unions, …). However, it is legal for the
        // initializer to refer to the address of the variable. Thus, we first
        // create a global with the generic type (note the assignment to
        // this->ir.irGlobal->value!), and in case we also do an initializer
        // with a different type later, swap it out and replace any existing
        // uses with bitcasts to the previous type.
        llvm::GlobalVariable* gvar = getOrCreateGlobal(loc, *gIR->module,
            i1ToI8(DtoType(type)), isLLConst, llLinkage, 0, llName,
            isThreadlocal());
        this->ir.irGlobal->value = gvar;

        // Check if we are defining or just declaring the global in this module.
        if (!(storage_class & STCextern) && mustDefineSymbol(this))
        {
            // Build the initializer. Might use this->ir.irGlobal->value!
            LLConstant *initVal = DtoConstInitializer(loc, type, init);

            // In case of type mismatch, swap out the variable.
            if (initVal->getType() != gvar->getType()->getElementType())
            {
                llvm::GlobalVariable* newGvar = getOrCreateGlobal(loc,
                    *gIR->module, initVal->getType(), isLLConst, llLinkage, 0,
                    "", // We take on the name of the old global below.
                    isThreadlocal());

                newGvar->takeName(gvar);

                llvm::Constant* newValue =
                    llvm::ConstantExpr::getBitCast(newGvar, gvar->getType());
                gvar->replaceAllUsesWith(newValue);

                gvar->eraseFromParent();
                gvar = newGvar;
                this->ir.irGlobal->value = newGvar;
            }

            // Now, set the initializer.
            assert(!ir.irGlobal->constInit);
            ir.irGlobal->constInit = initVal;
            gvar->setInitializer(initVal);

            // Also set up the edbug info.
            DtoDwarfGlobalVariable(gvar, this);
        }

        // Set the alignment (it is important not to use type->alignsize because
        // VarDeclarations can have an align() attribute independent of the type
        // as well).
        if (alignment != STRUCTALIGN_DEFAULT)
            gvar->setAlignment(alignment);

        // If this global is used from a naked function, we need to create an
        // artificial "use" for it, or it could be removed by the optimizer if
        // the only reference to it is in inline asm.
        if (nakedUse)
            gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));

        if (Logger::enabled())
            Logger::cout() << *gvar << '\n';
    }
}