Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit 89078f5

Browse files
perostOpenModelica-Hudson
authored andcommitted
Fix integer packing in C code generation.
- Pack integers into new arrays instead of packing in place, to avoid segfaults when passing integer array literals to external functions. Belonging to [master]: - #2994
1 parent 72fdfb4 commit 89078f5

File tree

3 files changed

+69
-16
lines changed

3 files changed

+69
-16
lines changed

Compiler/Template/CodegenCFunctions.tpl

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2197,7 +2197,9 @@ template extFunCallVardecl(SimExtArg arg, Text &varDecls, Text &auxFunction, Boo
21972197
case SIMEXTARG(isInput = true, isArray = true, type_ = ty, cref = c) then
21982198
match expTypeShort(ty)
21992199
case "integer" then
2200-
'pack_integer_array(&<%contextCref(c,contextFunction,&auxFunction)%>);<%\n%>'
2200+
let var_name = '<%contextCref(c, contextFunction, &auxFunction)%>'
2201+
let &varDecls += 'integer_array <%var_name%>_packed;<%\n%>'
2202+
'pack_alloc_integer_array(&<%var_name%>, &<%var_name%>_packed);<%\n%>'
22012203
else ""
22022204
case SIMEXTARG(isInput = false, isArray = true, type_ = ty, cref = c) then
22032205
match expTypeShort(ty)
@@ -2223,7 +2225,7 @@ template extFunCallVardecl(SimExtArg arg, Text &varDecls, Text &auxFunction, Boo
22232225
else
22242226
let &varDecls += '<%extType(ty,true,false,false)%> <%extVarName(c)%>;<%\n%>'
22252227
<<
2226-
<%extVarName(c)%> = (<%extType(ty,true,false,false)%>)<%match ty case T_COMPLEX(complexClassType=RECORD(__)) then "&" else ""%><%contextCref(c,contextFunction,&auxFunction)%>;
2228+
<%extVarName(c)%> = (<%extType(ty,true,false,false)%>)<%match ty case T_COMPLEX(complexClassType=RECORD(__)) then "&" else ""%><%contextCref(c,contextFunction,&auxFunction)%>;<%\n%>
22272229
>>
22282230
case SIMEXTARG(outputIndex=oi, isArray=false, type_=ty, cref=c) then
22292231
match oi case 0 then
@@ -2319,20 +2321,17 @@ template extFunCallVarcopy(SimExtArg arg, Text &auxFunction)
23192321
"Helper to extFunCall."
23202322
::=
23212323
match arg
2322-
case SIMEXTARG(isInput = true, isArray = true, type_ = ty, cref = c) then
2323-
// Inputs that have been packed should be unpacked after the external call.
2324-
match expTypeShort(ty)
2325-
case "integer" then
2326-
'unpack_integer_array(&<%contextCref(c,contextFunction,&auxFunction)%>);'
2327-
else ""
23282324
case SIMEXTARG(outputIndex=0) then ""
2329-
case SIMEXTARG(outputIndex=oi, isArray=true, cref=c, type_=ty) then
2325+
case SIMEXTARG(outputIndex=oi, isInput=isInput, isArray=true, cref=c, type_=ty) then
2326+
let var_name = contextCref(c, contextFunction, &auxFunction)
23302327
match expTypeShort(ty)
2331-
case "integer" then
2332-
'unpack_integer_array(&<%contextCref(c,contextFunction,&auxFunction)%>);'
2333-
case "string" then
2334-
'unpack_string_array(&<%contextCref(c,contextFunction,&auxFunction)%>, <%contextCref(c,contextFunction,&auxFunction)%>_c89);'
2335-
else ""
2328+
case "integer" then
2329+
if isInput then
2330+
'unpack_copy_integer_array(&<%var_name%>_packed, &<%var_name%>);'
2331+
else
2332+
'unpack_integer_array(&<%var_name%>);'
2333+
case "string" then 'unpack_string_array(&<%var_name%>, <%var_name%>_c89);'
2334+
else ""
23362335
case SIMEXTARG(outputIndex=oi, isArray=false, type_=ty, cref=c) then
23372336
let cr = '<%extVarName(c)%>'
23382337
<<
@@ -2365,11 +2364,13 @@ template extArg(SimExtArg extArg, Text &preExp, Text &varDecls, Text &auxFunctio
23652364
"Helper to extFunCall."
23662365
::=
23672366
match extArg
2368-
case SIMEXTARG(cref=c, outputIndex=oi, isArray=true, type_=t) then
2367+
case SIMEXTARG(cref=c, outputIndex=oi, isArray=true, type_=t, isInput=isInput) then
23692368
let name = contextCref(c,contextFunction,&auxFunction)
23702369
let shortTypeStr = expTypeShort(t)
23712370
let &varDecls += 'void *<%name%>_c89;<%\n%>'
2372-
let &preExp += '<%name%>_c89 = (void*) data_of_<%shortTypeStr%>_c89_array(&(<%name%>));<%\n%>'
2371+
//let arg_name = match shortTypeStr case "integer" then '<%name%>_packed' else name
2372+
let arg_name = if isInput then (match shortTypeStr case "integer" then '<%name%>_packed' else name) else name
2373+
let &preExp += '<%name%>_c89 = (void*) data_of_<%shortTypeStr%>_c89_array(&(<%arg_name%>));<%\n%>'
23732374
'(<%extType(t,isInput,true,false)%>) <%name%>_c89'
23742375
case SIMEXTARG(cref=c, isInput=ii, outputIndex=0, type_=t) then
23752376
let cr = match t case T_STRING(__) then contextCref(c,contextFunction,&auxFunction) else extVarName(c)

SimulationRuntime/c/util/integer_array.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,56 @@ void unpack_integer_array(integer_array_t *a)
16001600
}
16011601
}
16021602

1603+
/* Returns a modelica_integer array that can be treated as an int array. If the
1604+
* size of int and modelica_integer is the same this means simply returning the
1605+
* given array, but if int is smaller than modelica_integer a new array is
1606+
* allocated and filled with the data from given array as if it was an int array.
1607+
*
1608+
* I.e. if int is 32 bit and modelica_integer is 64 bit then the data will be
1609+
* packed into the first half of the new array.
1610+
*
1611+
* The case where int is larger than modelica_integer is not implemented. */
1612+
void pack_alloc_integer_array(integer_array_t *a, integer_array_t *dest)
1613+
{
1614+
if (sizeof(int) == sizeof(modelica_integer)) {
1615+
*dest = *a;
1616+
} else {
1617+
/* We only handle the case where int is smaller than modelica_integer. */
1618+
omc_assert_macro(sizeof(int) < sizeof(modelica_integer));
1619+
1620+
/* Allocate a new array. */
1621+
clone_integer_array_spec(a, dest);
1622+
alloc_integer_array_data(dest);
1623+
1624+
/* Pretend that the new array is an int array and fill it with the values
1625+
* from the given array. */
1626+
int *int_data = (int*)dest->data;
1627+
long i;
1628+
size_t n = base_array_nr_of_elements(*a);
1629+
1630+
for (i = 0; i < n; ++i) {
1631+
int_data[i] = (int)integer_get(*a, i);
1632+
}
1633+
}
1634+
}
1635+
1636+
/* Unpacks an integer_array that was packed with pack_integer_array into the
1637+
* destination array. If packing hasn't been done, i.e. if the size of int and
1638+
* modelica_integer is the same, then the function does nothing since both the
1639+
* source and destination is assumed to be the same array. */
1640+
void unpack_copy_integer_array(const integer_array_t *a, integer_array_t *dest)
1641+
{
1642+
if(sizeof(int) != sizeof(modelica_integer)) {
1643+
long i;
1644+
const int * int_data = (const int*)a->data;
1645+
long n = (long)base_array_nr_of_elements(*a);
1646+
1647+
for(i = n - 1; i >= 0; --i) {
1648+
integer_set(dest, i, int_data[i]);
1649+
}
1650+
}
1651+
}
1652+
16031653
void convert_alloc_integer_array_to_f77(const integer_array_t * a,
16041654
integer_array_t* dest)
16051655
{

SimulationRuntime/c/util/integer_array.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ extern void convert_alloc_integer_array_from_f77(const integer_array_t * a,
279279

280280
void pack_integer_array(integer_array_t *a);
281281
void unpack_integer_array(integer_array_t *a);
282+
void pack_alloc_integer_array(integer_array_t *a, integer_array_t *dest);
283+
void unpack_copy_integer_array(const integer_array_t *a, integer_array_t *dest);
282284

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

0 commit comments

Comments
 (0)