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.! |
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
|
Free forum by Nabble | Edit this page |