\section{Substrate Encapsulation}
\label{sec:substrate-encapsulation}

As has mentioned earlier, Machine SUIF can be viewed as an implementation
of the OPI on a substrate consisting of C++ library facilities and the core
of the Stanford SUIF infrastructure.  The [[machine]] library serves as the
layer that encapsulates the substrate for the rest of Machine SUIF, so that
libraries and passes are easy to move to OPI implementations that are based
on different substrates.

This section collects a number of declarations that help with substrate
encapsulation.  The header file ([[substrate.h]]) that it generates doesn't
depend on any OPI types defined elsewhere.  It is meant to be included by
other modules in the [[machine]] library, including the hoof-generated
module that defines many of the IR types in the OPI.

The [[substrate.h]] header file is also included by [[machine.h]], which
collects the exports of the [[machine]] library.  Clients of the library
therefore see these declarations when they include [[machine.h]].


\subsection{OPI Types}

Several OPI types are implemented in Machine SUIF as synonyms for SUIF
types.

<<renamed types>>=
typedef AnnotableObject IrObject;
typedef ProcedureSymbol ProcSym;
typedef ProcedureDefinition ProcDef;
typedef ProcedureDefinition OptUnit;
typedef PointerType PtrType;
typedef Symbol Sym;
typedef SymbolTable SymTable;
typedef SymbolTable ScopeTable;
typedef VariableSymbol VarSym;
typedef VariableDefinition VarDef;
typedef CodeLabelSymbol LabelSym;
@

Since the OPI's type abstraction, [[TypeId]], is used without an explicit
level of indirection, we make it a synonym for [[Type*]] instead of
[[Type]].

<<type [[TypeId]]>>=
typedef Type* TypeId;
@

\subsection{Class [[Integer]]}

In order to support cross-compilation without being limited by the host's
numeric characteristics, the OPI makes use of extended-precision integers.
The implementation of OPI-class [[Integer]] derives from SUIF's
infinite-integer class.

<<class [[Integer]]>>=
class Integer : public IInteger {
  public:
    Integer() { }				// returns the empty string
    Integer(const char *chars)			: IInteger(chars) { }
    Integer(const IInteger &i_integer)		: IInteger(i_integer) { }

    Integer(signed char integral)		: IInteger(integral) { }
    Integer(unsigned char integral)		: IInteger(integral) { }
    Integer(short integral)			: IInteger(integral) { }
    Integer(unsigned short integral)		: IInteger(integral) { }
    Integer(int integral)			: IInteger(integral) { }
    Integer(unsigned int integral)		: IInteger(integral) { }
    Integer(long integral)			: IInteger(integral) { }
    Integer(unsigned long integral)		: IInteger(integral) { }
#ifdef LONGLONG
    Integer(LONGLONG integral)			: IInteger(integral) { }
    Integer(unsigned LONGLONG integral)		: IInteger(integral) { }
#endif
    Integer(const char *initial_string, int base = 10);

    const char* chars() const { return c_string_int(); }
};
@


\subsection{Class [[IdString]]}

The OPI class [[IdString]] derived directly from SUIF's ``lexicon string''
class.  Values are hashed into a global lexicon, so that comparison for
equality takes place in constant time.

<<class [[IdString]]>>=

class IdString : public LString {
  public:
    IdString() { }				// returns the empty string
    IdString(const IdString &id_string)	: LString(id_string) { }
    IdString(const LString &l_string)	: LString(l_string) { }
    IdString(const String &string)	: LString(string) { }
    IdString(const char *chars)		: LString(chars) { }

    const char* chars() const { return c_str(); }
    bool is_empty()	const { return length() == 0; }
};

extern const IdString empty_id_string;
@

We provide a less-than operator on [[IdString]] values in a manner that
allows them to be used in STL sets and maps.

<<string function>>=
class less<IdString> : public binary_function<IdString, IdString, bool> {
  public:
    bool operator()(const IdString &s1, const IdString &s2) const
	{ return s1.get_ordinal() < s2.get_ordinal(); }
};
@



\subsection{Living with C++ Container Classes}

