Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/src/fr/hammons/slinc/Bytes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ object Bytes:
inline def %(b: Bytes): Bytes = a % b
inline def -(b: Bytes): Bytes = a - b
inline def >(b: Bytes): Boolean = a > b
inline def >=(b: Bytes): Boolean = a >= b
inline def toLong: Long = a
inline def toBits: Long = a * 8
def toSizeT = SizeT
Expand Down
37 changes: 37 additions & 0 deletions core/test/src/fr/hammons/slinc/modules/DescriptorSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import fr.hammons.slinc.types.CInt
import fr.hammons.slinc.types.CFloat
import fr.hammons.slinc.CUnion
import fr.hammons.slinc.Struct
import fr.hammons.slinc.ByteDescriptor
import fr.hammons.slinc.Bytes
import fr.hammons.slinc.ShortDescriptor
import fr.hammons.slinc.IntDescriptor
import fr.hammons.slinc.LongDescriptor
import fr.hammons.slinc.FloatDescriptor
import fr.hammons.slinc.DoubleDescriptor

trait DescriptorSpec(val slinc: Slinc) extends munit.FunSuite:
import slinc.dm
Expand All @@ -23,3 +30,33 @@ trait DescriptorSpec(val slinc: Slinc) extends munit.FunSuite:
DescriptorOf[CUnion[(CInt, A, CFloat)]].alignment,
DescriptorOf[A].alignment
)

test("ByteDescriptor is 1 byte in size"):
assertEquals(ByteDescriptor.size, Bytes(1))

test("ShortDescriptor is 2 bytes in size"):
assertEquals(ShortDescriptor.size, Bytes(2))

test("IntDescriptor is 4 bytes in size"):
assertEquals(IntDescriptor.size, Bytes(4))

test("LongDescriptor is 8 bytes in size"):
assertEquals(LongDescriptor.size, Bytes(8))

test("FloatDescriptor is 4 bytes in size"):
assertEquals(FloatDescriptor.size, Bytes(4))

test("DoubleDescriptor is 8 bytes in size"):
assertEquals(DoubleDescriptor.size, Bytes(8))

test("StructDescriptor.alignment is the max of the member elements"):
assertEquals(DescriptorOf[A].alignment, Bytes(8))

test("StructDescriptor.size is a multiple of alignment"):

assertEquals(DescriptorOf[A].size % DescriptorOf[A].alignment, Bytes(0))
assert(
DescriptorOf[A].size >= (DescriptorOf[CInt].size * 3 + DescriptorOf[
CLongLong
].size * 2)
)
63 changes: 26 additions & 37 deletions j17/src/fr/hammons/slinc/modules/DescriptorModule17.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,17 @@ package fr.hammons.slinc.modules

import fr.hammons.slinc.*

import jdk.incubator.foreign.CLinker.{
C_CHAR,
C_SHORT,
C_INT,
C_DOUBLE,
C_FLOAT,
C_LONG_LONG,
C_POINTER
}
import jdk.incubator.foreign.{
MemoryLayout,
MemoryAddress,
MemorySegment,
GroupLayout,
CLinker
}
CLinker,
ValueLayout
}, CLinker.C_POINTER
import scala.collection.concurrent.TrieMap
import fr.hammons.slinc.types.{arch, os, OS, Arch}
import fr.hammons.slinc.modules.platform.*

given descriptorModule17: DescriptorModule with
val chm: TrieMap[StructDescriptor, GroupLayout] = TrieMap.empty
Expand Down Expand Up @@ -69,26 +63,13 @@ given descriptorModule17: DescriptorModule with
else Seq.empty
)

override def sizeOf(td: TypeDescriptor): Bytes = td match
case ByteDescriptor => Bytes(1)
case ShortDescriptor => Bytes(2)
case IntDescriptor => Bytes(4)
case LongDescriptor => Bytes(8)
case FloatDescriptor => Bytes(4)
case DoubleDescriptor => Bytes(8)
case PtrDescriptor => Bytes(toMemoryLayout(PtrDescriptor).byteSize())
case sd: StructDescriptor =>
Bytes(toGroupLayout(sd).byteSize())
case VaListDescriptor => Bytes(toMemoryLayout(VaListDescriptor).byteSize())
case ad: AliasDescriptor[?] => sizeOf(ad.real)
case CUnionDescriptor(possibleTypes) => possibleTypes.map(sizeOf).max
override def sizeOf(td: TypeDescriptor): Bytes = Bytes(
toMemoryLayout(td).byteSize()
)

