FFI Inbox: FFI-Kernel-mt.78.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

FFI Inbox: FFI-Kernel-mt.78.mcz

commits-2
A new version of FFI-Kernel was added to project FFI Inbox:
http://source.squeak.org/FFIinbox/FFI-Kernel-mt.78.mcz

==================== Summary ====================

Name: FFI-Kernel-mt.78
Author: mt
Time: 29 May 2020, 4:18:42.331595 pm
UUID: 1d41e42b-d401-5e41-8bb8-bec2813972e0
Ancestors: FFI-Kernel-mt.77

Proposal to store type information for C code generation in FFI's atomic types.

An alternative would be to add two new tables as class variables -- just like AtomicTypeNames -- to not increase the size of ExternalType instances. I am not familiar with the implementation of the FFI plugin in the osvm. So this is just a guess. :-)

(Also see my question about byte alignment here: http://forum.world.st/FFI-Byte-alignment-tp5117408.html --- I discarded the dead code path in this proposal already.)

=============== Diff against FFI-Kernel-mt.77 ===============

Item was changed:
  Object subclass: #ExternalType
+ instanceVariableNames: 'compiledSpec referentClass referencedType pointerSize byteAlignment cTypeName cFormatPlaceholder'
- instanceVariableNames: 'compiledSpec referentClass referencedType pointerSize byteAlignment'
  classVariableNames: 'AtomicSelectors AtomicTypeNames AtomicTypes StructTypes'
  poolDictionaries: 'FFIConstants'
  category: 'FFI-Kernel'!
 
  !ExternalType commentStamp: 'eem 6/25/2019 10:39' prior: 0!
  An external type represents the type of external objects.
 
  Instance variables:
  compiledSpec <WordArray> Compiled specification of the external type
  referentClass <Behavior | nil> Class type of argument required
  referencedType <ExternalType> Associated (non)pointer type with the receiver
  pointerSize <Integer | nil> The size of a pointer if the external type is a pointer or is a structure containing a pointer.
  byteAlignment <Integer | nil> The desired alignment for a field of the external type within a structure.  If nil it has yet to be computed.
 
  Compiled Spec:
  The compiled spec defines the type in terms which are understood by the VM. Each word is defined as:
  bits 0...15 - byte size of the entity
  bit 16 - structure flag (FFIFlagStructure)
   This flag is set if the following words define a structure
  bit 17 - pointer flag (FFIFlagPointer)
   This flag is set if the entity represents a pointer to another object
  bit 18 - atomic flag (FFIFlagAtomic)
   This flag is set if the entity represents an atomic type.
   If the flag is set the atomic type bits are valid.
  bits 19...23 - unused
  bits 24...27 - atomic type (FFITypeVoid ... FFITypeDoubleFloat)
  bits 28...31 - unused
 
  Note that all combinations of the flags FFIFlagPointer, FFIFlagAtomic, and FFIFlagStructure are invalid, EXCEPT from the following:
 
  FFIFlagPointer + FFIFlagAtomic:
  This defines a pointer to an atomic type (e.g., 'char*', 'int*').
  The actual atomic type is represented in the atomic type bits.
 
  FFIFlagPointer + FFIFlagStructure:
  This defines a structure which is a typedef of a pointer type as in
  typedef void* VoidPointer;
  typedef Pixmap* PixmapPtr;
  It requires a byte size of four or eight (e.g. a 32-bit or 64-bit pointer) to work correctly.
 
  [Note: Other combinations may be allowed in the future]
  !

Item was changed:
  ----- Method: ExternalType class>>initializeAtomicTypes (in category 'class initialization') -----
  initializeAtomicTypes
+ "For a discussion about long vs. int see http://forum.world.st/Re-squeak-dev-64-bit-FFI-was-porting-Croquet-to-Squeak6-0-alpha-tp5113318.html."
+
  "ExternalType initialize"
+ | atomicType byteSize type typeName byteAlignment cTypeName cFormatPlaceholder |
- | atomicType byteSize type typeName byteAlignment |
  #(
+ "name atomic id byte size byte alignment C type name C printf % format"
+ ('void' 0 0 0 'void' 'p')
+ ('bool' 1 1 1 'int' 'd')
+ ('byte' 2 1 1 'unsigned char' 'hhu') "Not 'c' to avoid conversion issues"
+ ('sbyte' 3 1 1 'signed char' 'hhd') "Not 'c' to avoid conversion issues"
+ ('ushort' 4 2 2 'unsigned short' 'hu')
+ ('short' 5 2 2 'signed short' 'hd')
+ "!!!!!!" ('ulong' 6 4 "!!!!!!" 4 'unsigned int' 'u') "Not 'lu' bc. not unsigned long, see above"
+ "!!!!!!" ('long' 7 4 "!!!!!!" 4 'signed int' 'd') "Not 'ld' bc. not signed long, see above"
+ ('ulonglong' 8 8 8 'unsigned long long' 'llu')
+ ('longlong' 9 8 8 'signed long long' 'lld')
+ ('char' 10 1 1 'unsigned char' 'hhu') "Not 'c' to avoid conversion issues"
+ ('schar' 11 1 1 'signed char' 'hhd') "Not 'c' to avoid conversion issues"
+ ('float' 12 4 4 'float' 'g') "Not 'G' bc. notation in lowercase letters"
+ ('double' 13 8 8 'double' 'g') "Not 'G' bc. notation in lowercase letters"
+ "TODO: ('longdouble' 14 10 16? 4? 'long double' 'Lg')"
- "name atomic id byte size byte alignment"
- ('void' 0 0 0)
- ('bool' 1 1 1)
- ('byte' 2 1 1)
- ('sbyte' 3 1 1)
- ('ushort' 4 2 2)
- ('short' 5 2 2)
- ('ulong' 6 4 4)
- ('long' 7 4 4)
- ('ulonglong' 8 8 8)
- ('longlong' 9 8 8)
- ('char' 10 1 1)
- ('schar' 11 1 1)
- ('float' 12 4 4)
- ('double' 13 8 8)
  ) do:[:typeSpec| | compiled |
  typeName := typeSpec first.
  atomicType := typeSpec second.
  byteSize := typeSpec third.
  byteAlignment := typeSpec fourth.
+ cTypeName := typeSpec fifth.
+ cFormatPlaceholder := typeSpec sixth.
+
+ "1) Regular type form"
- "On 32 bits Windows and MacOS, double and long have an alignment of 8. But on Linux, their alignment is 4"
- (FFIPlatformDescription current wordSize = 4 and: [FFIPlatformDescription current isUnix]) ifTrue: [
- (#('double longlong ulonglong') includes: typeName) ifTrue: [
- byteAlignment := 4
- ]
- ].
  compiled := WordArray with: ((byteSize bitOr: FFIFlagAtomic) bitOr:
  (atomicType bitShift: FFIAtomicTypeShift)).
  type := (AtomicTypes at: typeName).
+ type
+ compiledSpec: compiled;
+ byteAlignment: byteAlignment;
+ cTypeName: cTypeName;
+ cFormatPlaceholder: '%', cFormatPlaceholder.
+
+ "2) Pointer type form"
- type compiledSpec: compiled;
- byteAlignment: byteAlignment.
  compiled := WordArray with: ((self pointerSpec bitOr: FFIFlagAtomic) bitOr:
  (atomicType bitShift: FFIAtomicTypeShift)).
  type asPointerType
  byteAlignment: self pointerAlignment;
+ compiledSpec: compiled;
+ cTypeName: cTypeName, ' *';
+ cFormatPlaceholder: '%p'.
+
- compiledSpec: compiled.
  ].!

