//===- MCLDAttribute.h ----------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_ATTRIBUTE_H
#define MCLD_ATTRIBUTE_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <vector>
#include <string>
namespace mcld
{
class AttributeFactory;
/** \class AttributeBase
* \brief AttributeBase provides the real storage for attributes of options.
*
* Attributes are options affecting the link editing of input files.
* Some options affects the input files mentioned on the command line after
* them. For example, --whole-archive option affects archives mentioned on
* the command line after the --whole-archve option. We call such options
* "attributes of input files"
*
* AttributeBase is the storage for attributes of input files. Each input
* file (@see mcld::Input in MCLinker) has a pointer of an attribute. Since
* most attributes of input files are identical, our design lets input files
* which have identical attributes share common attribute. AttributeBase is
* the shared storage for attribute.
*/
class AttributeBase
{
public:
AttributeBase()
: m_WholeArchive(false),
m_AsNeeded(false),
m_AddNeeded(true),
m_Static(false)
{ }
AttributeBase(const AttributeBase& pBase)
: m_WholeArchive(pBase.m_WholeArchive),
m_AsNeeded(pBase.m_AsNeeded),
m_AddNeeded(pBase.m_AddNeeded),
m_Static(pBase.m_Static)
{ }
virtual ~AttributeBase()
{ }
// ----- observers ----- //
// represent GNU ld --whole-archive/--no-whole-archive options
bool isWholeArchive() const
{ return m_WholeArchive; }
// represent GNU ld --as-needed/--no-as-needed options
bool isAsNeeded() const
{ return m_AsNeeded; }
// represent GNU ld --add-needed/--no-add-needed options
bool isAddNeeded() const
{ return m_AddNeeded; }
// represent GNU ld -static option
bool isStatic() const
{ return m_Static; }
// represent GNU ld -call_shared option
bool isDynamic() const
{ return !m_Static; }
public:
bool m_WholeArchive : 1;
bool m_AsNeeded : 1;
bool m_AddNeeded : 1;
bool m_Static : 1;
};
/** \class Attribute
* \brief The base class of attributes. Providing the raw operations of an
* attributes
*
* For conventience and producing less bugs, we move the stoarges of attributes
* onto AttributeBase, and modifiers remains with the class Attribute.
*/
class Attribute : public AttributeBase
{
public:
// ----- modifiers ----- //
void setWholeArchive()
{ m_WholeArchive = true; }
void unsetWholeArchive()
{ m_WholeArchive = false; }
void setAsNeeded()
{ m_AsNeeded = true; }
void unsetAsNeeded()
{ m_AsNeeded = false; }
void setAddNeeded()
{ m_AddNeeded = true; }
void unsetAddNeeded()
{ m_AddNeeded = false; }
void setStatic()
{ m_Static = true; }
void setDynamic()
{ m_Static = false; }
};
/** \class AttrConstraint
* \brief AttrConstarint is the constraint of a system.
*
* Some systems can not enable certain attributes of a input file.
* For example, systems which have no shared libraries can not enable
* --call_shared options. We call the ability of enabling attributes
* as the constraint of attributes of a system.
*
* Systems enable attributes at the target implementation of SectLinker.
*
* @see SectLinker
*/
class AttrConstraint : public AttributeBase
{
public:
void enableWholeArchive()
{ m_WholeArchive = true; }
void disableWholeArchive()
{ m_WholeArchive = false; }
void enableAsNeeded()
{ m_AsNeeded = true; }
void disableAsNeeded()
{ m_AsNeeded = false; }
void enableAddNeeded()
{ m_AddNeeded = true; }
void disableAddNeeded()
{ m_AddNeeded = false; }
void setSharedSystem()
{ m_Static = false; }
void setStaticSystem()
{ m_Static = true; }
bool isSharedSystem() const
{ return !m_Static; }
bool isStaticSystem() const
{ return m_Static; }
bool isLegal(const Attribute& pAttr) const;
};
/** \class AttributeProxy
* \brief AttributeProxys is the illusion of private attribute of each
* input file.
*
* We designers want to hide the details of sharing common attributes
* between input files. We want input files under the illusion that they
* have their own private attributes to simplify the linking algorithms.
*
* AttributeProxy hides the reality of sharing. An input file can change
* its attribute without explicit searching of existing attributes
* as it has a private ownership of the attribute. AttributeProxy does
* the searching in the AttributeFactory and changes the pointer of
* the attribute of the input file. If the searching fails, AttributeProxy
* requests a new attribute from the AttributeFactory.
*/
class AttributeProxy
{
private:
friend class AttributeFactory;
explicit AttributeProxy(AttributeFactory& pParent, Attribute& pBase);
~AttributeProxy();
public:
// ----- observers ----- //
bool isWholeArchive() const;
bool isAsNeeded() const;
bool isAddNeeded() const;
bool isStatic() const;
bool isDynamic() const;
Attribute* attr()
{ return m_pBase; }
const Attribute* attr() const
{ return m_pBase; }
// ----- modifiers ----- //
void setWholeArchive();
void unsetWholeArchive();
void setAsNeeded();
void unsetAsNeeded();
void setAddNeeded();
void unsetAddNeeded();
void setStatic();
void setDynamic();
private:
AttributeProxy* clone() const;
void change(Attribute* pBase)
{ m_pBase = pBase; }
private:
AttributeFactory &m_AttrPool;
Attribute *m_pBase;
};
// ----- comparisons ----- //
inline bool operator== (const Attribute& pLHS, const Attribute& pRHS)
{
return ((pLHS.isWholeArchive() == pRHS.isWholeArchive()) &&
(pLHS.isAsNeeded() == pRHS.isAsNeeded()) &&
(pLHS.isAddNeeded() == pRHS.isAddNeeded()) &&
(pLHS.isStatic() == pRHS.isStatic()));
}
inline bool operator!= (const Attribute& pLHS, const Attribute& pRHS)
{
return !(pLHS == pRHS);
}
} // namespace of mcld
#endif