\paragraph{SUIF's STL substitutes.}

To counteract the vagaries of C++ implementations, SUIF has its own
STL-like container classes.  In order to be free to switch between the
native STL classes and SUIF's substitutes, Machine SUIF uses its own
container names.

<<container-class defines>>=
#define List list
#define Vector vector
#define Set set
#define Map map
#define HashMap suif_hash_map
@


\paragraph{Iterator arithmetic.}

A certain kind of C++ container-class ``iterator'' can be incremented or
decremented but can't be used in other pointer arithmetic.  The following
functions can be applied to such an iterator (which in OPI jargon we call a
\emph{handle}) to produce a handle on the preceding or following element
without side-affecting the argument.

<<iterator helpers>>=
template <class Iterator>
Iterator
before(Iterator iterator)
{
    return --iterator;
}

template <class Iterator>
Iterator
after(Iterator iterator)
{
    return ++iterator;
}
@




\subsection{C++ and Base SUIF Header Files}

This module takes care of including header C++ and base SUIF header files
that are widely used in Machine SUIF.  When adding a new C++ module to the
system, it is usually not necessary to worry about its dependence any
specific substrate header files, since they come in via inclusion of
[[<machine/machine.h>]].

<<substrate header includes>>=
#include <stdlib.h>
#include <set>
#include <map>
#include <functional>
				// Following suppresses inclusion of <vector>
				// under SGI STL, which defines bit_vector,
				// which conflicts with a basesuif typedef.
#define __SGI_STL_VECTOR
#include <vector.h>

#include <common/i_integer.h>
#include <common/formatted.h>
#include <common/suif_vector.h>
#include <common/suif_list.h>
#include <common/suif_map.h>
#include <common/suif_indexed_list.h>
#include <bit_vector/bit_vector.h>
#include <utils/type_utils.h>
#include <utils/symbol_utils.h>
#include <utils/expression_utils.h>
extern "C" void init_utils(SuifEnv*);

#include <suifkernel/suif_env.h>
#include <suifkernel/dll_subsystem.h>
#include <suifkernel/command_line_parsing.h>
#include <basicnodes/basic.h>
#include <basicnodes/basic_constants.h>
#include <suifnodes/suif.h>
#include <typebuilder/type_builder.h>
#include <suifcloning/cloner.h>

#include <basicnodes/basic_factory.h>
#include <suifnodes/suif_factory.h>
@



\subsection{Accessing SUIF Value Descriptors}

SUIF has a number of IR classes devoted to describing static data values
such as those that appear in C initializers.  These are rarely used in
Machine SUIF, and they ought to be better encapsulated than they are at
present.  Meanwhile, here are some functions used for access SUIF's value
descriptors.  The important classes are [[ValueBlock]], which is the root
class for value descriptions, and [[VarDef]] which connects a variable
symbol with its statically-defined value (if it has one).  A
[[MultiValueBlock]] describes an aggregate of values, while a
[[RepeatValueBlock]] represents a series of copies of the same value.
An [[ExpressionValueBlock]] used an expression to describe an initial
value.  In this case, the easiest way to extract a description of the value
is to use a Machine SUIF operand.

<<accessing value descriptors>>=
VarDef* get_def(VarSym*);
ProcSym* get_proc_sym(ProcDef*); 

ValueBlock* get_init(VarDef* d);
int get_bit_alignment(VarDef* d);

int subblocks_size(MultiValueBlock *mvb);

ValueBlock* get_subblock(MultiValueBlock *mvb, int i);

Integer get_subblock_offset(MultiValueBlock *mvb, int i);

int get_repetition_count(RepeatValueBlock *rvb);

ValueBlock* get_subblock(RepeatValueBlock *rvb);

TypeId get_type(ValueBlock *vb);

class Opnd;
Opnd get_value(ExpressionValueBlock *svb);
@


\subsection{Miscellany}

\paragraph{Current compilation environment.}

The following global variable connects to the substrate by recording the
current ``SUIF environment'', which holds the current file set, modules
loaded, object factories, and so on.

<<SUIF environment>>=
extern SuifEnv* the_suif_env;
@

\paragraph{Extracting the name of a named object.}

The overloaded function [[get_name]] provides a uniform way to extract the
name of a source file or procedure or to get the name of a symbol or type.
(Symbols and types are instances of SUIF's [[SymbolTableObject]] class.)

<<function [[get_name]]>>=
IdString get_name(FileBlock*);
IdString get_name(ProcDef*);
IdString get_name(SymbolTableObject*);
@

\paragraph{SUIF object-class identification.}

SUIF objects are built on a reflection system that allows easy run-time
identification of their classes.  It is useful during debugging to the able
to print the class name of a SUIF object.

<<class identification>>=
const char* get_class_name(SuifObject*);
@


\paragraph{An IR-class forward reference.}

Class [[AnyBody]] requires a forward reference to [[InstrList]].  Since
[[substrate.h]] is one of the few headers included before the
hoof-generated OPI types are defined, we include this forward reference
here.

<<forward reference>>=
class InstrList;
@

\paragraph{Command-line option helpers.}

Fetching the strings accumulated in an [[OptionString]] (one of the
non-terminal descriptor in a SUIF command-line grammar) is a bit clumsy.
This helper abbreviates the procedure a bit.

<<command-line-option helpers>>=
IdString get_option_string_value(OptionString*, int pos = 0);
@

The next helper processes zero, one or two files names from a command line.
It uses [[the_suif_env]] to decide whether an input file is appropriate and
behaves accordingly.  If no input is in the environment already and there
is at least one name given, it reads the SUIF file into the environment.
If an output file is provided, it returns its name.  Otherwise, it returns
the empty string.

<<command-line-option helpers>>=

IdString process_file_names(OptionString *file_names);
@


\subsection{Header file [[substrate.h]]}

The substrate header file has the following outline:

<<substrate.h>>=
/* file "machine/substrate.h" */

<<Machine-SUIF copyright>>

#ifndef MACHINE_SUBSTRATE_H
#define MACHINE_SUBSTRATE_H

#include <machine/copyright.h>

#ifndef SUPPRESS_PRAGMA_INTERFACE
#pragma interface "machine/substrate.h"
#endif

<<substrate header includes>>

<<forward reference>>

<<iterator helpers>>

<<renamed types>>

<<type [[TypeId]]>>

<<class [[Integer]]>>

<<class [[IdString]]>>

<<string function>>

<<accessing value descriptors>>

<<SUIF environment>>

<<function [[get_name]]>>

<<class identification>>

<<command-line-option helpers>>

<<container-class defines>>

<<SUIF environment>>

<<class identification>>

#endif /* MACHINE_SUBSTRATE_H */
@