Item was added:
+ ----- Method: ExternalType>>cFormatPlaceholder (in category 'accessing') -----
+ cFormatPlaceholder
+
+ ^ cFormatPlaceholder!

Item was added:
+ ----- Method: ExternalType>>cFormatPlaceholder: (in category 'accessing') -----
+ cFormatPlaceholder: aString
+
+ cFormatPlaceholder := aString.!

Item was added:
+ ----- Method: ExternalType>>cTypeName (in category 'accessing') -----
+ cTypeName
+
+ ^ cTypeName!

Item was added:
+ ----- Method: ExternalType>>cTypeName: (in category 'accessing') -----
+ cTypeName: aString
+
+ cTypeName := aString.!


Reply | Threaded
Open this post in threaded view
|

Re: FFI Inbox: FFI-Kernel-mt.78.mcz

marcel.taeumel
I think I withdraw this proposal. C stuff would be better off in a class that could safely be unloaded after all external shared pools are installed. To save resources on the target platform if required.

Best,
Marcel

Am 29.05.2020 16:18:52 schrieb [hidden email] <[hidden email]>:

A new version of FFI-Kernel was added to project FFI Inbox:
http://source.squeak.org/FFIinbox/FFI-Kernel-mt.78.mcz

==================== Summary ====================

Name: FFI-Kernel-mt.78
Author: mt
Time: 29 May 2020, 4:18:42.331595 pm
UUID: 1d41e42b-d401-5e41-8bb8-bec2813972e0
Ancestors: FFI-Kernel-mt.77

