Ignore:
Timestamp:
Sep 10, 2021, 10:43:15 AM (3 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
Children:
63b3279
Parents:
d0b9247
Message:

Andrew MMath: Used (most of) Gregor's feedback to update the thesis. There are still a few \todo items as well as a general request for examples.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • doc/theses/andrew_beach_MMath/implement.tex

    rd0b9247 r9cdfa5fb  
    1414\label{s:VirtualSystem}
    1515% Virtual table rules. Virtual tables, the pointer to them and the cast.
    16 While the \CFA virtual system currently has only one public features, virtual
     16While the \CFA virtual system currently has only two public features, virtual
    1717cast and virtual tables,
    18 % ??? refs (see the virtual cast feature \vpageref{p:VirtualCast}),
    1918substantial structure is required to support them,
    2019and provide features for exception handling and the standard library.
     
    3534as part of field-by-field construction.
    3635
    37 \subsection{Type Id}
    38 Every virtual type has a unique id.
     36\subsection{Type ID}
     37Every virtual type has a unique ID.
    3938These are used in type equality, to check if the representation of two values
    4039are the same, and to access the type's type information.
     
    4443
    4544Our approach for program uniqueness is using a static declaration for each
    46 type id, where the run-time storage address of that variable is guaranteed to
     45type ID, where the run-time storage address of that variable is guaranteed to
    4746be unique during program execution.
    48 The type id storage can also be used for other purposes,
     47The type ID storage can also be used for other purposes,
    4948and is used for type information.
    5049
    51 The problem is that a type id may appear in multiple TUs that compose a
    52 program (see \autoref{ss:VirtualTable}); so the initial solution would seem
    53 to be make it external in each translation unit. Hovever, the type id must
     50The problem is that a type ID may appear in multiple TUs that compose a
     51program (see \autoref{ss:VirtualTable}), so the initial solution would seem
     52to be make it external in each translation unit. Hovever, the type ID must
    5453have a declaration in (exactly) one of the TUs to create the storage.
    5554No other declaration related to the virtual type has this property, so doing
    5655this through standard C declarations would require the user to do it manually.
    5756
    58 Instead the linker is used to handle this problem.
     57Instead, the linker is used to handle this problem.
    5958% I did not base anything off of C++17; they are solving the same problem.
    6059A new feature has been added to \CFA for this purpose, the special attribute
    6160\snake{cfa_linkonce}, which uses the special section @.gnu.linkonce@.
    62 When used as a prefix (\eg @.gnu.linkonce.example@) the linker does
     61When used as a prefix (\eg @.gnu.linkonce.example@), the linker does
    6362not combine these sections, but instead discards all but one with the same
    6463full name.
    6564
    66 So each type id must be given a unique section name with the linkonce
    67 prefix. Luckily \CFA already has a way to get unique names, the name mangler.
     65So, each type ID must be given a unique section name with the \snake{linkonce}
     66prefix. Luckily, \CFA already has a way to get unique names, the name mangler.
    6867For example, this could be written directly in \CFA:
    6968\begin{cfa}
     
    7473__attribute__((section(".gnu.linkonce._X1fFv___1"))) void _X1fFv___1() {}
    7574\end{cfa}
    76 This is done internally to access the name manglers.
     75This is done internally to access the name mangler.
    7776This attribute is useful for other purposes, any other place a unique
    7877instance required, and should eventually be made part of a public and
     
    8180\subsection{Type Information}
    8281
    83 There is data stored at the type id's declaration, the type information.
    84 The type information currently is only the parent's type id or, if the
     82There is data stored at the type ID's declaration, the type information.
     83The type information currently is only the parent's type ID or, if the
    8584type has no parent, the null pointer.
    86 The ancestors of a virtual type are found by traversing type ids through
     85The ancestors of a virtual type are found by traversing type IDs through
    8786the type information.
    8887An example using helper macros looks like:
     
    105104\item
    106105Generate a new structure definition to store the type
    107 information. The layout is the same in each case, just the parent's type id,
     106information. The layout is the same in each case, just the parent's type ID,
    108107but the types used change from instance to instance.
    109108The generated name is used for both this structure and, if relevant, the
     
    115114\item
    116115The definition is generated and initialized.
    117 The parent id is set to the null pointer or to the address of the parent's
     116The parent ID is set to the null pointer or to the address of the parent's
    118117type information instance. Name resolution handles the rest.
    119118\item
     
    151150file as if it was a forward declaration, except no definition is required.
    152151
    153 This technique is used for type-id instances. A link-once definition is
     152This technique is used for type ID instances. A link-once definition is
    154153generated each time the structure is seen. This will result in multiple
    155154copies but the link-once attribute ensures all but one are removed for a
     
    168167\subsection{Virtual Table}
    169168\label{ss:VirtualTable}
    170 Each virtual type has a virtual table type that stores its type id and
     169%\todo{Clarify virtual table type vs. virtual table instance.}
     170Each virtual type has a virtual table type that stores its type ID and
    171171virtual members.
    172172Each virtual type instance is bound to a table instance that is filled with
     
    176176
    177177The layout always comes in three parts (see \autoref{f:VirtualTableLayout}).
    178 The first section is just the type id at the head of the table. It is always
     178The first section is just the type ID at the head of the table. It is always
    179179there to ensure that it can be found even when the accessing code does not
    180180know which virtual type it has.
    181 The second section are all the virtual members of the parent, in the same
     181The second section is all the virtual members of the parent, in the same
    182182order as they appear in the parent's virtual table. Note that the type may
    183183change slightly as references to the ``this" change. This is limited to
     
    199199This, combined with the fixed offset to the virtual table pointer, means that
    200200for any virtual type, it is always safe to access its virtual table and,
    201 from there, it is safe to check the type id to identify the exact type of the
     201from there, it is safe to check the type ID to identify the exact type of the
    202202underlying object, access any of the virtual members and pass the object to
    203203any of the method-like virtual members.
     
    207207the context of the declaration.
    208208
    209 The type id is always fixed; with each virtual table type having
    210 exactly one possible type id.
     209The type ID is always fixed, with each virtual table type having
     210exactly one possible type ID.
    211211The virtual members are usually filled in by type resolution.
    212212The best match for a given name and type at the declaration site is used.
    213213There are two exceptions to that rule: the @size@ field, the type's size,
    214 is set using a @sizeof@ expression and the @align@ field, the
     214is set using a @sizeof@ expression, and the @align@ field, the
    215215type's alignment, is set using an @alignof@ expression.
    216216
    217217Most of these tools are already inside the compiler. Using simple
    218 code transformations early on in compilation, allows most of that work to be
     218code transformations early on in compilation allows most of that work to be
    219219handed off to the existing tools. \autoref{f:VirtualTableTransformation}
    220 shows an example transformation, this example shows an exception virtual table.
     220shows an example transformation; this example shows an exception virtual table.
    221221It also shows the transformation on the full declaration.
    222222For a forward declaration, the @extern@ keyword is preserved and the
     
    312312        struct __cfavir_type_id * const * child );
    313313\end{cfa}
    314 The type id for the target type of the virtual cast is passed in as
     314The type ID for the target type of the virtual cast is passed in as
    315315@parent@ and
    316316the cast target is passed in as @child@.
     
    322322The virtual cast either returns the original pointer or the null pointer
    323323as the new type.
    324 So the function does the parent check and returns the appropriate value.
    325 The parent check is a simple linear search of child's ancestors using the
     324The function does the parent check and returns the appropriate value.
     325The parent check is a simple linear search of the child's ancestors using the
    326326type information.
    327327
     
    329329% The implementation of exception types.
    330330
    331 Creating exceptions can roughly divided into two parts,
     331Creating exceptions can be roughly divided into two parts:
    332332the exceptions themselves and the virtual system interactions.
    333333
     
    361361
    362362All types associated with a virtual type,
    363 the types of the virtual table and the type id,
     363the types of the virtual table and the type ID,
    364364are generated when the virtual type (the exception) is first found.
    365 The type id (the instance) is generated with the exception, if it is
     365The type ID (the instance) is generated with the exception, if it is
    366366a monomorphic type.
    367 However, if the exception is polymorphic, then a different type id has to
     367However, if the exception is polymorphic, then a different type ID has to
    368368be generated for every instance. In this case, generation is delayed
    369369until a virtual table is created.
     
    372372When a virtual table is created and initialized, two functions are created
    373373to fill in the list of virtual members.
    374 The first is a copy function that adapts the exception's copy constructor
     374The first is the @copy@ function that adapts the exception's copy constructor
    375375to work with pointers, avoiding some issues with the current copy constructor
    376376interface.
    377 Second is the msg function that returns a C-string with the type's name,
     377Second is the @msg@ function that returns a C-string with the type's name,
    378378including any polymorphic parameters.
    379379
     
    402402
    403403% Discussing multiple frame stack unwinding:
    404 Unwinding across multiple stack frames is more complex because that
     404Unwinding across multiple stack frames is more complex, because that
    405405information is no longer contained within the current function.
    406406With separate compilation,
    407407a function does not know its callers nor their frame layout.
    408408Even using the return address, that information is encoded in terms of
    409 actions in code, intermixed with the actions required finish the function.
     409actions in code, intermixed with the actions required to finish the function.
    410410Without changing the main code path it is impossible to select one of those
    411411two groups of actions at the return site.
    412412
    413 The traditional unwinding mechanism for C is implemented by saving a snap-shot
    414 of a function's state with @setjmp@ and restoring that snap-shot with
     413The traditional unwinding mechanism for C is implemented by saving a snapshot
     414of a function's state with @setjmp@ and restoring that snapshot with
    415415@longjmp@. This approach bypasses the need to know stack details by simply
    416 reseting to a snap-shot of an arbitrary but existing function frame on the
    417 stack. It is up to the programmer to ensure the snap-shot is valid when it is
    418 reset and that all required clean-up from the unwound stacks is performed.
     416reseting to a snapshot of an arbitrary but existing function frame on the
     417stack. It is up to the programmer to ensure the snapshot is valid when it is
     418reset and that all required cleanup from the unwound stacks is performed.
    419419This approach is fragile and requires extra work in the surrounding code.
    420420
    421421With respect to the extra work in the surrounding code,
    422 many languages define clean-up actions that must be taken when certain
    423 sections of the stack are removed. Such as when the storage for a variable
     422many languages define cleanup actions that must be taken when certain
     423sections of the stack are removed, such as when the storage for a variable
    424424is removed from the stack, possibly requiring a destructor call,
    425425or when a try statement with a finally clause is
    426426(conceptually) popped from the stack.
    427 None of these cases should be handled by the user --- that would contradict the
    428 intention of these features --- so they need to be handled automatically.
     427None of these cases should be handled by the user -- that would contradict the
     428intention of these features -- so they need to be handled automatically.
    429429
    430430To safely remove sections of the stack, the language must be able to find and
    431 run these clean-up actions even when removing multiple functions unknown at
     431run these cleanup actions even when removing multiple functions unknown at
    432432the beginning of the unwinding.
    433433
     
    529529provided storage object. It has two public fields: the @exception_class@,
    530530which is described above, and the @exception_cleanup@ function.
    531 The clean-up function is used by the EHM to clean-up the exception, if it
     531The cleanup function is used by the EHM to clean up the exception. If it
    532532should need to be freed at an unusual time, it takes an argument that says
    533533why it had to be cleaned up.
     
    551551of the most recent stack frame. It continues to call personality functions
    552552traversing the stack from newest to oldest until a function finds a handler or
    553 the end of the stack is reached. In the latter case, raise exception returns
    554 @_URC_END_OF_STACK@.
    555 
    556 Second, when a handler is matched, raise exception moves to the clean-up
    557 phase and walks the stack a second time.
     553the end of the stack is reached. In the latter case,
     554@_Unwind_RaiseException@ returns @_URC_END_OF_STACK@.
     555
     556Second, when a handler is matched, @_Unwind_RaiseException@
     557moves to the cleanup phase and walks the stack a second time.
    558558Once again, it calls the personality functions of each stack frame from newest
    559559to oldest. This pass stops at the stack frame containing the matching handler.
    560 If that personality function has not install a handler, it is an error.
    561 
    562 If an error is encountered, raise exception returns either
     560If that personality function has not installed a handler, it is an error.
     561
     562If an error is encountered, @_Unwind_RaiseException@ returns either
    563563@_URC_FATAL_PHASE1_ERROR@ or @_URC_FATAL_PHASE2_ERROR@ depending on when the
    564564error occurred.
     
    571571        _Unwind_Stop_Fn, void *);
    572572\end{cfa}
    573 It also unwinds the stack but it does not use the search phase. Instead another
     573It also unwinds the stack but it does not use the search phase. Instead,
     574another
    574575function, the stop function, is used to stop searching. The exception is the
    575 same as the one passed to raise exception. The extra arguments are the stop
     576same as the one passed to @_Unwind_RaiseException@.
     577The extra arguments are the stop
    576578function and the stop parameter. The stop function has a similar interface as a
    577579personality function, except it is also passed the stop parameter.
     
    721723one list per stack, with the
    722724list head stored in the exception context. Within each linked list, the most
    723 recently thrown exception is at the head followed by older thrown
     725recently thrown exception is at the head, followed by older thrown
    724726exceptions. This format allows exceptions to be thrown, while a different
    725727exception is being handled. The exception at the head of the list is currently
     
    732734exception into managed memory. After the exception is handled, the free
    733735function is used to clean up the exception and then the entire node is
    734 passed to free, returning the memory back to the heap.
     736passed to @free@, returning the memory back to the heap.
    735737
    736738\subsection{Try Statements and Catch Clauses}
     
    757759The three functions passed to try terminate are:
    758760\begin{description}
    759 \item[try function:] This function is the try block, it is where all the code
     761\item[try function:] This function is the try block. It is where all the code
    760762from inside the try block is placed. It takes no parameters and has no
    761763return value. This function is called during regular execution to run the try
     
    766768from the conditional part of each handler and runs each check, top to bottom,
    767769in turn, to see if the exception matches this handler.
    768 The match is performed in two steps, first a virtual cast is used to check
     770The match is performed in two steps: first, a virtual cast is used to check
    769771if the raised exception is an instance of the declared exception type or
    770772one of its descendant types, and then the condition is evaluated, if
    771773present.
    772774The match function takes a pointer to the exception and returns 0 if the
    773 exception is not handled here. Otherwise the return value is the id of the
     775exception is not handled here. Otherwise, the return value is the ID of the
    774776handler that matches the exception.
    775777
     
    782784\end{description}
    783785All three functions are created with GCC nested functions. GCC nested functions
    784 can be used to create closures,
     786can be used to create closures;
    785787in other words,
    786 functions that can refer to variables in their lexical scope even
     788functions that can refer to variables in their lexical scope even though
    787789those variables are part of a different function.
    788790This approach allows the functions to refer to all the
     
    869871At each node, the EHM checks to see if the try statement the node represents
    870872can handle the exception. If it can, then the exception is handled and
    871 the operation finishes, otherwise the search continues to the next node.
     873the operation finishes; otherwise, the search continues to the next node.
    872874If the search reaches the end of the list without finding a try statement
    873875with a handler clause
     
    879881if the exception is handled and false otherwise.
    880882The handler function checks each of its internal handlers in order,
    881 top-to-bottom, until it funds a match. If a match is found that handler is
     883top-to-bottom, until it finds a match. If a match is found that handler is
    882884run, after which the function returns true, ignoring all remaining handlers.
    883885If no match is found the function returns false.
    884 The match is performed in two steps, first a virtual cast is used to see
     886The match is performed in two steps. First a virtual cast is used to see
    885887if the raised exception is an instance of the declared exception type or one
    886 of its descendant types, if so then it is passed to the custom predicate
     888of its descendant types, if so, then the second step is to see if the
     889exception passes the custom predicate
    887890if one is defined.
    888891% You need to make sure the type is correct before running the predicate
     
    936939% Recursive Resumption Stuff:
    937940\autoref{f:ResumptionMarking} shows search skipping
    938 (see \vpageref{s:ResumptionMarking}), which ignores parts of
     941(see \autoref{s:ResumptionMarking}), which ignores parts of
    939942the stack
    940943already examined, and is accomplished by updating the front of the list as
     
    951954This structure also supports new handlers added while the resumption is being
    952955handled. These are added to the front of the list, pointing back along the
    953 stack --- the first one points over all the checked handlers ---
     956stack -- the first one points over all the checked handlers --
    954957and the ordering is maintained.
    955958
     
    979982%\autoref{code:cleanup}
    980983A finally clause is handled by converting it into a once-off destructor.
    981 The code inside the clause is placed into GCC nested-function
     984The code inside the clause is placed into a GCC nested-function
    982985with a unique name, and no arguments or return values.
    983986This nested function is
    984987then set as the cleanup function of an empty object that is declared at the
    985988beginning of a block placed around the context of the associated try
    986 statement (see \autoref{f:FinallyTransformation}).
     989statement, as shown in \autoref{f:FinallyTransformation}.
    987990
    988991\begin{figure}
     
    10241027% Stack selections, the three internal unwind functions.
    10251028
    1026 Cancellation also uses libunwind to do its stack traversal and unwinding,
    1027 however it uses a different primary function: @_Unwind_ForcedUnwind@. Details
    1028 of its interface can be found in the Section~\vref{s:ForcedUnwind}.
     1029Cancellation also uses libunwind to do its stack traversal and unwinding.
     1030However, it uses a different primary function: @_Unwind_ForcedUnwind@. Details
     1031of its interface can be found in Section~\vref{s:ForcedUnwind}.
    10291032
    10301033The first step of cancellation is to find the cancelled stack and its type:
Note: See TracChangeset for help on using the changeset viewer.