Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lostanza - passing/return struct by value in C #174

Open
callendorph opened this issue Nov 14, 2022 · 3 comments
Open

lostanza - passing/return struct by value in C #174

callendorph opened this issue Nov 14, 2022 · 3 comments

Comments

@callendorph
Copy link

In C - you can pass or return a defined struct by value from a function. For example - see the GSL complex math library.

I can't seem to work out how to do this in lostanza. It seems like lostanza is focused only on pointers. Do you have an example of using structures as values?

@OlegPliss
Copy link
Collaborator

This is a working code from current GC implementation passing and returning small structures by value:
`lostanza deftype LiveRange :
live:ptr
dead:ptr

;Write the live range r into the heap address at the given break location.
;
;Live ranges are stored directly in the heap memory, in the space
;currently occupied by dead objects: the breaks.
;
;The encoding varies depending upon the size of the break.
;The minimum size of a break is 8 bytes long, but the live range struct is
;in general 16 bytes long.
;
;Encoding:
;Case break >= 16 bytes: then just directly store the live range.
;Case break == 8 bytes: only store the 'dead' field, tagged with 1.
;
;Since heap addresses are always 8-byte aligned, the tagged 1 will tell us
;which encoding we are using.
lostanza defn write-live-range (location:ptr, r:LiveRange) -> ref :
;Case: break == 8 bytes.
if addr(location[1]) == r.live :
;Store the tagged 'dead' field.
location[0] = (r.dead as long) | 1
;Case: break >= 16 bytes.
else :
;Store the live range directly.
location[0] = r.live as long
location[1] = r.dead as long
;No meaningful return value
return false

;Read the live range at the given break location.
lostanza defn read-live-range (location:ptr) -> LiveRange :
;Read the first word at the location.
val location0 = location[0]
;Test the tag bit to determine which encoding we are using.
if location0 & 1L :
;Case break == 8 bytes.
val live = addr(location[1]) ;Computed from size of break.
val dead = (location0 - 1) as ptr ;Remove tag bit.
return LiveRange{live, dead}
else :
;Case break >= 16 bytes.
val live = location0 as ptr
val dead = location[1] as ptr
return LiveRange{live, dead}
`

@callendorph
Copy link
Author

Sorry - I should have been more specific with what I am trying to do. What I want to do is wrap GSL's complex value implementation. It passes a struct gsl_complex by value to and from functions in C.

The gsl_complex is a struct containing 2 doubles (128 bits). From what I can tell of call-c's calling convention - it can only assign to a value of a primitive type or a pointer (or at least that is what I have gathered from this document). Maybe I'm wrong on that account ?

It is not clear to me how I can use the LiveRange code here to make a call-c invokation of say gsl_complex_polar and get the resulting value as a lostanza deftype.

Below has gotten me the farthest towards my goal:

public lostanza deftype GComplex :
  x: double
  y: double

extern gsl_complex_polar : (double, double) -> GComplex

lostanza var r:GComplex

public lostanza defn GComplex (rad:ref<Double>, th:ref<Double>) -> ref<GComplex> :
  r = call-c gsl_complex_polar(rad.value, th.value)
  return new GComplex{r.x, r.y}

This sadly fails with FATAL ERROR: More than a single C return value!

Is there another way to do this ?

@CuppoJava
Copy link
Collaborator

Hi Carl,

What you are trying to do is reasonable, and is the way that it should (and will ultimately) be done. You're hitting a part of the compiler that is not-yet-implemented today: the C calling convention for structs.

Until that is finished, you have to write an additional C-wrapper that changes how gsl_complex_polar returns its results in order to connect to it.

Our apologies. It's on the near-term roadmap however!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants