Implement review feedback. Aliasees can be either GlobalValue's or

bitcasts of them.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36537 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anton Korobeynikov
2007-04-28 13:45:00 +00:00
parent 44b2c5098f
commit a80e1181b7
20 changed files with 231 additions and 113 deletions

View File

@ -1212,14 +1212,18 @@ the first <a href="#uint32_vbr">uint32_vbr</a> which describes alias itself.</p>
linkage, 2 - Weak linkage.</td> linkage, 2 - Weak linkage.</td>
</tr> </tr>
<tr> <tr>
<td><a href="#bit">bit(2-31)</a></td> <td><a href="#bit">bit(2)</a></td>
<td class="td_left">0 - Aliasee is global value. 1 - Aliasee is constant
expression (bitcast of global value)</td>
</tr>
<tr>
<td><a href="#bit">bit(3-31)</a></td>
<td class="td_left">Type slot number of type for the alias itself.</td> <td class="td_left">Type slot number of type for the alias itself.</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<p>The next two <a href="#uint32_vbr">uint32_vbr's</a> describes the <p>The next <a href="#uint32_vbr">uint32_vbr</a> describes the aliasee. </p>
aliasee. </p>
<table> <table>
<tbody> <tbody>
@ -1227,10 +1231,6 @@ the first <a href="#uint32_vbr">uint32_vbr</a> which describes alias itself.</p>
<th><b>Type</b></th> <th><b>Type</b></th>
<th class="td_left"><b>Description</b></th> <th class="td_left"><b>Description</b></th>
</tr> </tr>
<tr>
<td><a href="#uint32_vbr">uint32_vbr</a></td>
<td class="td_left">Type slot number of type for the aliasee.</td>
</tr>
<tr> <tr>
<td><a href="#uint32_vbr">uint32_vbr</a></td> <td><a href="#uint32_vbr">uint32_vbr</a></td>
<td class="td_left">Slot number of the aliasee.</td> <td class="td_left">Slot number of the aliasee.</td>

View File

@ -24,6 +24,7 @@
<li><a href="#callingconv">Calling Conventions</a></li> <li><a href="#callingconv">Calling Conventions</a></li>
<li><a href="#globalvars">Global Variables</a></li> <li><a href="#globalvars">Global Variables</a></li>
<li><a href="#functionstructure">Functions</a></li> <li><a href="#functionstructure">Functions</a></li>
<li><a href="aliasstructure">Aliases</a>
<li><a href="#paramattrs">Parameter Attributes</a></li> <li><a href="#paramattrs">Parameter Attributes</a></li>
<li><a href="#moduleasm">Module-Level Inline Assembly</a></li> <li><a href="#moduleasm">Module-Level Inline Assembly</a></li>
<li><a href="#datalayout">Data Layout</a></li> <li><a href="#datalayout">Data Layout</a></li>
@ -705,7 +706,7 @@ a power of 2.</p>
</div> </div>
<div class="doc_text"> <div class="doc_text">
<p>Aliases act as "second name" for the aliasee value (which can be either <p>Aliases act as "second name" for the aliasee value (which can be either
function or global variable). Aliases may have an function or global variable or bitcast of global value). Aliases may have an
optional <a href="#linkage">linkage type</a>, and an optional <a href="#linkage">linkage type</a>, and an
optional <a href="#visibility">visibility style</a>.</p> optional <a href="#visibility">visibility style</a>.</p>

View File

@ -116,6 +116,12 @@ public:
bool isThreadLocal ///< Whether the GV is thread local or not bool isThreadLocal ///< Whether the GV is thread local or not
) {} ) {}
virtual void handleGlobalAlias(
const Type* ElemType,
GlobalValue::LinkageTypes Linkage,
unsigned TypeSlotNum,
unsigned AliaseeSlot) { }
/// This method is called when a type list is recognized. It simply /// This method is called when a type list is recognized. It simply
/// provides the number of types that the list contains. The handler /// provides the number of types that the list contains. The handler
/// should expect that number of calls to handleType. /// should expect that number of calls to handleType.

View File