override def alignmentOf(td: TypeDescriptor): Bytes = td match
case s: StructDescriptor =>
s.members.view.map(_.descriptor).map(alignmentOf).max
case CUnionDescriptor(possibleTypes) =>
possibleTypes.view.map(alignmentOf).max
case _ => sizeOf(td)
override def alignmentOf(td: TypeDescriptor): Bytes = Bytes(
toMemoryLayout(td).byteAlignment
)

override def memberOffsets(sd: List[TypeDescriptor]): IArray[Bytes] =
offsets.getOrElseUpdate(
Expand Down Expand Up @@ -117,13 +98,21 @@ given descriptorModule17: DescriptorModule with
}
)

val platform = (os, arch) match
case (OS.Linux, Arch.X64) => x64.Linux
case (OS.Darwin, Arch.X64) => x64.Darwin
case (OS.Windows, Arch.X64) => x64.Windows
case (OS.Linux, Arch.AArch64) => aarch64.Linux
case (OS.Darwin, Arch.AArch64) => aarch64.Darwin
case _ => throw Error("Unsupported platform!")

def toMemoryLayout(td: TypeDescriptor): MemoryLayout = td match
case ByteDescriptor => C_CHAR.nn
case ShortDescriptor => C_SHORT.nn
case IntDescriptor => C_INT.nn
case LongDescriptor => C_LONG_LONG.nn
case FloatDescriptor => C_FLOAT.nn
case DoubleDescriptor => C_DOUBLE.nn
case ByteDescriptor => platform.jByte
case ShortDescriptor => platform.jShort
case IntDescriptor => platform.jInt
case LongDescriptor => platform.jLong
case FloatDescriptor => platform.jFloat
case DoubleDescriptor => platform.jDouble
case PtrDescriptor => C_POINTER.nn
case VaListDescriptor => C_POINTER.nn
case sd: StructDescriptor => toGroupLayout(sd)
Expand All @@ -138,7 +127,7 @@ given descriptorModule17: DescriptorModule with
chm.getOrElseUpdate(
sd, {
val originalMembers = sd.members.map(toMemoryLayout)
val alignment = alignmentOf(sd)
val alignment = Bytes(originalMembers.view.map(_.byteAlignment()).max)
MemoryLayout
.structLayout(genLayoutList(originalMembers, alignment)*)
.nn
Expand Down
11 changes: 11 additions & 0 deletions j17/src/fr/hammons/slinc/modules/platform/Platform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package fr.hammons.slinc.modules.platform

import jdk.incubator.foreign.ValueLayout
trait Platform {
val jByte: ValueLayout
val jShort: ValueLayout
val jInt: ValueLayout
val jLong: ValueLayout
val jFloat: ValueLayout
val jDouble: ValueLayout
}
20 changes: 20 additions & 0 deletions j17/src/fr/hammons/slinc/modules/platform/aarch64/Darwin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package fr.hammons.slinc.modules.platform.aarch64

import fr.hammons.slinc.modules.platform.Platform
import jdk.incubator.foreign.CLinker.{
C_CHAR,
C_DOUBLE,
C_FLOAT,
C_INT,
C_LONG,
C_SHORT
}
import jdk.incubator.foreign.ValueLayout

object Darwin extends Platform:
val jByte: ValueLayout = C_CHAR.nn
val jShort: ValueLayout = C_SHORT.nn
val jInt: ValueLayout = C_INT.nn
val jLong: ValueLayout = C_LONG.nn
val jFloat: ValueLayout = C_FLOAT.nn
val jDouble: ValueLayout = C_DOUBLE.nn
20 changes: 20 additions & 0 deletions j17/src/fr/hammons/slinc/modules/platform/aarch64/Linux.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package fr.hammons.slinc.modules.platform.aarch64

import fr.hammons.slinc.modules.platform.Platform
import jdk.incubator.foreign.CLinker.{
C_CHAR,
C_INT,
C_SHORT,
C_LONG,
C_FLOAT,
C_DOUBLE
}
import jdk.incubator.foreign.ValueLayout

object Linux extends Platform:
val jByte: ValueLayout = C_CHAR.nn
val jShort: ValueLayout = C_SHORT.nn
val jInt: ValueLayout = C_INT.nn
val jLong: ValueLayout = C_LONG.nn
val jFloat: ValueLayout = C_FLOAT.nn
val jDouble: ValueLayout = C_DOUBLE.nn
19 changes: 19 additions & 0 deletions j17/src/fr/hammons/slinc/modules/platform/x64/Darwin.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package fr.hammons.slinc.modules.platform.x64

import fr.hammons.slinc.modules.platform.Platform
import jdk.incubator.foreign.CLinker.{
C_CHAR,
C_DOUBLE,
C_FLOAT,
C_INT,
C_LONG,
C_SHORT
}

object Darwin extends Platform:
val jByte = C_CHAR.nn
val jShort = C_SHORT.nn
val jInt = C_INT.nn
val jLong = C_LONG.nn
val jFloat = C_FLOAT.nn
val jDouble = C_DOUBLE.nn
3 changes: 3 additions & 0 deletions j17/src/fr/hammons/slinc/modules/platform/x64/Linux.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package fr.hammons.slinc.modules.platform.x64

val Linux = Darwin
20 changes: 20 additions & 0 deletions j17/src/fr/hammons/slinc/modules/platform/x64/Windows.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package fr.hammons.slinc.modules.platform.x64

import fr.hammons.slinc.modules.platform.Platform
import jdk.incubator.foreign.CLinker.{
C_CHAR,
C_SHORT,
C_INT,
C_LONG_LONG,
C_FLOAT,
C_DOUBLE
}
import jdk.incubator.foreign.ValueLayout

object Windows extends Platform:
val jByte: ValueLayout = C_CHAR.nn
val jShort: ValueLayout = C_SHORT.nn
val jInt: ValueLayout = C_INT.nn
val jLong: ValueLayout = C_LONG_LONG.nn
val jFloat: ValueLayout = C_FLOAT.nn
val jDouble: ValueLayout = C_DOUBLE.nn
3 changes: 3 additions & 0 deletions j17/test/src/fr/hammons/slinc/LayoutSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package fr.hammons.slinc

class LayoutSpec {}
39 changes: 9 additions & 30 deletions j19/src/fr/hammons/slinc/modules/DescriptorModule19.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ given descriptorModule19: DescriptorModule with
.structLayout(
genLayoutList(
sd.members.map(toMemoryLayout),
alignmentOf(sd)
Bytes(
sd.members.view.map(toMemoryLayout).map(_.byteAlignment()).max
)
)*
)
.nn
Expand Down Expand Up @@ -115,33 +117,10 @@ given descriptorModule19: DescriptorModule with
}
)

