Studio:Restrictions on discriminated unions

From STRIDE Wiki
Jump to navigation Jump to search

Beginning with STRIDE 2.1, there are restrictions in place for disciminated unions. These restrictions are diagnosed as errors by the SCL language translator if they are encountered.

Restrictions

Union/Discriminant Restriction #1
Union and Discriminant must reside in same payload

The discriminant for a discriminated union must be present in the Command Payload if the union is present in the Command Payload. The discriminant for a discriminated union must be present in the Respose Payload if the union is present in the Response Payload.

Union/Discriminant Restriction #2
Discriminant may not reside in a memory block that is a descendent of the block that contains the union

Within a payload (Command or Response), the discriminant may not reside in a payload memory block that is a descendent of the block in which the union resides. (See section 1.2.11 Payloads for a detailed description of memory blocks)

Union/Discriminant Restriction #3
Discriminant may not reside in a memory block that comes “after” the union

Within a payload (Command or Response), the discrimiminant may not reside in a memory block that comes after the block containing the union given a pre-order, left, right traversal of memory blocks that make up the payload.

Union/Discriminant Restriction #4
Union residing in OUT block may not have discriminant residing in RETURN or INRETURN block
Union/Discriminant Restriction #5
Union residing in INOUT block may not have discriminant that resides in INRETURN block

Rationale for the Restrictions

Restriction #1: To eliminate Restriction #1 the host runtime would need to capture and record discrimant values on a call so that on the corresponding return the values could recalled and used to discriminate the union value within the response payload (since the discriminant values cannot be found in the response payload).

Restrictions #2 thru #5 are in place because of the manner in which the host runtime processes I-blocks sent from target to host. The host runtime is designed to process each block fully before reading the next block. This means that the host runtime cannot handle the senario where the union resides in an I-block that arrives prior to the I-block containing the discriminant.

Examples

Restricted by #1:

typedef union U { int m1; int m2;} U;
U f(int d);
#pragma scl_function(f);
#pragma scl_union(f(), f.d);

Restricted by #1:

typedef union U { int m1; int m2;} U;
void f(int d, U* pu);
#pragma scl_function(f);
#pragma scl_union(*f.pu, f.d);
#pragma scl_ptr(f.pu, OUT, PRIVATE)

Restricted by #2:

typedef union U { int m1; int m2;} U;
typedef struct S
{
  int *pd;
  U   u;
}S;
void f(S s);
#pragma scl_function(f);
#pragma scl_union(f.s.u, *f.s.pd);

Restricted by #2:

typedef struct M1 { int *pd; int x;} M1;
typedef struct M2 { int *pd; int y;} M2;
typedef union U  { M1 m1; M2 m2;} U;
void f(U u);
#pragma scl_function(f);
#pragma scl_union(f.u, *f.u.m1.pd);

Restricted by #3:

typedef union U { int m1; int m2;} U;
void f(U* pu, int *pd);
#pragma scl_function(f);
#pragma scl_union(*f.pu, *f.pd)

NOT Restricted by #3 (or any other restriction)

typedef union U { int m1; int m2;} U;
void f(int *pd, U* pu);
#pragma scl_function(f);
#pragma scl_union(*f.pu, *f.pd)
</sourc>
==Restricted by #4==
<source lang="c">
typedef union U { int m1; int m2;} U;
void f(int **pd, U* pu);
#pragma scl_function(f)
#pragma scl_union(*f.pu, **f.pd)
#pragma scl_ptr(f.pu, OUT, PRIVATE)
#pragma scl_ptr(f.pd, OUT, PRIVATE)
#pragma scl_ptr(*f.pd, RETURN, POOL)

Restricted by #5

typedef union U { int m1; int m2;} U;
void f(int **pd, U* pu);
#pragma scl_function(f)
#pragma scl_union(*f.pu, **f.pd)
#pragma scl_ptr(f.pu, INOUT, PRIVATE)
#pragma scl_ptr(f.pd, INOUT, PRIVATE)
#pragma scl_ptr(*f.pd, INRETURN, POOL)