From b68b5dd18b0dfdd130e815ee7495c289c246bd6c Mon Sep 17 00:00:00 2001 From: heck Date: Thu, 1 Jun 2023 11:37:59 +0200 Subject: [PATCH] Add the C language mapping specification --- README.md | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..4de4424 --- /dev/null +++ b/README.md @@ -0,0 +1,239 @@ + +* [pEpACIDLang - C Language Mapping](#pepacidlang---c-language-mapping) + * [About This Document](#about-this-document) + * [IDL-Types](#idl-types) + * [Type Classes](#type-classes) + * [IDL-Type Mapping To C](#idl-type-mapping-to-c) + * [Creation and Destruction](#creation-and-destruction) + * [Primitive Types](#primitive-types) + * [Object Types](#object-types) + * [Allocators](#allocators) + * [Destructors](#destructors) + * [Method Parameters](#method-parameters) + * [Rules For Parameter Allocation](#rules-for-parameter-allocation) + * [Parameter Passing Modes](#parameter-passing-modes) + * [Mapping Table for C](#mapping-table-for-c) + * [Rules For Parameters Of Primitive-Type](#rules-for-parameters-of-primitive-type) + * [Rules For Parameters Of Object-Type](#rules-for-parameters-of-object-type) + * [Read](#read) + * [Update](#update) + * [Consume](#consume) + * [Produce](#produce) + * [Rules For Multithreading](#rules-for-multithreading) + + +# pEpACIDLang - C Language Mapping + +pEpACIDLang stands for "pEp Abstract C Interface Description Language". + +pEpACIDLang is language to describe a programming interface. +'Abstract', because the interfaces defined in pEpACIDLang are agnostic to the target language. +A concrete interface and client code using the interface can be generated in any language where: +* a language mapping specification +* a interface generator + +exists for. +The interface generator implements parts of the language mapping specification. +'C' because the syntax and some concepts are based on the C language. +The current problem at hand is to replace a handwritten C API with a pEpACIDlang generated one. + +This is the document specifying the language mapping for C. + +## About This Document + +State: Draft, to be reviewed with fdik and positron. + +**ATTENTION, IMPORTANT** +In this document, all types expressed as T are the IDL-types, not their corresponding c-types. +An example for clarity: +If `T` is the type `string`, the IDL-type `string` is meant, so the c-type of `T*` is `char**`. + +Usually a variable typename is expressed as `T`. But sometimes `T` is being used to refer to an instance of type `T`. +This imprecision is used for brevity, but only where the context does not allow for an ambiguity. + +## IDL-Types + +### Type Classes + +There are only two type-classes. + +* Primitive Types +* Object Types + +### IDL-Type Mapping To C + +| Type-Class | IDL-Type | C-Type | +|------------|-----------|--------------| +| Primitive | int | int | +| Primitive | uint | unsigned int | +| Primitive | size | size_t | +| Primitive | bool | bool | +| Primitive | enum | enum | +| Object | struct | struct* | +| Object | string | char* | +| Object | binary | char* | +| Object | opaque | void* | +| Object | list | list_T* | +| Object | pair | pair_F_S* | + +### Creation and Destruction + +#### Primitive Types + +* Primitive types are always statically allocated +* Primitive types are trivially constructable and destroyable +* All storage classes (auto/static/extern/register) are allowed + +#### Object Types + +For any object-type `T`, corresponding `new` and `free` methods are being generated. + +To create an object of type `T` correctly, there are two ways: + +1. Using its allocator-method +2. Using any method that has a parameter of type `T` with mode `Produce` + +To destroy an object of type `T` correctly, the only way is to use its destructor-method. + +##### Allocators + +The allocator-method has the signature: +`IDL_STATUS new_T(T*)` + +* The memory for `T` has to be dynamically allocated +* An empty object is being created. Any object-types reachable through `T` are pointing to `NULL`. + +Result: +STATUS_OK - `T*` is pointing to a valid object +STATUS_ERROR - Dereferencing of `T*` is undefined behaviour + +##### Destructors + +The destructor-method has the signature: +`IDL_STATUS free_T(T*)` + +1. For all object-type members of `T` itself, their respective destructor-methods are being called +2. The memory for `T` is freed compatibly to how it was allocated using its allocator-method +3. `T*` is set to `NULL` + +Result: +STATUS_OK - All memory reachable through `T*` is freed and `T*` is NULL +STATUS_ERROR - FATAL (most implementations of `free()` can guarantee this will never happen) + +## Method Parameters + +The main concerns when sharing memory (e.g. in form of parameters) are: + +* Ownership: defined as who is allowed and responsible to destroy an object. +* Mutability: Who is allowed to change the contents of the memory location that is known to several parties. + +In environments where memory management is explicit, the lifecycle of data in memory is: + +1. Memory being allocated +2. Memory being shared with producers/consumers (e.g. as a parameter Read/Update/Consume) +3. Read/write operations by multiple parties (needs synchronization if multithreaded environment) +3. Make sure this memory will never be accessed again by nobody +4. Memory has to be freed exactly once and compatible to how it was allocated + +Every such lifecycle must be completed. +All of this must be guaranteed. + +### Rules For Parameter Allocation + +Parameters have to be allocated as follows: + +* Primitive-types: The general rules outlined under [Creation and Destruction](#creation-and-destruction) apply +* Object-types: Using the allocator- and destructor-methods outlined under [Creation and Destruction](#creation-and-destruction) + +These rules apply regardless of the parameter passing mode. + +### Parameter Passing Modes + +The modes are named by describing what the callee does, from the perspective of the callee, using one verb. + +* `Read` - Immutable, ownership remains with caller +* `Update` - Mutable, ownership remains with caller +* `Consume` - Mutable, ownership goes to callee +* `Produce` - Immutable, ownership goes to caller + +#### Mapping Table for C + +Type of `T` as a function of type-class and mode. +Where `T` any of the respective IDL-Types (not their respective c-type, as mentioned in [About This Document](#about-this-document)). + +| Mode/Type-Class | READ | UPDATE | CONSUME | PRODUCE | +|------------------|------|--------|---------|---------| +| Primitive | T | T* | - (1) | - (1) | +| Object | T | T* | T | T* | + +#### Rules For Parameters Of Primitive-Type + +The caller has to allocate memory for `T`. +For mode `Update`, the callee is allowed to mutate the memory pointed to by `T*`. +(1) A primitive-type cannot be consumed or produced because it's always statically allocated. + +#### Rules For Parameters Of Object-Type + +##### Read + +The caller has to guarantee that either-or: + +* `T` is `NULL` +* `T` is pointing to a valid object of type `*T` (allocated as defined under 'Rules For Parameter Allocation') + This guarantee applies transitively for all object-type members of `*T`. + +The callee is not allowed to mutate or free any memory that can be reached through `T`. +The caller is responsible to free all the memory that can be reached through `T`. + +##### Update + +The caller has to guarantee that: + +* All object-types reachable through `T*` are either `NULL` or pointing to a valid object + (allocated as defined under [Rules For Parameter Allocation](#rules-for-parameter-allocation)) + +The callee is allowed to mutate the object in two ways: + +1. Mutate any primitive-types reachable through `T*` +2. Free or replace any object-types reachable trough `T*` + +The callee has to guarantee, that upon return of the method: + +* `T*` is pointing to a valid `*T` (allocated as defined under [Rules For Parameter Allocation](#rules-for-parameter-allocation)) +* All object-type members reachable through `T*` are either `NULL` or pointing to a valid object of type `*T` (allocated as + defined under [Rules For Parameter Allocation](#rules-for-parameter-allocation)) + +Upon success of the method call: +The caller must replace all pointers to `*T` and to any of its transitive members by dereferencing `T*` and its respective +transitive members. +The caller must free `T` and any of its transitive members. + +TODO: Upon any failure of the method call: + +##### Consume + +The same rules for mode `Read` apply, with the exception that the caller has to guarantee to never access `T` again in +any way. + +##### Produce + +The caller is allowed to pass a `T*` with an undefined value. +TODO... + +#### Rules For Multithreading + +These rules apply to all memory that can be accessed through a parameter. +Such memory must be allocated in the calling thread No such memory can be shared with other +TODO.... + + + + + + + + + + + +