Skip to content

[IR] Add method to GlobalVariable to change type of initializer. #102553

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading