Skip to content

Commit

Permalink
Fix integer packing in C code generation.
Browse files Browse the repository at this point in the history
- Pack integers into new arrays instead of packing in place, to avoid
  segfaults when passing integer array literals to external functions.

Belonging to [master]:
  - OpenModelica/OMCompiler#2994
  • Loading branch information
perost authored and OpenModelica-Hudson committed Mar 25, 2019
1 parent 72fdfb4 commit 89078f5
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 16 deletions.
33 changes: 17 additions & 16 deletions Compiler/Template/CodegenCFunctions.tpl
Expand Up @@ -2197,7 +2197,9 @@ template extFunCallVardecl(SimExtArg arg, Text &varDecls, Text &auxFunction, Boo
case SIMEXTARG(isInput = true, isArray = true, type_ = ty, cref = c) then
match expTypeShort(ty)
case "integer" then
'pack_integer_array(&<%contextCref(c,contextFunction,&auxFunction)%>);<%\n%>'
let var_name = '<%contextCref(c, contextFunction, &auxFunction)%>'
let &varDecls += 'integer_array <%var_name%>_packed;<%\n%>'
'pack_alloc_integer_array(&<%var_name%>, &<%var_name%>_packed);<%\n%>'
else ""
case SIMEXTARG(isInput = false, isArray = true, type_ = ty, cref = c) then
match expTypeShort(ty)
Expand All @@ -2223,7 +2225,7 @@ template extFunCallVardecl(SimExtArg arg, Text &varDecls, Text &auxFunction, Boo
else
let &varDecls += '<%extType(ty,true,false,false)%> <%extVarName(c)%>;<%\n%>'
<<
<%extVarName(c)%> = (<%extType(ty,true,false,false)%>)<%match ty case T_COMPLEX(complexClassType=RECORD(__)) then "&" else ""%><%contextCref(c,contextFunction,&auxFunction)%>;
<%extVarName(c)%> = (<%extType(ty,true,false,false)%>)<%match ty case T_COMPLEX(complexClassType=RECORD(__)) then "&" else ""%><%contextCref(c,contextFunction,&auxFunction)%>;<%\n%>
>>
case SIMEXTARG(outputIndex=oi, isArray=false, type_=ty, cref=c) then
match oi case 0 then
Expand Down Expand Up @@ -2319,20 +2321,17 @@ template extFunCallVarcopy(SimExtArg arg, Text &auxFunction)
"Helper to extFunCall."
::=
match arg
case SIMEXTARG(isInput = true, isArray = true, type_ = ty, cref = c) then
// Inputs that have been packed should be unpacked after the external call.
match expTypeShort(ty)
case "integer" then
'unpack_integer_array(&<%contextCref(c,contextFunction,&auxFunction)%>);'
else ""
case SIMEXTARG(outputIndex=0) then ""
case SIMEXTARG(outputIndex=oi, isArray=true, cref=c, type_=ty) then
case SIMEXTARG(outputIndex=oi, isInput=isInput, isArray=true, cref=c, type_=ty) then
let var_name = contextCref(c, contextFunction, &auxFunction)
match expTypeShort(ty)
case "integer" then
'unpack_integer_array(&<%contextCref(c,contextFunction,&auxFunction)%>);'
case "string" then
'unpack_string_array(&<%contextCref(c,contextFunction,&auxFunction)%>, <%contextCref(c,contextFunction,&auxFunction)%>_c89);'
else ""
case "integer" then
if isInput then
'unpack_copy_integer_array(&<%var_name%>_packed, &<%var_name%>);'
else
'unpack_integer_array(&<%var_name%>);'
case "string" then 'unpack_string_array(&<%var_name%>, <%var_name%>_c89);'
else ""
case SIMEXTARG(outputIndex=oi, isArray=false, type_=ty, cref=c) then
let cr = '<%extVarName(c)%>'
<<
Expand Down Expand Up @@ -2365,11 +2364,13 @@ template extArg(SimExtArg extArg, Text &preExp, Text &varDecls, Text &auxFunctio
"Helper to extFunCall."
::=
match extArg
case SIMEXTARG(cref=c, outputIndex=oi, isArray=true, type_=t) then
case SIMEXTARG(cref=c, outputIndex=oi, isArray=true, type_=t, isInput=isInput) then
let name = contextCref(c,contextFunction,&auxFunction)
let shortTypeStr = expTypeShort(t)
let &varDecls += 'void *<%name%>_c89;<%\n%>'
let &preExp += '<%name%>_c89 = (void*) data_of_<%shortTypeStr%>_c89_array(&(<%name%>));<%\n%>'
//let arg_name = match shortTypeStr case "integer" then '<%name%>_packed' else name
let arg_name = if isInput then (match shortTypeStr case "integer" then '<%name%>_packed' else name) else name
let &preExp += '<%name%>_c89 = (void*) data_of_<%shortTypeStr%>_c89_array(&(<%arg_name%>));<%\n%>'
'(<%extType(t,isInput,true,false)%>) <%name%>_c89'
case SIMEXTARG(cref=c, isInput=ii, outputIndex=0, type_=t) then
let cr = match t case T_STRING(__) then contextCref(c,contextFunction,&auxFunction) else extVarName(c)
Expand Down
50 changes: 50 additions & 0 deletions SimulationRuntime/c/util/integer_array.c
Expand Up @@ -1600,6 +1600,56 @@ void unpack_integer_array(integer_array_t *a)
}
}

/* Returns a modelica_integer array that can be treated as an int array. If the
* size of int and modelica_integer is the same this means simply returning the
* given array, but if int is smaller than modelica_integer a new array is
* allocated and filled with the data from given array as if it was an int array.
*
* I.e. if int is 32 bit and modelica_integer is 64 bit then the data will be
* packed into the first half of the new array.
*
* The case where int is larger than modelica_integer is not implemented. */
void pack_alloc_integer_array(integer_array_t *a, integer_array_t *dest)
{
if (sizeof(int) == sizeof(modelica_integer)) {
*dest = *a;
} else {
/* We only handle the case where int is smaller than modelica_integer. */
omc_assert_macro(sizeof(int) < sizeof(modelica_integer));

/* Allocate a new array. */
clone_integer_array_spec(a, dest);
alloc_integer_array_data(dest);

/* Pretend that the new array is an int array and fill it with the values
* from the given array. */
int *int_data = (int*)dest->data;
long i;
size_t n = base_array_nr_of_elements(*a);

for (i = 0; i < n; ++i) {
int_data[i] = (int)integer_get(*a, i);
}
}
}

/* Unpacks an integer_array that was packed with pack_integer_array into the
* destination array. If packing hasn't been done, i.e. if the size of int and
* modelica_integer is the same, then the function does nothing since both the
* source and destination is assumed to be the same array. */
void unpack_copy_integer_array(const integer_array_t *a, integer_array_t *dest)
{
if(sizeof(int) != sizeof(modelica_integer)) {
long i;
const int * int_data = (const int*)a->data;
long n = (long)base_array_nr_of_elements(*a);

for(i = n - 1; i >= 0; --i) {
integer_set(dest, i, int_data[i]);
}
}
}

void convert_alloc_integer_array_to_f77(const integer_array_t * a,
integer_array_t* dest)
{
Expand Down
2 changes: 2 additions & 0 deletions SimulationRuntime/c/util/integer_array.h
Expand Up @@ -279,6 +279,8 @@ extern void convert_alloc_integer_array_from_f77(const integer_array_t * a,

void pack_integer_array(integer_array_t *a);
void unpack_integer_array(integer_array_t *a);
void pack_alloc_integer_array(integer_array_t *a, integer_array_t *dest);
void unpack_copy_integer_array(const integer_array_t *a, integer_array_t *dest);

/* Note: data_of_integer_array converts from integer_array to int*, for external functions only */
static inline int* data_of_integer_array(const integer_array_t *a)
Expand Down

0 comments on commit 89078f5

Please sign in to comment.