Proposal to store type information for C code generation in FFI's atomic types.

An alternative would be to add two new tables as class variables -- just like AtomicTypeNames -- to not increase the size of ExternalType instances. I am not familiar with the implementation of the FFI plugin in the osvm. So this is just a guess. :-)

(Also see my question about byte alignment here: http://forum.world.st/FFI-Byte-alignment-tp5117408.html --- I discarded the dead code path in this proposal already.)

=============== Diff against FFI-Kernel-mt.77 ===============

Item was changed:
Object subclass: #ExternalType
+ instanceVariableNames: 'compiledSpec referentClass referencedType pointerSize byteAlignment cTypeName cFormatPlaceholder'
- instanceVariableNames: 'compiledSpec referentClass referencedType pointerSize byteAlignment'
classVariableNames: 'AtomicSelectors AtomicTypeNames AtomicTypes StructTypes'
poolDictionaries: 'FFIConstants'
category: 'FFI-Kernel'!

!ExternalType commentStamp: 'eem 6/25/2019 10:39' prior: 0!
An external type represents the type of external objects.

Instance variables:
compiledSpec Compiled specification of the external type
referentClass Class type of argument required
referencedType Associated (non)pointer type with the receiver
pointerSize The size of a pointer if the external type is a pointer or is a structure containing a pointer.
byteAlignment The desired alignment for a field of the external type within a structure. If nil it has yet to be computed.

Compiled Spec:
The compiled spec defines the type in terms which are understood by the VM. Each word is defined as:
bits 0...15 - byte size of the entity
bit 16 - structure flag (FFIFlagStructure)
This flag is set if the following words define a structure
bit 17 - pointer flag (FFIFlagPointer)
This flag is set if the entity represents a pointer to another object
bit 18 - atomic flag (FFIFlagAtomic)
This flag is set if the entity represents an atomic type.
If the flag is set the atomic type bits are valid.
bits 19...23 - unused
bits 24...27 - atomic type (FFITypeVoid ... FFITypeDoubleFloat)
bits 28...31 - unused

Note that all combinations of the flags FFIFlagPointer, FFIFlagAtomic, and FFIFlagStructure are invalid, EXCEPT from the following:

FFIFlagPointer + FFIFlagAtomic:
This defines a pointer to an atomic type (e.g., 'char*', 'int*').
The actual atomic type is represented in the atomic type bits.

FFIFlagPointer + FFIFlagStructure:
This defines a structure which is a typedef of a pointer type as in
typedef void* VoidPointer;
typedef Pixmap* PixmapPtr;
It requires a byte size of four or eight (e.g. a 32-bit or 64-bit pointer) to work correctly.

[Note: Other combinations may be allowed in the future]
!

Item was changed:
----- Method: ExternalType class>>initializeAtomicTypes (in category 'class initialization') -----
initializeAtomicTypes
+ "For a discussion about long vs. int see http://forum.world.st/Re-squeak-dev-64-bit-FFI-was-porting-Croquet-to-Squeak6-0-alpha-tp5113318.html."
+
"ExternalType initialize"
+ | atomicType byteSize type typeName byteAlignment cTypeName cFormatPlaceholder |
- | atomicType byteSize type typeName byteAlignment |
#(
+ "name atomic id byte size byte alignment C type name C printf % format"
+ ('void' 0 0 0 'void' 'p')
+ ('bool' 1 1 1 'int' 'd')
+ ('byte' 2 1 1 'unsigned char' 'hhu') "Not 'c' to avoid conversion issues"
+ ('sbyte' 3 1 1 'signed char' 'hhd') "Not 'c' to avoid conversion issues"
+ ('ushort' 4 2 2 'unsigned short' 'hu')
+ ('short' 5 2 2 'signed short' 'hd')
+ "!!!!!!" ('ulong' 6 4 "!!!!!!" 4 'unsigned int' 'u') "Not 'lu' bc. not unsigned long, see above"
+ "!!!!!!" ('long' 7 4 "!!!!!!" 4 'signed int' 'd') "Not 'ld' bc. not signed long, see above"
+ ('ulonglong' 8 8 8 'unsigned long long' 'llu')
+ ('longlong' 9 8 8 'signed long long' 'lld')
+ ('char' 10 1 1 'unsigned char' 'hhu') "Not 'c' to avoid conversion issues"
+ ('schar' 11 1 1 'signed char' 'hhd') "Not 'c' to avoid conversion issues"
+ ('float' 12 4 4 'float' 'g') "Not 'G' bc. notation in lowercase letters"
+ ('double' 13 8 8 'double' 'g') "Not 'G' bc. notation in lowercase letters"
+ "TODO: ('longdouble' 14 10 16? 4? 'long double' 'Lg')"
- "name atomic id byte size byte alignment"
- ('void' 0 0 0)
- ('bool' 1 1 1)
- ('byte' 2 1 1)
- ('sbyte' 3 1 1)
- ('ushort' 4 2 2)
- ('short' 5 2 2)
- ('ulong' 6 4 4)
- ('long' 7 4 4)
- ('ulonglong' 8 8 8)
- ('longlong' 9 8 8)
- ('char' 10 1 1)
- ('schar' 11 1 1)
- ('float' 12 4 4)
- ('double' 13 8 8)
) do:[:typeSpec| | compiled |
typeName := typeSpec first.
atomicType := typeSpec second.
byteSize := typeSpec third.
byteAlignment := typeSpec fourth.
+ cTypeName := typeSpec fifth.
+ cFormatPlaceholder := typeSpec sixth.
+
+ "1) Regular type form"
- "On 32 bits Windows and MacOS, double and long have an alignment of 8. But on Linux, their alignment is 4"
- (FFIPlatformDescription current wordSize = 4 and: [FFIPlatformDescription current isUnix]) ifTrue: [
- (#('double longlong ulonglong') includes: typeName) ifTrue: [
- byteAlignment := 4
- ]
- ].
compiled := WordArray with: ((byteSize bitOr: FFIFlagAtomic) bitOr:
(atomicType bitShift: FFIAtomicTypeShift)).
type := (AtomicTypes at: typeName).
+ type
+ compiledSpec: compiled;
+ byteAlignment: byteAlignment;
+ cTypeName: cTypeName;
+ cFormatPlaceholder: '%', cFormatPlaceholder.
+
+ "2) Pointer type form"
- type compiledSpec: compiled;
- byteAlignment: byteAlignment.
compiled := WordArray with: ((self pointerSpec bitOr: FFIFlagAtomic) bitOr:
(atomicType bitShift: FFIAtomicTypeShift)).
type asPointerType
byteAlignment: self pointerAlignment;
+ compiledSpec: compiled;
+ cTypeName: cTypeName, ' *';
+ cFormatPlaceholder: '%p'.
+
- compiledSpec: compiled.
].!

Item was added:
+ ----- Method: ExternalType>>cFormatPlaceholder (in category 'accessing') -----
+ cFormatPlaceholder
+
+ ^ cFormatPlaceholder!

Item was added:
+ ----- Method: ExternalType>>cFormatPlaceholder: (in category 'accessing') -----
+ cFormatPlaceholder: aString
+
+ cFormatPlaceholder := aString.!

Item was added:
+ ----- Method: ExternalType>>cTypeName (in category 'accessing') -----
+ cTypeName
+
+ ^ cTypeName!

Item was added:
+ ----- Method: ExternalType>>cTypeName: (in category 'accessing') -----
+ cTypeName: aString
+
+ cTypeName := aString.!