Skip to content

Commit 2f8f58d

Browse files
[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.
1 parent 5c016bf commit 2f8f58d

File tree

3 files changed

+15
-29
lines changed

3 files changed

+15
-29
lines changed

clang/lib/CodeGen/CGDecl.cpp

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -370,38 +370,12 @@ CodeGenFunction::AddInitializerToStaticVarDecl(const VarDecl &D,
370370
assert(VarSize == CstSize && "Emitted constant has unexpected size");
371371
#endif
372372

373-
// The initializer may differ in type from the global. Rewrite
374-
// the global to match the initializer. (We have to do this
375-
// because some types, like unions, can't be completely represented
376-
// in the LLVM type system.)
377-
if (GV->getValueType() != Init->getType()) {
378-
llvm::GlobalVariable *OldGV = GV;
379-
380-
GV = new llvm::GlobalVariable(
381-
CGM.getModule(), Init->getType(), OldGV->isConstant(),
382-
OldGV->getLinkage(), Init, "",
383-
/*InsertBefore*/ OldGV, OldGV->getThreadLocalMode(),
384-
OldGV->getType()->getPointerAddressSpace());
385-
GV->setVisibility(OldGV->getVisibility());
386-
GV->setDSOLocal(OldGV->isDSOLocal());
387-
GV->setComdat(OldGV->getComdat());
388-
389-
// Steal the name of the old global
390-
GV->takeName(OldGV);
391-
392-
// Replace all uses of the old global with the new global
393-
OldGV->replaceAllUsesWith(GV);
394-
395-
// Erase the old global, since it is no longer used.
396-
OldGV->eraseFromParent();
397-
}
398-
399373
bool NeedsDtor =
400374
D.needsDestruction(getContext()) == QualType::DK_cxx_destructor;
401375

402376
GV->setConstant(
403377
D.getType().isConstantStorage(getContext(), true, !NeedsDtor));
404-
GV->setInitializer(Init);
378+
GV->replaceInitializer(Init);
405379

406380
emitter.finalize(GV);
407381

llvm/include/llvm/IR/GlobalVariable.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,16 @@ class GlobalVariable : public GlobalObject, public ilist_node<GlobalVariable> {
147147
return static_cast<Constant*>(Op<0>().get());
148148
}
149149
/// setInitializer - Sets the initializer for this global variable, removing
150-
/// any existing initializer if InitVal==NULL. If this GV has type T*, the
151-
/// initializer must have type T.
150+
/// any existing initializer if InitVal==NULL. The initializer must have the
151+
/// type getValueType().
152152
void setInitializer(Constant *InitVal);
153153

154+
/// replaceInitializer - Sets the initializer for this global variable, and
155+
/// sets the value type of the global to the type of the initializer. The
156+
/// initializer must not be null. This may affect the global's alignment if
157+
/// it isn't explicitly set.
158+
void replaceInitializer(Constant *InitVal);
159+
154160
/// If the value is a global constant, its value is immutable throughout the
155161
/// runtime execution of the program. Assigning a value into the constant
156162
/// leads to undefined behavior.

llvm/lib/IR/Globals.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,12 @@ void GlobalVariable::setInitializer(Constant *InitVal) {
503503
}
504504
}
505505

506+
void GlobalVariable::replaceInitializer(Constant *InitVal) {
507+
assert(InitVal && "Can't compute type of null initializer");
508+
ValueType = InitVal->getType();
509+
setInitializer(InitVal);
510+
}
511+
506512
/// Copy all additional attributes (those not needed to create a GlobalVariable)
507513
/// from the GlobalVariable Src to this one.
508514
void GlobalVariable::copyAttributesFrom(const GlobalVariable *Src) {

0 commit comments

Comments
 (0)