@ -81,6 +81,15 @@ private:
void setNext(Function *N) { Next = N; } void setNext(Function *N) { Next = N; }
void setPrev(Function *N) { Prev = N; } void setPrev(Function *N) { Prev = N; }
// getNext/Prev - Return the next or previous function in the list. These
// methods should never be used directly, and are only used to implement the
// function list as part of the module.
//
Function *getNext() { return Next; }
const Function *getNext() const { return Next; }
Function *getPrev() { return Prev; }
const Function *getPrev() const { return Prev; }
public: public:
/// Function ctor - If the (optional) Module argument is specified, the /// Function ctor - If the (optional) Module argument is specified, the
/// function is automatically inserted into the end of the function list for /// function is automatically inserted into the end of the function list for
@ -243,15 +252,6 @@ public:
Function *Obj = 0; Function *Obj = 0;
return unsigned(reinterpret_cast<uintptr_t>(&Obj->ArgumentList)); return unsigned(reinterpret_cast<uintptr_t>(&Obj->ArgumentList));
} }
private:
// getNext/Prev - Return the next or previous function in the list. These
// methods should never be used directly, and are only used to implement the
// function list as part of the module.
//
Function *getNext() { return Next; }
const Function *getNext() const { return Next; }
Function *getPrev() { return Prev; }
const Function *getPrev() const { return Prev; }
}; };
inline ValueSymbolTable * inline ValueSymbolTable *

View File

@ -1,4 +1,4 @@
//===______-- llvm/GlobalAlias.h - GlobalAlias class ------------*- C++ -*-===// //===-------- llvm/GlobalAlias.h - GlobalAlias class ------------*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// This file contains the declaration of the GlobalAlias class, which // This file contains the declaration of the GlobalAlias class, which
// represents a single function or variable alias in the VM. // represents a single function or variable alias in the IR.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -36,13 +36,18 @@ class GlobalAlias : public GlobalValue {
void setNext(GlobalAlias *N) { Next = N; } void setNext(GlobalAlias *N) { Next = N; }
void setPrev(GlobalAlias *N) { Prev = N; } void setPrev(GlobalAlias *N) { Prev = N; }
const GlobalValue* Aliasee; // getNext/Prev - Return the next or previous alias in the list.
std::string Target; GlobalAlias *getNext() { return Next; }
const GlobalAlias *getNext() const { return Next; }
GlobalAlias *getPrev() { return Prev; }
const GlobalAlias *getPrev() const { return Prev; }
Use Aliasee;
public: public:
/// GlobalAlias ctor - If a parent module is specified, the alias is /// GlobalAlias ctor - If a parent module is specified, the alias is
/// automatically inserted into the end of the specified modules alias list. /// automatically inserted into the end of the specified module's alias list.
GlobalAlias(const Type *Ty, LinkageTypes Linkage, const std::string &Name = "", GlobalAlias(const Type *Ty, LinkageTypes Linkage, const std::string &Name = "",
const GlobalValue* Aliasee = 0, Module *Parent = 0); Constant* Aliasee = 0, Module *Parent = 0);
/// isDeclaration - Is this global variable lacking an initializer? If so, /// isDeclaration - Is this global variable lacking an initializer? If so,
/// the global variable is defined in some other translation unit, and is thus /// the global variable is defined in some other translation unit, and is thus
@ -52,30 +57,30 @@ public:
/// removeFromParent - This method unlinks 'this' from the containing module, /// removeFromParent - This method unlinks 'this' from the containing module,
/// but does not delete it. /// but does not delete it.
/// ///
virtual void removeFromParent(); void removeFromParent();
/// eraseFromParent - This method unlinks 'this' from the containing module /// eraseFromParent - This method unlinks 'this' from the containing module
/// and deletes it. /// and deletes it.
/// ///
virtual void eraseFromParent(); void eraseFromParent();
virtual void print(std::ostream &OS) const; virtual void print(std::ostream &OS) const;
void print(std::ostream *OS) const { if (OS) print(*OS); } void print(std::ostream *OS) const { if (OS) print(*OS); }
void setAliasee(const GlobalValue* GV); /// set/getAliasee - These methods retrive and set alias target.
const GlobalValue* getAliasee() const { return Aliasee; } void setAliasee(Constant* GV);
const Constant* getAliasee() const {
return cast_or_null<Constant>(getOperand(0));
}
Constant* getAliasee() {
return cast_or_null<Constant>(getOperand(0));
}
// Methods for support type inquiry through isa, cast, and dyn_cast: // Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const GlobalAlias *) { return true; } static inline bool classof(const GlobalAlias *) { return true; }
static inline bool classof(const Value *V) { static inline bool classof(const Value *V) {
return V->getValueID() == Value::GlobalAliasVal; return V->getValueID() == Value::GlobalAliasVal;
} }
private:
// getNext/Prev - Return the next or previous alias in the list.
GlobalAlias *getNext() { return Next; }
const GlobalAlias *getNext() const { return Next; }
GlobalAlias *getPrev() { return Prev; }
const GlobalAlias *getPrev() const { return Prev; }
}; };
} // End llvm namespace } // End llvm namespace

