Tapenade’s representation classes

About chained lists of Objects

Tapenade provides the following utility classes, mostly independent from AD itself.

TapList<XX>: forward chained lists of Objects of type XX. Direct access through XX head and TapList<XX> tail. For those who remember Le_Lisp, a TapList is a cons, head is car, tail is cdr.

TapList<TapPair<K, V>> represents an association list, called A-list by Lisp programmer, with a key of type K and a value of type V.

Convention on the structure of (TapList) trees of zones

Trees of (extended declared) zones of any reference expression MUST obey the present CONVENTION, and likewise all functions that use or create these trees e.g. symbolTable.treeOfZonesOfValue(), TapList.getSetFieldLocation(), includePointedElementsInTree(),…

EXAMPLES of structures of zonesTree’s: (<> represents any leaf info e.g. a TapIntList, Boolean, etc…, BUT NOT A TapList ! )

    for an varRef of Type:       the zonesTree is:
      R                          (<>)
      S3                         ((<>) (<>) (<>))
     *R                          (<> <>)
     *S3                         (<> (<>) (<>) (<>))
   ***R                          (<> <> <> <>)
      S3 with son2:S2            ((<>) ((<>) (<>)) (<>))
      S3 with son2:*R            ((<>) (<> <>) (<>))
     *S3 with son2:**S3          (<> (<>) (<> <> (<>) (<>) (<>)) (<>))

Important property: if a <> has a brother, then it is a pointer and the tail of its father, if present, is its destination zonesTree.

About storage

  • Files: BlockStorage UnitStorage

additional storage of info on Call-Graph and Flow-Graph nodes, in the form of an array of Objects, indexed by the node’s rank.

About entries in the symbol table

  • Files:
    SymbolDecl VariableDecl TypeDecl FunctionDecl ClassDecl
    NameSpaceDecl InterfaceDecl FieldDecl

Each SymbolTable contains a hash table (hash on the symbol name), each bucket containing a (TapList<SymbolDecl>) i.e. a hatted list of SymbolDecl’s. A “hatted” list is a TapList whose first element is empty/null and therefore whose actual contents start at the next element. It is used to emulate pass-by-reference. Each SymbolDecl holds all useful information about one particular symbol of the program. Depending on the kind of symbol, a SymbolDecl is actually of one of the following sub-types:

  • VariableDecl: a variable name

  • TypeDecl: a type name

  • FunctionDecl: a function name

  • ClassDecl: a class name

  • NameSpaceDecl: a C++ namespace

  • InterfaceDecl: the name of an interface (e.g. the INTERFACE declaration in Fortran 90)

  • FieldDecl: the name of a field in a record or union. This kind of SymbolDecl should probably disappear and be replaced by the previous kinds of SymbolDecl.

Every SymbolDecl holds:

  • the String of the symbol name

  • indication whether there are already statements in the code that declare the various aspects of this symbol. If not, then declaration instructions will have to be added to the regenerated source.

  • Indication about the location of this symbol’s declaration in the original source.

  • A list (TapList<String> extraInfo) containing extra labels on this symbol (e.g. public, pointer, volatile...)

  • A list (TapList<SymbolDecl> dependsOn) of the other SymbolDecl’s in the current SymbolTable, on which the declaration of this symbol depends. This is useful to preserve consistency should the declaration order change.

  • ...

In addition, every VariableDecl holds:

  • the type of the variable (see section 9{reference-type=”ref” reference=”secNoteTypes”})

  • the Tapenade-Memory-Zones of this variable (see section 11{reference-type=”ref” reference=”secState2”}: data-flow infrastructure)

  • an optional initialization Tree

  • ...

In addition, every TypeDecl holds:

  • the actual type which this symbol stands for (see section 9{reference-type=”ref” reference=”secNoteTypes”})

  • ...

In addition, every FunctionDecl holds:

  • the Unit of the function that this name designates

  • ...

In addition, every ClassDecl holds:

  • the Unit of the class that this name designates

In addition, every NameSpaceDecl holds:

  • the SymbolTable of this nameSpace

In addition, every InterfaceDecl holds: (Warning: not sure to keep these InterfaceDecl)

  • ...

In addition, every FieldDecl holds: (Warning: not sure to keep these FieldDecl, see CompositeTypeSpec)

  • the actual type of this field (see section 9{reference-type=”ref” reference=”secNoteTypes”})

Type representation

  • Files:
    TypeSpec WrapperTypeSpec VoidTypeSpec MetaTypeSpec LabelTypeSpec PrimitiveTypeSpec
    NamedTypeSpec EnumTypeSpec ClassTypeSpec ModifiedTypeSpec ArrayTypeSpec
    PointerTypeSpec ReferenceTypeSpec CompositeTypeSpec FunctionTypeSpec ArrayDim

