blob: 45506b44eeb946b8862e6fe4a93be4ce216ce5cc [file] [log] [blame]
//===-- AST Linkables Interface ---------------------------------*- C++ -*-===//
//
// High Level Virtual Machine (HLVM)
//
// Copyright (C) 2006 Reid Spencer. All Rights Reserved.
//
// This software is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version.
//
// This software is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library in the file named LICENSE.txt; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA 02110-1301 USA
//
//===----------------------------------------------------------------------===//
/// @file hlvm/AST/Linkables.h
/// @author Reid Spencer <rspencer@reidspencer.com> (original author)
/// @date 2006/06/10
/// @since 0.1.0
/// @brief Declares the interface to all subclasses of Linkable
//===----------------------------------------------------------------------===//
#ifndef HLVM_AST_LINKABLE_H
#define HLVM_AST_LINKABLE_H
#include <hlvm/AST/Constants.h>
#include <hlvm/AST/ContainerType.h>
#include <hlvm/AST/Block.h>
namespace hlvm
{
/// This enumeration is used to specify the kinds of linkage that are
/// permitted for a Linkable.
/// @brief Enumeration of ways to link bundles
enum LinkageKinds {
ExternalLinkage = 1, ///< Externally visible item
LinkOnceLinkage = 2, ///< Keep one copy of item when linking (inline)
WeakLinkage = 3, ///< Keep one copy of item when linking (weak)
AppendingLinkage = 4, ///< Append item to an array of similar items
InternalLinkage = 5 ///< Rename collisions when linking (static funcs)
};
/// This class provides an Abstract Syntax Tree node that represents an item
/// which can be linked with other Bundles. Linkabe is an abstract base
/// class and cannot be instantiated. All Linkables are Constant values
/// because they represents a runtime value that is a constant address. The
/// value pointed to by the Linkable may be mutable or immutable depending
/// on its type and options. As the name suggests, Linkables participate
/// in linkage. A Bundle referring to a name in another Bundle will only link
/// with a Linkable and nothing else. There are several ways in which
/// Linkables can be linked together, specified by the LinkageKinds value.
/// @see LinkageKinds
/// @see Bundle
/// @see Constant
/// @brief AST Bundle Node
class Linkable : public Constant
{
/// @name Constructors
/// @{
protected:
Linkable( NodeIDs id ) : Constant(id) { setLinkageKind(InternalLinkage);}
virtual ~Linkable();
/// @}
/// @name Accessors
/// @{
public:
inline LinkageKinds getLinkageKind() const {
return LinkageKinds(flags & 0x0007); }
static inline bool classof(const Linkable*) { return true; }
static inline bool classof(const Node* N) { return N->isLinkable(); }
/// @}
/// @name Mutators
/// @{
void setLinkageKind(LinkageKinds k) {
flags &= 0xFFF8; flags |= uint16_t(k);
}
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents a
/// global Variable. A Variable can only be declared as a component of a
/// Bundle. It is visible throughout the Bundle that declares it and may
/// be a candidate for linkage with other Bundles. A Variable is a storage
/// location, with an address, of a specific type. Global variables may have
/// a constant value in which case HLVM will ensure that the value of the
/// global variable is immutable. Variables can be of any type.
/// @see Linkable
/// @see Bundle
/// @brief AST Variable Node
class Variable : public Linkable
{
/// @name Constructors
/// @{
protected:
Variable() : Linkable(VariableID), init(0) {}
virtual ~Variable();
/// @}
/// @name Accessors
/// @{
public:
bool isConstant() const { return flags & 0x0008; }
Constant* getInitializer() const { return init; }
bool hasInitializer() const { return init != 0; }
bool isZeroInitialized() const { return init == 0; }
static inline bool classof(const Variable*) { return true; }
static inline bool classof(const Node* N) { return N->is(VariableID); }
/// @}
/// @name Mutators
/// @{
public:
void setIsConstant(bool v) { flags |= 0x0008; }
void setInitializer(Constant* C) { init = C; }
/// @}
/// @name Data
/// @{
protected:
Constant* init;
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents an argument
/// to a Function. An Argument is simply a Value that has a name. Arguments can
/// be used within a function's blocks to access the value of the argument.
/// @see Value
/// @see Function
/// @brief AST Argument Node
class Argument : public Value
{
/// @name Constructors
/// @{
protected:
Argument() : Value(ArgumentID), name() {}
virtual ~Argument();
/// @}
/// @name Accessors
/// @{
public:
const std::string& getName() const { return name; }
/// Return the 1-based index of this in this function it belongs to.
/// If this is not an argument of any function, returns 0;
unsigned getArgNum() const;
static inline bool classof(const Argument*) { return true; }
static inline bool classof(const Node* N) { return N->is(ArgumentID); }
/// @}
/// @name Mutators
/// @{
public:
void setName(const std::string& nm) { name = nm; }
/// @}
/// @name Data
/// @{
protected:
std::string name;
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents a Function.
/// A Function is a callable block of code that accepts parameters and
/// returns a result. This is the basic unit of code in HLVM. A Function
/// has a name, a set of formal arguments, a return type, and, optionally, a
/// Block of code to execute. The name of a function is used for linking
/// purposes. The formal arguments and return type are encapsulated in the
/// Function's associated SignatureType. If a Block is associated with the
/// Function then the function is defined and the Block defines the computation
/// the Function provides. If a Block is not associated with the Function, then
/// the function is undefined and serves as a reference to a function in another
/// Bundle.
/// @see Block
/// @see Bundle
/// @see SignatureType
/// @brief AST Function Node
class Function : public Linkable
{
/// @name Types
/// @{
public:
typedef std::vector<Argument*> ArgumentList;
typedef ArgumentList::iterator iterator;
typedef ArgumentList::const_iterator const_iterator;
/// @}
/// @name Constructors
/// @{
protected:
Function(NodeIDs id = FunctionID) : Linkable(id), block(0), args() {}
virtual ~Function();
/// @}
/// @name Accessors
/// @{
public:
bool hasBlock() const { return block != 0; }
Block* getBlock() const { return block; }
const SignatureType* getSignature() const
{ return static_cast<const SignatureType*>(type); }
const Type* getResultType() const
{ return getSignature()->getResultType();}
Argument* getArgument(const std::string& name) const;
Argument* getArgument(unsigned argnum) const;
/// Return the 1-based index of the \p arg in this function. If \p arg
/// is not an argument of this function, returns 0;
unsigned getArgNum(const Argument* arg) const;
static inline bool classof(const Function*) { return true; }
static inline bool classof(const Node* N) { return N->isFunction(); }
/// @}
/// @name Argument Iteration
/// @{
public:
iterator begin() { return args.begin(); }
const_iterator begin() const { return args.begin(); }
iterator end () { return args.end(); }
const_iterator end () const { return args.end(); }
size_t size () const { return args.size(); }
bool empty() const { return args.empty(); }
Argument* front() { return args.front(); }
const Argument* front() const { return args.front(); }
Argument* back() { return args.back(); }
const Argument* back() const { return args.back(); }
/// @}
/// @name Mutators
/// @{
public:
virtual void insertChild(Node* kid);
virtual void removeChild(Node* kid);
void setBlock(Block* blk) { blk->setParent(this); }
void addArgument(Argument* arg) { args.push_back(arg); }
virtual void resolveTypeTo(const Type* from, const Type* to);
/// @}
/// @name Data
/// @{
protected:
Block * block; ///< The code block to be executed
ArgumentList args;
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents a Program
/// in HLVM. A Program is an entry point for running HLVM programs. It is
/// simply a Function with a specific signature. It represents the first
/// function to be executed by the runtime after option processing. To be
/// executable, a Bundle must have at least one Program node in it.
/// The Program node exists to simply ensure that the signature of the function
/// is correct and to serve as a way to identify Program's quickly.
/// @see Function
/// @see Bundle
/// @see SignatureType
/// @brief AST Program Node
class Program : public Function
{
/// @name Constructors
/// @{
protected:
Program() : Function(ProgramID) {}
virtual ~Program();
/// @}
/// @name Accessors
/// @{
public:
static inline bool classof(const Program*) { return true; }
static inline bool classof(const Node* N) { return N->is(ProgramID); }
/// @}
/// @name Data
/// @{
private:
Linkable::setLinkageKind;
/// @}
friend class AST;
};
} // end hlvm namespace
#endif