View File

@ -121,16 +121,6 @@ public:
/// value is outside of the current translation unit... /// value is outside of the current translation unit...
virtual bool isDeclaration() const = 0; virtual bool isDeclaration() const = 0;
/// removeFromParent - This method unlinks 'this' from the containing module,
/// but does not delete it.
///
virtual void removeFromParent() = 0;
/// eraseFromParent - This method unlinks 'this' from the containing module
/// and deletes it.
///
virtual void eraseFromParent() = 0;
/// getParent - Get the module that this global value is contained inside /// getParent - Get the module that this global value is contained inside
/// of... /// of...
inline Module *getParent() { return Parent; } inline Module *getParent() { return Parent; }

View File

@ -107,12 +107,12 @@ public:
/// removeFromParent - This method unlinks 'this' from the containing module, /// removeFromParent - This method unlinks 'this' from the containing module,
/// but does not delete it. /// but does not delete it.
/// ///
virtual void removeFromParent(); void removeFromParent();
/// eraseFromParent - This method unlinks 'this' from the containing module /// eraseFromParent - This method unlinks 'this' from the containing module
/// and deletes it. /// and deletes it.
/// ///
virtual void eraseFromParent(); void eraseFromParent();
/// Override Constant's implementation of this method so we can /// Override Constant's implementation of this method so we can
/// replace constant initializers. /// replace constant initializers.

View File

