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

Encoding for Flexible Array Members #62

Open
keynmol opened this issue Mar 16, 2022 · 2 comments
Open

Encoding for Flexible Array Members #62

keynmol opened this issue Mar 16, 2022 · 2 comments
Labels
enhancement New feature or request

Comments

@keynmol
Copy link
Contributor

keynmol commented Mar 16, 2022

Which I've just found out are a thing and I don't like it: https://en.wikipedia.org/wiki/Flexible_array_member

They shouldn't have any effect on sizeof or alignment, I think. We can just pretend that they don't exist and let the user manually allocate such monstrosity

Or lift it as a usable type, and provide an allocator for such length

This is the sort of thing that will crash during generation:

typedef struct sdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
} sdshdr5;
@keynmol keynmol added the enhancement New feature or request label Mar 16, 2022
@keynmol
Copy link
Contributor Author

keynmol commented Jul 10, 2023

Given that the C standard does not specify any field that constitutes length (and in fact the example above uses 5 bits from the char field to indicate length).

The only option I see at this point is providing a helper function such as this:

opaque type FAM[T, A] = Long

def flexibleArrayMemberData[T <: CStruct, A](struct: Ptr[T])(using fam: FAM[T, A]): Ptr[A] = 
   (struct + fam).asInstanceOf[A]

Just need to check that the inference works on that correctly, if you just pass the argument without any parameters.

and we generate (for the example above) an inline instance of FAM in the struct's companion:

inline given FAM[sdshdr5, CChar] = sizeOf[sdshdr5] 

@keynmol
Copy link
Contributor Author

keynmol commented Jul 10, 2023

Alternatively, no need to go crazy - the companion object can host those static functions.

Take this header:

struct vectord {
  char len;
  int length;
  double arr[];
};

Here's the encoding:

//> using platform scala-native

package libtest

import _root_.scala.scalanative.unsafe.*
import _root_.scala.scalanative.unsigned.*
import _root_.scala.scalanative.libc.*
import _root_.scala.scalanative.*
import libtest.structs.vectord

opaque type FAM[T <: CStruct, A] = CSize
object FAM:
  private[libtest] inline def apply[T <: CStruct, A](a: CSize): FAM[T,A] = 
    a.asInstanceOf

object structs:
  import _root_.libtest.structs.*

  /**
   * [bindgen] header: test.h
  */
  opaque type vectord = CStruct2[CChar, CInt]
  object vectord:
    given _tag: Tag[vectord] = Tag.materializeCStruct2Tag[CChar, CInt]
    def apply()(using Zone): Ptr[vectord] = scala.scalanative.unsafe.alloc[vectord](1)
    def apply(len : CChar, length : CInt)(using Zone): Ptr[vectord] = 
      val ____ptr = apply()
      (!____ptr).len = len
      (!____ptr).length = length
      ____ptr


    extension (struct: vectord)
      def len : CChar = struct._1
      def len_=(value: CChar): Unit = !struct.at1 = value
      def length : CInt = struct._2
      def length_=(value: CInt): Unit = !struct.at2 = value

    inline def fam(ptr: Ptr[vectord]): Ptr[Double] = 
      (ptr + sizeof[vectord]).asInstanceOf[Ptr[Double]]

    inline def applyWithFam(len: CChar, length: CInt)(famLength: Long)(using Zone): Ptr[vectord] =
      val ____rawptr = alloc[Byte](sizeof[vectord] + famLength.toULong * sizeof[Double])
      val ____ptr = ____rawptr.asInstanceOf[Ptr[vectord]]
      (!____ptr).len = len
      (!____ptr).length = length
      ____ptr


@main def hello = 
  Zone {implicit z =>
    val p = vectord.applyWithFam('h', 50)(50)
    val fam = vectord.fam(p)

    for 
      i <- 0 until (!p).length 
    do 
      fam(i) = i * 10.0
  }

Specifically the fam and applyWithFam methods

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

No branches or pull requests

1 participant