override def sizeOf(td: TypeDescriptor): Bytes = td match
case ByteDescriptor => Bytes(1)
case ShortDescriptor => Bytes(2)
case IntDescriptor => Bytes(4)
case LongDescriptor => Bytes(8)
case FloatDescriptor => Bytes(4)
case DoubleDescriptor => Bytes(8)
case PtrDescriptor => Bytes(ValueLayout.ADDRESS.nn.byteSize())
case VaListDescriptor => Bytes(ValueLayout.ADDRESS.nn.byteSize())
case sd: StructDescriptor => Bytes(toGroupLayout(sd).byteSize())
case ad: AliasDescriptor[?] => sizeOf(ad.real)
case CUnionDescriptor(possibleTypes) => possibleTypes.view.map(sizeOf).max
override def sizeOf(td: TypeDescriptor): Bytes = Bytes(
toMemoryLayout(td).byteSize()
)

override def alignmentOf(td: TypeDescriptor): Bytes =
import java.lang.foreign.ValueLayout
td match
case ByteDescriptor => Bytes(1)
case ShortDescriptor => Bytes(2)
case IntDescriptor => Bytes(4)
case LongDescriptor => Bytes(8)
case FloatDescriptor => Bytes(4)
case DoubleDescriptor => Bytes(8)
case PtrDescriptor => Bytes(ValueLayout.ADDRESS.nn.byteAlignment())
case VaListDescriptor => Bytes(ValueLayout.ADDRESS.nn.byteSize())
case sd: StructDescriptor =>
sd.members.view.map(_.descriptor).map(alignmentOf).max
case ad: AliasDescriptor[?] =>
alignmentOf(ad.real)
case CUnionDescriptor(possibleTypes) =>
possibleTypes.view.map(alignmentOf).max
override def alignmentOf(td: TypeDescriptor): Bytes = Bytes(
toMemoryLayout(td).byteAlignment()
)