@ -480,8 +480,24 @@ static Value *getVal(const Type *Ty, const ValID &ID) {
// or an id number that hasn't been read yet. We may be referencing something // or an id number that hasn't been read yet. We may be referencing something
// forward, so just create an entry to be resolved later and get to it... // forward, so just create an entry to be resolved later and get to it...
// //
V = new Argument(Ty); switch (ID.Type) {
case ValID::GlobalName:
case ValID::GlobalID:
const PointerType *PTy = dyn_cast<PointerType>(Ty);
if (!PTy) {
GenerateError("Invalid type for reference to global" );
return 0;
}
const Type* ElTy = PTy->getElementType();
if (const FunctionType *FTy = dyn_cast<FunctionType>(ElTy))
V = new Function(FTy, GlobalValue::ExternalLinkage);
else
V = new GlobalVariable(ElTy, false, GlobalValue::ExternalLinkage);
break;
default:
V = new Argument(Ty);
}
// Remember where this forward reference came from. FIXME, shouldn't we try // Remember where this forward reference came from. FIXME, shouldn't we try
// to recycle these things?? // to recycle these things??
CurModule.PlaceHolderInfo.insert(std::make_pair(V, std::make_pair(ID, CurModule.PlaceHolderInfo.insert(std::make_pair(V, std::make_pair(ID,
@ -987,7 +1003,7 @@ Module *llvm::RunVMAsmParser(const char * AsmString, Module * M) {
%type <BasicBlockVal> BasicBlock InstructionList %type <BasicBlockVal> BasicBlock InstructionList
%type <TermInstVal> BBTerminatorInst %type <TermInstVal> BBTerminatorInst
%type <InstVal> Inst InstVal MemoryInst %type <InstVal> Inst InstVal MemoryInst
%type <ConstVal> ConstVal ConstExpr %type <ConstVal> ConstVal ConstExpr AliaseeRef
%type <ConstVector> ConstVector %type <ConstVector> ConstVector
%type <ArgList> ArgList ArgListH %type <ArgList> ArgList ArgListH
%type <PHIList> PHIList %type <PHIList> PHIList
@ -1943,6 +1959,30 @@ GlobalType : GLOBAL { $$ = false; } | CONSTANT { $$ = true; };
// ThreadLocal // ThreadLocal
ThreadLocal : THREAD_LOCAL { $$ = true; } | { $$ = false; }; ThreadLocal : THREAD_LOCAL { $$ = true; } | { $$ = false; };
// AliaseeRef - Match either GlobalValue or bitcast to GlobalValue.
AliaseeRef : ResultTypes SymbolicValueRef {
const Type* VTy = $1->get();
Value *V = getVal(VTy, $2);
GlobalValue* Aliasee = dyn_cast<GlobalValue>(V);
if (!Aliasee)
GEN_ERROR("Aliases can be created only to global values");
$$ = Aliasee;
CHECK_FOR_ERROR
delete $1;
}
| BITCAST '(' AliaseeRef TO Types ')' {
Constant *Val = $3;
const Type *DestTy = $5->get();
if (!CastInst::castIsValid($1, $3, DestTy))
GEN_ERROR("invalid cast opcode for cast from '" +
Val->getType()->getDescription() + "' to '" +
DestTy->getDescription() + "'");
$$ = ConstantExpr::getCast($1, $3, DestTy);
CHECK_FOR_ERROR
delete $5;
};
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Rules to match Modules // Rules to match Modules
@ -2045,34 +2085,20 @@ Definition
CurGV = 0; CurGV = 0;
CHECK_FOR_ERROR CHECK_FOR_ERROR
} }
| OptGlobalAssign GVVisibilityStyle ALIAS AliasLinkage ResultTypes | OptGlobalAssign GVVisibilityStyle ALIAS AliasLinkage AliaseeRef {
SymbolicValueRef {
std::string Name($1); std::string Name($1);
if (Name.empty()) if (Name.empty())
GEN_ERROR("Alias name cannot be empty") GEN_ERROR("Alias name cannot be empty");
const PointerType *PFTy = 0;
const FunctionType *Ty = 0; Constant* Aliasee = $5;
Value* V = 0; if (Aliasee == 0)
const Type* VTy = 0;
if (!(PFTy = dyn_cast<PointerType>($5->get())) ||
!(Ty = dyn_cast<FunctionType>(PFTy->getElementType()))) {
VTy = $5->get();
V = getExistingVal(VTy, $6);
} else {
VTy = PFTy;
V = getExistingVal(PFTy, $6);
}
if (V == 0)
GEN_ERROR(std::string("Invalid aliasee for alias: ") + $1); GEN_ERROR(std::string("Invalid aliasee for alias: ") + $1);
if (GlobalValue* Aliasee = dyn_cast<GlobalValue>(V)) {
GlobalAlias* GA = new GlobalAlias(VTy, $4, Name, Aliasee, GlobalAlias* GA = new GlobalAlias(Aliasee->getType(), $4, Name, Aliasee,
CurModule.CurrentModule); CurModule.CurrentModule);
GA->setVisibility($2); GA->setVisibility($2);
InsertValue(GA, CurModule.Values); InsertValue(GA, CurModule.Values);
} else
GEN_ERROR("Aliases can be created only to global values");
CHECK_FOR_ERROR CHECK_FOR_ERROR
delete $5;
} }
| TARGET TargetDefinition { | TARGET TargetDefinition {
CHECK_FOR_ERROR CHECK_FOR_ERROR

View File

@ -179,6 +179,27 @@ public:
} }
virtual void handleGlobalAlias(
const Type* ElemType,
GlobalValue::LinkageTypes Linkage,
unsigned TypeSlotNum,
unsigned AliaseeSlot) {
if (os) {
*os << " GA: "
<< " Linkage=" << Linkage
<< " Type=";
//WriteTypeSymbolic(*os, ElemType, M);
*os << " Slot=" << TypeSlotNum << " AliaseeSlot=" << AliaseeSlot
<< "\n";
}
bca.numValues++;
if (TypeSlotNum > bca.maxValueSlot)
bca.maxValueSlot = TypeSlotNum;
if (AliaseeSlot > bca.maxValueSlot)
bca.maxValueSlot = AliaseeSlot;
}
virtual void handleTypeList(unsigned numEntries) { virtual void handleTypeList(unsigned numEntries) {
bca.maxTypeSlot = numEntries - 1; bca.maxTypeSlot = numEntries - 1;
} }

View File

@ -1923,12 +1923,10 @@ void BytecodeReader::ParseModuleGlobalInfo() {
// Read aliases... // Read aliases...
unsigned VarType = read_vbr_uint(); unsigned VarType = read_vbr_uint();
while (VarType != Type::VoidTyID) { // List is terminated by Void while (VarType != Type::VoidTyID) { // List is terminated by Void
unsigned TypeSlotNo = VarType >> 2; unsigned TypeSlotNo = VarType >> 3;
unsigned EncodedLinkage = VarType & 3; unsigned EncodedLinkage = VarType & 3;
unsigned AliaseeTypeSlotNo, AliaseeSlotNo; bool isConstantAliasee = (VarType >> 2) & 1;
unsigned AliaseeSlotNo = read_vbr_uint();
AliaseeTypeSlotNo = read_vbr_uint();
AliaseeSlotNo = read_vbr_uint();
const Type *Ty = getType(TypeSlotNo); const Type *Ty = getType(TypeSlotNo);
if (!Ty) if (!Ty)
@ -1937,11 +1935,11 @@ void BytecodeReader::ParseModuleGlobalInfo() {
if (!isa<PointerType>(Ty)) if (!isa<PointerType>(Ty))
error("Alias not a pointer type! Ty= " + Ty->getDescription()); error("Alias not a pointer type! Ty= " + Ty->getDescription());
Value* V = getValue(AliaseeTypeSlotNo, AliaseeSlotNo, false); Value* V = getValue(TypeSlotNo, AliaseeSlotNo, false);
if (!V) if (!V && !isConstantAliasee)
error("Invalid aliasee! TypeSlotNo=" + utostr(AliaseeTypeSlotNo) + error("Invalid aliasee! TypeSlotNo=" + utostr(TypeSlotNo) +
" SlotNo=" + utostr(AliaseeSlotNo)); " SlotNo=" + utostr(AliaseeSlotNo));
if (!isa<GlobalValue>(V)) if (!isConstantAliasee && !isa<GlobalValue>(V))
error("Aliasee is not global value! SlotNo=" + utostr(AliaseeSlotNo)); error("Aliasee is not global value! SlotNo=" + utostr(AliaseeSlotNo));
GlobalValue::LinkageTypes Linkage; GlobalValue::LinkageTypes Linkage;
@ -1960,8 +1958,14 @@ void BytecodeReader::ParseModuleGlobalInfo() {
} }
GlobalAlias *GA = new GlobalAlias(Ty, Linkage, "", GlobalAlias *GA = new GlobalAlias(Ty, Linkage, "",
dyn_cast<GlobalValue>(V), TheModule); dyn_cast_or_null<Constant>(V),
TheModule);
insertValue(GA, TypeSlotNo, ModuleValues); insertValue(GA, TypeSlotNo, ModuleValues);
if (!V && isConstantAliasee)
Aliasees.push_back(std::make_pair(GA, AliaseeSlotNo));
if (Handler) Handler->handleGlobalAlias(Ty, Linkage,
TypeSlotNo, AliaseeSlotNo);
VarType = read_vbr_uint(); VarType = read_vbr_uint();
} }
} }
@ -2068,6 +2072,23 @@ void BytecodeReader::ParseModule() {
error("Cannot find initializer value."); error("Cannot find initializer value.");
} }
// And aliasees
while (!Aliasees.empty()) {
GlobalAlias *GA = Aliasees.back().first;
unsigned Slot = Aliasees.back().second;
Aliasees.pop_back();
// Look up the aliasee value...
const llvm::PointerType* GAType = GA->getType();
unsigned TypeSlot = getTypeSlot(GAType);
if (Constant *CV = getConstantValue(TypeSlot, Slot)) {
if (GA->getAliasee())
error("Aliasee was *already* set?!");
GA->setAliasee(CV);
} else
error("Cannot find aliasee value.");
}
if (!ConstantFwdRefs.empty()) if (!ConstantFwdRefs.empty())
error("Use of undefined constants in a module"); error("Use of undefined constants in a module");

View File

@ -129,6 +129,9 @@ public:
/// them. /// them.
typedef std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitsList; typedef std::vector<std::pair<GlobalVariable*, unsigned> > GlobalInitsList;
/// @brief A list of global aliases and the slot number for constant aliasees
typedef std::vector<std::pair<GlobalAlias*, unsigned> > AliaseeList;
/// This type maps a typeslot/valueslot pair to the corresponding Value*. /// This type maps a typeslot/valueslot pair to the corresponding Value*.
/// It is used for dealing with forward references as values are read in. /// It is used for dealing with forward references as values are read in.
/// @brief A map for dealing with forward references of values. /// @brief A map for dealing with forward references of values.
@ -338,6 +341,12 @@ private:
/// of what we must do. /// of what we must do.
GlobalInitsList GlobalInits; GlobalInitsList GlobalInits;
/// Constant values are read in after global aliases. Because of this, we must
/// defer setting the constant aliasees until after module level constants
/// have been read. In the mean time, this list keeps track of what we must
/// do.
AliaseeList Aliasees;
// For lazy reading-in of functions, we need to save away several pieces of // For lazy reading-in of functions, we need to save away several pieces of
// information about each function: its begin and end pointer in the buffer // information about each function: its begin and end pointer in the buffer
// and its FunctionSlot. // and its FunctionSlot.

View File

@ -89,6 +89,12 @@ void SlotCalculator::processModule() {
I != E; ++I) I != E; ++I)
CreateSlotIfNeeded(I); CreateSlotIfNeeded(I);
// Add all of the global aliases to the value table...
//
for (Module::const_alias_iterator I = TheModule->alias_begin(),
E = TheModule->alias_end(); I != E; ++I)
CreateSlotIfNeeded(I);
// Add all of the module level constants used as initializers // Add all of the module level constants used as initializers
// //
for (Module::const_global_iterator I = TheModule->global_begin(), for (Module::const_global_iterator I = TheModule->global_begin(),
@ -96,6 +102,13 @@ void SlotCalculator::processModule() {
if (I->hasInitializer()) if (I->hasInitializer())
CreateSlotIfNeeded(I->getInitializer()); CreateSlotIfNeeded(I->getInitializer());
// Add all of the module level constants used as aliasees
//
for (Module::const_alias_iterator I = TheModule->alias_begin(),
E = TheModule->alias_end(); I != E; ++I)
if (I->getAliasee())
CreateSlotIfNeeded(I->getAliasee());
// Now that all global constants have been added, rearrange constant planes // Now that all global constants have been added, rearrange constant planes
// that contain constant strings so that the strings occur at the start of the // that contain constant strings so that the strings occur at the start of the
// plane, not somewhere in the middle. // plane, not somewhere in the middle.

View File

@ -1095,9 +1095,11 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
// Output aliases // Output aliases
for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end(); for (Module::const_alias_iterator I = M->alias_begin(), E = M->alias_end();
I != E; ++I) { I != E; ++I) {
unsigned Slot = Table.getTypeSlot(I->getType()); unsigned TypeSlotNo = Table.getTypeSlot(I->getType());
assert(((Slot << 2) >> 2) == Slot && "Slot # too big!"); unsigned AliaseeSlotNo = Table.getSlot(I->getAliasee());
assert(((TypeSlotNo << 3) >> 3) == TypeSlotNo && "Slot # too big!");
unsigned aliasLinkage = 0; unsigned aliasLinkage = 0;
unsigned isConstantAliasee = ((!isa<GlobalValue>(I->getAliasee())) << 2);
switch (I->getLinkage()) { switch (I->getLinkage()) {
case GlobalValue::ExternalLinkage: case GlobalValue::ExternalLinkage:
aliasLinkage = 0; aliasLinkage = 0;
@ -1111,9 +1113,8 @@ void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
default: default:
assert(0 && "Invalid alias linkage"); assert(0 && "Invalid alias linkage");
} }
output_vbr((Slot << 2) | aliasLinkage); output_vbr((TypeSlotNo << 3) | isConstantAliasee | aliasLinkage);
output_vbr(Table.getTypeSlot(I->getAliasee()->getType())); output_vbr(AliaseeSlotNo);
output_vbr(Table.getSlot(I->getAliasee()));
} }
output_typeid(Table.getTypeSlot(Type::VoidTy)); output_typeid(Table.getTypeSlot(Type::VoidTy));
} }

View File

@ -123,18 +123,29 @@ bool AsmPrinter::doFinalization(Module &M) {
} }
if (TAI->getSetDirective()) { if (TAI->getSetDirective()) {
if (M.alias_size()) if (!M.alias_empty())
SwitchToTextSection(TAI->getTextSection()); SwitchToTextSection(TAI->getTextSection());
O << "\n"; O << "\n";
for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
I!=E; ++I) { I!=E; ++I) {
const GlobalValue *Aliasee = I->getAliasee(); const Constant *Aliasee = dyn_cast_or_null<Constant>(I->getAliasee());
assert(Aliasee && "Aliasee cannot be null!"); assert(Aliasee && "Aliasee cannot be null");
std::string Target = Mang->getValueName(Aliasee);
std::string Name = Mang->getValueName(I);
// Aliases with external weak linkage was emitted already std::string Name = Mang->getValueName(I);
std::string Target;
if (const GlobalValue *GV = dyn_cast<GlobalValue>(Aliasee))
Target = Mang->getValueName(GV);
else {
const ConstantExpr *CE = 0;
if ((CE = dyn_cast<ConstantExpr>(Aliasee)) &&
(CE->getOpcode() == Instruction::BitCast))
Target = Mang->getValueName(CE->getOperand(0));
else
assert(0 && "Unsupported aliasee");
}
if (I->hasExternalLinkage()) if (I->hasExternalLinkage())
O << "\t.globl\t" << Name << "\n"; O << "\t.globl\t" << Name << "\n";
else if (I->hasWeakLinkage()) else if (I->hasWeakLinkage())

View File

@ -75,9 +75,8 @@ bool GlobalDCE::runOnModule(Module &M) {
for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
I != E; ++I) { I != E; ++I) {
Changed |= RemoveUnusedGlobalValue(*I);
// Aliases are always needed even if they are not used. // Aliases are always needed even if they are not used.
GlobalIsNeeded(I); MarkUsedGlobalsAsNeeded(cast<Constant>(I->getAliasee()));
} }
// Now that all globals which are needed are in the AliveGlobals set, we loop // Now that all globals which are needed are in the AliveGlobals set, we loop
@ -143,10 +142,7 @@ void GlobalDCE::GlobalIsNeeded(GlobalValue *G) {
// referenced by the initializer to the alive set. // referenced by the initializer to the alive set.
if (GV->hasInitializer()) if (GV->hasInitializer())
MarkUsedGlobalsAsNeeded(GV->getInitializer()); MarkUsedGlobalsAsNeeded(GV->getInitializer());
} else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(G)) { } else if (!isa<GlobalAlias>(G)) {
// If this is a global alias we also need it's aliasee
GlobalIsNeeded(const_cast<GlobalValue*>(GA->getAliasee()));
} else {
// Otherwise this must be a function object. We have to scan the body of // Otherwise this must be a function object. We have to scan the body of
// the function looking for constants and global values which are used as // the function looking for constants and global values which are used as
// operands. Any operands of these types must be processed to ensure that // operands. Any operands of these types must be processed to ensure that

View File

@ -926,7 +926,7 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
assert(0 && "Invalid alias linkage"); assert(0 && "Invalid alias linkage");
} }
const GlobalValue *Aliasee = GA->getAliasee(); const Constant *Aliasee = dyn_cast_or_null<Constant>(GA->getAliasee());
assert(Aliasee && "Aliasee cannot be null"); assert(Aliasee && "Aliasee cannot be null");
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Aliasee)) { if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Aliasee)) {
@ -940,9 +940,15 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
Out << getLLVMName(F->getName(), GlobalPrefix); Out << getLLVMName(F->getName(), GlobalPrefix);
else else
Out << "@\"\""; Out << "@\"\"";
} else } else {
assert(0 && "Unsupported aliasee"); const ConstantExpr *CE = 0;
if ((CE = dyn_cast<ConstantExpr>(Aliasee)) &&
(CE->getOpcode() == Instruction::BitCast)) {
writeOperand(CE, false);
} else
assert(0 && "Unsupported aliasee");
}
printInfoComment(*GA); printInfoComment(*GA);
Out << "\n"; Out << "\n";
} }

