Opened 6 years ago

Closed 6 years ago

#5134 closed defect (fixed)

Record as argument to external function is not passed by reference

Reported by: c.schulze@… Owned by: Adrian Pop
Priority: high Milestone: 1.13.0
Component: Code Generation Version:
Keywords: Cc:

Description

The Modelica Specification clearly states "Records are passed by reference (i.e. a pointer to the record is being passed)."

However, OpenModelica passes the record/struct instance instead of a pointer to the instance.

Attachments (1)

RecordPassedToFunction.mo (572 bytes ) - added by c.schulze@… 6 years ago.

Download all attachments as: .zip

Change History (6)

by c.schulze@…, 6 years ago

Attachment: RecordPassedToFunction.mo added

comment:1 by Francesco Casella, 6 years ago

Component: *unknown*Code Generation
Milestone: Future1.13.0
Owner: changed from somebody to Lennart Ochel

comment:2 by Adrian Pop, 6 years ago

Owner: changed from Lennart Ochel to Adrian Pop
Status: newaccepted

comment:3 by Adrian Pop, 6 years ago

I thought this was an easy fix via PR:
https://github.com/OpenModelica/OMCompiler/pull/2674
which fixed this model, *but* it doesn't seem so as
it breaks one model in our testsuite.
Spec says:

If there is a single output parameter and no explicit call of the external function, 
or if there is an explicit external call in the form of an equation, in which case the 
LHS must be one of the output parameters, the external routine is assumed to be a 
value-returning function. The element type T of an array can be any simple type as defined in Section 12.9.1.1 or, for C, a record type is returned as a value of the record type defined in Section 12.9.1.3.

So it seems we need more exceptions for the handling of the return from external functions.

If I get this right these are the cases:

// 1. no explicit call
// return structure, pass input by reference
// extern struct PLUS mk_plus_ext(struct ADD*, struct ADD*)
function mk_plus_ext
  input ADD left;
  input ADD right;
  output PLUS out;
  external "C" annotation(Library="blah");
end mk_plus_ext;

// 2. explicit call
// return structure, pass by reference
// extern struct PLUS mk_plus_ext(struct ADD*, struct ADD*)
function mk_plus_ext
  input ADD left;
  input ADD right;
  output PLUS out;
  external "C" out = ext(left, right) annotation(Library="blah");
end mk_plus_ext;

// 3. pass output by reference, explicitely
// pass by reference, including the output
// extern void mk_plus_ext(struct PLUS*, struct ADD*, struct ADD*)
function mk_plus_ext
  input ADD left;
  input ADD right;
  output PLUS out;
  external "C" ext(out, left, right) annotation(Library="blah");
end mk_plus_ext;

in reply to:  3 comment:4 by Francesco Casella, 6 years ago

Replying to adrpo:

If I get this right these are the cases:

// 1. no explicit call
// return structure, pass input by reference
// extern struct PLUS mk_plus_ext(struct ADD*, struct ADD*)
function mk_plus_ext
  input ADD left;
  input ADD right;
  output PLUS out;
  external "C" annotation(Library="blah");
end mk_plus_ext;

// 2. explicit call
// return structure, pass by reference
// extern struct PLUS mk_plus_ext(struct ADD*, struct ADD*)
function mk_plus_ext
  input ADD left;
  input ADD right;
  output PLUS out;
  external "C" out = ext(left, right) annotation(Library="blah");
end mk_plus_ext;

// 3. pass output by reference, explicitely
// pass by reference, including the output
// extern void mk_plus_ext(struct PLUS*, struct ADD*, struct ADD*)
function mk_plus_ext
  input ADD left;
  input ADD right;
  output PLUS out;
  external "C" ext(out, left, right) annotation(Library="blah");
end mk_plus_ext;

I double-checked and it seems to me this is correct. The whole thing is horribly complicated, maybe it should have been made simpler, but it's too late to change that now, alas.

comment:5 by Adrian Pop, 6 years ago

Resolution: fixed
Status: acceptedclosed

Fixed with 0cdd3e/OMCompiler.
More tests added with: 4b2bcb/OpenModelica-testsuite.

Note: See TracTickets for help on using tickets.