[IR] Add method to GlobalVariable to change type of initializer. (#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.
This commit is contained in:
Eli Friedman 2024-08-09 09:22:40 -07:00 committed by GitHub
parent 5c016bf40e
commit 2f8f58dd17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 15 additions and 29 deletions

View File

@ -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);

View File

@ -147,10 +147,16 @@ public:
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.

View File

@ -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) {