View File

@ -163,12 +163,15 @@ void GlobalVariable::replaceUsesOfWithOnConstant(Value *From, Value *To,
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
GlobalAlias::GlobalAlias(const Type *Ty, LinkageTypes Link, GlobalAlias::GlobalAlias(const Type *Ty, LinkageTypes Link,
const std::string &Name, const GlobalValue* aliasee, const std::string &Name, Constant* aliasee,
Module *ParentModule) Module *ParentModule)
: GlobalValue(Ty, Value::GlobalAliasVal, 0, 0, : GlobalValue(Ty, Value::GlobalAliasVal, &Aliasee, 1, Link, Name) {
Link, Name), Aliasee(aliasee) {
LeakDetector::addGarbageObject(this); LeakDetector::addGarbageObject(this);
if (aliasee)
assert(aliasee->getType() == Ty && "Alias and aliasee types should match!");
Aliasee.init(aliasee, this);
if (ParentModule) if (ParentModule)
ParentModule->getAliasList().push_back(this); ParentModule->getAliasList().push_back(this);
} }
@ -190,12 +193,16 @@ void GlobalAlias::eraseFromParent() {
} }
bool GlobalAlias::isDeclaration() const { bool GlobalAlias::isDeclaration() const {
return (Aliasee && Aliasee->isDeclaration()); const GlobalValue* AV = dyn_cast_or_null<const GlobalValue>(getAliasee());
return (AV && AV->isDeclaration());
} }
void GlobalAlias::setAliasee(const GlobalValue *GV) void GlobalAlias::setAliasee(Constant *Aliasee)
{ {
// FIXME: Some checks? if (Aliasee) {
Aliasee = GV; assert(Aliasee->getType() == getType() &&
"Alias and aliasee types should match!");
setOperand(0, Aliasee);
}
} }

