Skip to content

Commit

Permalink
[IR] Add method to GlobalVariable to change type of initializer. (llv…
Browse files Browse the repository at this point in the history
…m#102553)

With opaque pointers, nothing directly uses the value type, so we can
mutate it if we want. This avoid doing a complicated RAUW dance.
  • Loading branch information
efriedma-quic authored and bwendling committed Aug 15, 2024
1 parent e52f8ba commit 0449d83
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 29 deletions.
28 changes: 1 addition & 27 deletions clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,38 +370,12 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
assert(VarSize == CstSize && "Emitted constant has unexpected size");
#endif

// The initializer may differ in type from the global. Rewrite
// the global to match the initializer. (We have to do this
// because some types, like unions, can't be completely represented
// in the LLVM type system.)
if (GV->getValueType() != Init->getType()) {
llvm::GlobalVariable *OldGV = GV;

GV = new llvm::GlobalVariable(
CGM.getModule(), Init->getType(), OldGV->isConstant(),
OldGV->getLinkage(), Init, "",
/*InsertBefore*/ OldGV, OldGV->getThreadLocalMode(),
OldGV->getType()->getPointerAddressSpace());
GV->setVisibility(OldGV->getVisibility());
GV->setDSOLocal(OldGV->isDSOLocal());
GV->setComdat(OldGV->getComdat());

// Steal the name of the old global
GV->takeName(OldGV);

// Replace all uses of the old global with the new global
OldGV->replaceAllUsesWith(GV);

// Erase the old global, since it is no longer used.
OldGV->eraseFromParent();
}

bool NeedsDtor =
D.needsDestruction(getContext()) == QualType::DK_cxx_destructor;

GV->setConstant(
D.getType().isConstantStorage(getContext(), true, !NeedsDtor));
GV->setInitializer(Init);
GV->replaceInitializer(Init);

emitter.finalize(GV);

Expand Down
10 changes: 8 additions & 2 deletions llvm/include/llvm/IR/GlobalVariable.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,16 @@ class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
return static_cast<Constant*>(Op<0>().get());
}
/// setInitializer - Sets the initializer for this global variable, removing
/// any existing initializer if InitVal==NULL. If this GV has type T*, the
/// initializer must have type T.
/// any existing initializer if InitVal==NULL. The initializer must have the
/// type getValueType().
void setInitializer(Constant *InitVal);

/// replaceInitializer - Sets the initializer for this global variable, and
/// sets the value type of the global to the type of the initializer. The
/// initializer must not be null. This may affect the global's alignment if
/// it isn't explicitly set.
void replaceInitializer(Constant *InitVal);

/// If the value is a global constant, its value is immutable throughout the
/// runtime execution of the program. Assigning a value into the constant
/// leads to undefined behavior.
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/IR/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,12 @@ void GlobalVariable::setInitializer(Constant *InitVal) {
}
}

void GlobalVariable::replaceInitializer(Constant *InitVal) {
assert(InitVal && "Can't compute type of null initializer");
ValueType = InitVal->getType();
setInitializer(InitVal);
}

/// Copy all additional attributes (those not needed to create a GlobalVariable)
/// from the GlobalVariable Src to this one.
void GlobalVariable::copyAttributesFrom(const GlobalVariable *Src) {
Expand Down

0 comments on commit 0449d83

Please sign in to comment.