TypeSpec is the base class of all types. TypeSpec holds:

  • ...

WrapperTypeSpec is a meaningless wrapper type around another TypeSpec. It is used to emulate pass-by-reference. In principle, on can place as many WrapperTypeSpec as they wish around any TypeSpec, but it uses memory space and traversal time. WrapperTypeSpec’s are useful during construction of the IR. During construction, a WrapperTypeSpec is placed between every TypeSpec and its “base” TypeSpec. They are less useful later, and Tapenade should remove them then (not done).

Firstly, here are the “leaf” types that do not contain (i.e. refer to, point to) a “base” TypeSpec:

VoidTypeSpec represents the “void” type

MetaTypeSpec is used only in the “*Lib” descriptions of intrinsic routines. It basically stands for any type, but allows the specification to restrict to a given type subset e.g. the floating point numbers of any size, and also allows it to specify that two arguments must be of the same type, whatever it is.

LabelTypeSpec is the type of variables that hold a GOTO label

PrimitiveTypeSpec stands for a primitive type. PrimitiveTypeSpec holds:

  • (String name) the name of this primitive type (in :”integer”, “float”, “complex”, “boolean”, “character”) In a very special case, name can be “adouble”. Not sure we need this. Ideally, there should be only one object created for each case, shared by all types that refer to it (?)

  • (int size) its size in bytes.

NamedTypeSpec stands for another type that is referred to by a name. The actual type referred to will be found by looking up for the name in the current SymbolTable. The SymbolTable will be searched for a TypeDecl with this name. NamedTypeSpec holds:

  • (String name) the name of the type.

EnumTypeSpec represents a C-like enumerated (“enum”) type. EnumTypeSpec holds:

  • (String name) the name of the enum type.

  • (Tree enumTree) the possible enumerated values.

ClassTypeSpec represents a class type. ClassTypeSpec holds:

  • (String name) the name of the class type.

  • (Unit unit) the Unit of the class.

Here are now the types that “contain” a “base” TypeSpec:

ModifiedTypeSpec stands for a type which is modified by imposing some modifiers to it. Modifiers here are only abut size or the “sign” issues. ModifiedTypeSpec holds:

  • (TypeSpec elementType ?) the contained type (unmodified)

  • the modifiers that apply to the size in bytes

  • the signed/unsigned modifier

ArrayTypeSpec stands for a n-dimensional array type of a given base type. ArrayTypeSpec holds:

  • (TypeSpec elementType) the contained type

  • (ArrayDim[] dimensions) the specification of each dimension of the array. Slowest dimension comes first, fastest last.

PointerTypeSpec stands for “pointer-to” types. PointerTypeSpec holds:

  • (TypeSpec destinationType ?) the pointed-to type

  • (ArrayDim offsetLength) when this pointer-to type is actually an array-of type (C style), the dimension of the array.

ReferenceTypeSpec stands for the C++ “&” types for pass-by-reference. ReferenceTypeSpec holds:

  • (TypeSpec destinationType ?) the pointed-to type

  • some modifiers (e.g. “const”)

Here are types that are made of several base types:

CompositeTypeSpec stands for Record or Union types.

  • (FieldDecl[] fields) the array of all fields of this composite type. For consistency, this FieldDecl[] should be replaced with a SymbolTable (or maybe 3 like in a Class) of all “things” accessible through this composite type These “things” can be fields (i.e. variables) as well as types or functions, so it would be more reasonable to store them into a SymbolTable.

  • (String name) optional name given to this CompositeTypeSpec upon creation. E.g. in C, the “nn” in: struct nn {float field1; int field2;}

  • indication of Record vs Union.

  • some modifiers (e.g. “sequence”, “private”, ...)

FunctionTypeSpec is the type of a function. FunctionTypeSpec holds:

  • (TypeSpec[] argumentsTypes) the types of the function’s arguments

  • A mark for variable number of arguments

  • (TypeSpec returnType) the return type of the function

Environment

  • Files: TapEnv

The unique object tapEnv is created at the beginning and passed/used almost everywhere. It contains several “environment” parameters that influence Tapenade’s behavior, such as:

  • the sizes in bytes of primitive types,

  • the “current” Unit. Not sure this is the right place to keep this,

  • the functions that should be inlined,

  • various counters that will grow during Tapenade execution,

  • the current differentiation “mode”,

  • which data-flow analysis is requested,

  • turn on/off several differentiation options or refinements.

Messages, Logger

  • Files: PositionAndMessage

wrapper around a message that Tapenade emits and its related position in the source.

  • Files: TapEnv

TapEnv.print TapEnv.println
TapEnv.printOnTrace TapEnv.printlnOnTrace
...

These methods define the Tapenade logging handler, with detail levels.