View File

@ -298,6 +298,9 @@ void Module::dropAllReferences() {
for(Module::global_iterator I = global_begin(), E = global_end(); I != E; ++I) for(Module::global_iterator I = global_begin(), E = global_end(); I != E; ++I)
I->dropAllReferences(); I->dropAllReferences();
for(Module::alias_iterator I = alias_begin(), E = alias_end(); I != E; ++I)
I->dropAllReferences();
} }
void Module::addLibrary(const std::string& Lib) { void Module::addLibrary(const std::string& Lib) {

View File

@ -316,7 +316,9 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) {
Assert1(GA.hasExternalLinkage() || GA.hasInternalLinkage() || Assert1(GA.hasExternalLinkage() || GA.hasInternalLinkage() ||
GA.hasWeakLinkage(), GA.hasWeakLinkage(),
"Alias should have external or external weak linkage!", &GA); "Alias should have external or external weak linkage!", &GA);
Assert1(GA.getType() == GA.getAliasee()->getType(),
"Alias and aliasee types should match!", &GA);
visitGlobalValue(GA); visitGlobalValue(GA);
} }

View File

@ -2,8 +2,6 @@
; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll ; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll
; RUN: diff %t1.ll %t2.ll ; RUN: diff %t1.ll %t2.ll
; XFAIL: *
@bar = external global i32 @bar = external global i32
@foo1 = alias i32* @bar @foo1 = alias i32* @bar
@foo2 = alias i32* @bar @foo2 = alias i32* @bar
@ -15,6 +13,8 @@ declare i32 @foo_f()
@bar_i = alias internal i32* @bar @bar_i = alias internal i32* @bar
@A = alias bitcast (i32* @bar to i64*)
define i32 @test() { define i32 @test() {
entry: entry:
%tmp = load i32* @foo1 %tmp = load i32* @foo1