VM Maker: VMMaker.oscog-eem.2775.mcz

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

VM Maker: VMMaker.oscog-eem.2775.mcz

commits-2
 
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2775.mcz

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

Name: VMMaker.oscog-eem.2775
Author: eem
Time: 16 July 2020, 4:10:20.53343 pm
UUID: 5277c7af-b6e2-42b2-879d-eab85ff574c2
Ancestors: VMMaker.oscog-eem.2774

ThreadedFFIPlugin: Add primitiveCDataModel which with 0 args answers the C data model name (LLP64, ILP32 et al), and with a ByteArray arg of 9 elements, answers the sizes of char, short, etc, & wchar_t.
Add ThreadedFFIPluginPartialSimulator to test the above primitive.  Hence implement InterpreterProxy>>deny: & stringForCString:.

Slang:
Fix a bug with the struct name cache (somehow I lost the updates to the methods that loaded the cache, which should have been changed to send ensureStructTypeCache).  Rename ensureStructTypeNameCache to ensureStructTypeCache to match voidStructTypeCache.
Allow TMethod>>typeFor:in: to infer tpes for non-integral constants (integral constants need very special handling, done in the client).
Eliminate unnecessary parentheses in ifNil:.

=============== Diff against VMMaker.oscog-eem.2774 ===============

Item was changed:
  ----- Method: CCodeGenerator>>generateIfNil:on:indent: (in category 'C translation') -----
  generateIfNil: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
 
  (self isNilConstantReceiverOf: msgNode)
  ifFalse:
+ [aStream nextPutAll: 'if (!!'.
+ self emitCExpression: msgNode receiver on: aStream indent: level + 1.
+ aStream nextPutAll: ') {'; cr.
- [aStream nextPutAll: 'if (!!('.
- msgNode receiver emitCCodeAsExpressionOn: aStream level: level + 1 generator: self.
- aStream nextPutAll: ')) {'; cr.
  msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
  aStream tab: level; nextPut: $}]
  ifTrue:
  [msgNode args first emitCCodeOn: aStream level: level generator: self]!

Item was added:
+ ----- Method: InterpreterProxy>>deny: (in category 'testing') -----
+ deny: aBooleanOrBlock
+ aBooleanOrBlock value ifTrue: [AssertionFailure signal: 'Assertion failed']!

Item was changed:
  ----- Method: InterpreterProxy>>stringForCString: (in category 'testing') -----
  stringForCString: aCString
  "Answer a ByteString object containing the bytes (possibly UTF-8?) in the null-terminated C string aCString."
  <option: #(atLeastVMProxyMajor:minor: 1 14)>
  <returnTypeC: #sqInt>
  <var: #aCString type: #'char *'>
+ self assert: aCString isString.
+ ^aCString!
- self notYetImplemented!

Item was changed:
  ----- Method: TConstantNode>>typeOrNilFrom:in: (in category 'type inference') -----
  typeOrNilFrom: aCodeGenerator in: aTMethod
  "For integers, answer int unless the value does not fit into a 32bits signed int.
  In that case, answer the shortest architecture independant integer type that could hold the constant.
  This method must be consistent with CCodeGenerator>>cLiteralFor:"
  | hb |
  value isInteger
  ifTrue:
  [value positive
  ifTrue:
  [hb := value highBit.
  hb < 32 ifTrue: [^#int].
  hb = 32 ifTrue: [^#'unsigned int'].
  hb = 64 ifTrue: [^#'unsigned long long'].
  ^#'long long']
  ifFalse:
  [hb := value bitInvert highBit.
  hb < 32 ifTrue: [^#int].
  ^#'long long']].
  value isFloat ifTrue: [^#double].
+ (#(nil true false) includes: value) ifTrue: [^#sqInt]. "A machine word sized variable is better on 64-bits than int, we think."
- (#(nil true false) includes: value) ifTrue: [^#int].
  (value isString and: [value isSymbol not]) ifTrue: [^#'char *'].
  ^nil!

Item was changed:
  ----- Method: TMethod>>typeFor:in: (in category 'utilities') -----
+ typeFor: aVariableOrConstantOrVariableNameString in: aCodeGen
- typeFor: aVariable in: aCodeGen
  "Answer the type for aVariable, deferring to aCodeGen (which defers to the vmClass)
  if no type is found and the variable is global (not an arg or a local).  Expect the
  cCodeGen to answer nil for variables without types. nil for typelessness is required
  by the type propagation logic in inlineSend:directReturn:exitVar:in:."
  | varName |
+ aVariableOrConstantOrVariableNameString isString ifFalse:
+ ["N.B. Very important *not* to type integers, to allow the client to do the work of merging various integer types."
+ (aVariableOrConstantOrVariableNameString isConstant
+  and: [aVariableOrConstantOrVariableNameString value isInteger not]) ifTrue:
+ [^aVariableOrConstantOrVariableNameString typeOrNilFrom: aCodeGen in: self]].
+ varName := aVariableOrConstantOrVariableNameString asString.
- varName := aVariable asString.
  ^(declarations
  at: varName
  ifAbsent:
  [(args includes: varName) "arg types default to sqInt"
  ifTrue: ['sqInt ', varName]
  ifFalse:
  [(locals includes: varName) ifFalse: "don't provide type for locals"
  [aCodeGen typeOfVariable: varName]]]) ifNotNil:
  [:decl|
  aCodeGen extractTypeFor: varName fromDeclaration: decl]!

Item was added:
+ ----- Method: ThreadedFFIPlugin>>primitiveCDataModel (in category 'primitives') -----
+ primitiveCDataModel
+ "Two forms of C Data Model infomation.
+ With 0 arguments answer the string naming the C data model, LP32, LP64, LLP64, etc.
+ WIth 1 argument, which must be a ByteArray of at least 9 elements, answer the sizes of
+ char, short, int, long, long long, wchar_t, float, double, void *."
+ <export: true>
+ | errorCode model |
+ interpreterProxy methodArgumentCount = 1 ifTrue:
+ [| sizes |
+ sizes := interpreterProxy stackValue: 0.
+ ((interpreterProxy isBytes: sizes)
+ and: [(interpreterProxy slotSizeOf: sizes) = 9]) ifFalse:
+ [^interpreterProxy primitiveFailFor: PrimErrBadArgument].
+ (self cCoerceSimple: (interpreterProxy firstIndexableField: sizes) to: #'char *')
+ at: 0 put: (self sizeof: #char);
+ at: 1 put: (self sizeof: #short);
+ at: 2 put: (self sizeof: #int);
+ at: 3 put: (self sizeof: #long);
+ at: 4 put: (self sizeof: #'long long');
+ at: 5 put: (self sizeof: #wchar_t);
+ at: 6 put: (self sizeof: #float);
+ at: 7 put: (self sizeof: #double);
+ at: 8 put: (self sizeof: #'void *').
+ ^interpreterProxy methodReturnValue: sizes].
+
+ interpreterProxy methodArgumentCount = 0 ifFalse:
+ [^interpreterProxy primitiveFailFor: PrimErrBadNumArgs].
+
+ "Attempt to identify the programming model:
+   LP32    ILP32    LLP64   LP64    ILP64  SILP64(unidentified)
+ char 8 8  8 8 8 8
+
+ short 16 16 16 16 16 64
+
+ int 16 32 32 32 64 64
+
+ long 32 32 32 64 64 64
+
+ long long 64 64 64 64 64 64
+
+ pointer 32 32 64 64 64 64"
+
+ errorCode := 0. "Set bit 0 if char is wrong, bit 1 if short is wrong, 2 for int, 3 for long, 4 for long long, 5 for void *"
+ (self sizeof: #char) ~= 1 ifTrue:
+ [errorCode := errorCode + 1].
+ (self sizeof: #short) ~= 2 ifTrue: "N.B. SILP64 exists on Cray supercomputers; we don't care..."
+ [errorCode := errorCode + 2].
+ (self sizeof: #'long long') ~= 8 ifTrue:
+ [errorCode := errorCode + 16].
+
+ (self sizeof: #'void *') = 8 ifTrue: "LP64 LLP64 ILP64"
+ [(self sizeof: #int) = 8 ifTrue: "ILP64"
+ [(self sizeof: #long) = 8
+ ifTrue: [model := 'ILP64']
+ ifFalse: [errorCode := errorCode + 8]].
+ (self sizeof: #int) = 4 ifTrue: "LP64 or LLP64"
+ [(self sizeof: #long) = 8 ifTrue: "LP64"
+ [model := 'LP64'].
+ (self sizeof: #long) = 4 ifTrue: "LLP64"
+ [model := 'LLP64'].
+ ((self sizeof: #long) ~= 8 and: [(self sizeof: #long) ~= 4]) ifTrue:
+ [errorCode := errorCode + 8]].
+ ((self sizeof: #int) ~= 8 and: [(self sizeof: #int) ~= 4]) ifTrue:
+ [errorCode := errorCode + 4]].
+
+ (self sizeof: #'void *') = 4 ifTrue: "LP32 ILP32"
+ [(self sizeof: #long) ~= 4 ifTrue:
+ [errorCode := errorCode + 8].
+ (self sizeof: #int) = 4 ifTrue: "ILP32"
+ [model := 'ILP32'].
+ (self sizeof: #int) = 2 ifTrue: "LP32"
+ [model := 'LP32'].
+ ((self sizeof: #int) ~= 4 and: [(self sizeof: #int) ~= 2]) ifTrue:
+ [errorCode := errorCode + 4]].
+
+ ((self sizeof: #'void *') ~= 8 and: [(self sizeof: #'void *') ~= 4]) ifTrue:
+ [errorCode := errorCode + 32].
+
+ errorCode ~= 0 ifTrue:
+ [^interpreterProxy primitiveFailForOSError: errorCode].
+ model ifNil:
+ [^interpreterProxy primitiveFailFor: PrimErrNotFound].
+ interpreterProxy methodReturnString: model
+
+ "Screed for testing
+ | proxy plugin |
+ proxy := InterpreterProxy new.
+ plugin := ThreadedFFIPluginPartialSimulator new.
+ plugin sizes: (Dictionary newFromPairs: #(char 1 short 2 int 4 long 4 #'long long' 8 #'void *' 8  #'void *' 4 float 4 double 8 wchar_t 4)).
+ plugin sizes: (Dictionary newFromPairs: #(char 1 short 2 int 2 long 4 #'long long' 8 #'void *' 4 float 4 double 8 wchar_t 4)).
+ plugin instVarNamed: 'interpreterProxy' put: proxy.
+ proxy synthesizeStackFor: plugin with: (Array with: (ByteArray new: 9)).
+ plugin primitiveCDataModel.
+ ^proxy stackValue: 0"!

Item was added:
+ ThreadedFFIPlugin subclass: #ThreadedFFIPluginPartialSimulator
+ instanceVariableNames: 'sizes'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'VMMaker-Plugins-FFI'!
+
+ !ThreadedFFIPluginPartialSimulator commentStamp: 'eem 7/16/2020 12:22' prior: 0!
+ A ThreadedFFIPluginPartialSimulator exists to test a few primitives such as primitiveCProgrammingModel.
+
+ Instance Variables
+ sizes a Dictionary of sizes for sizeof:!

Item was added:
+ ----- Method: ThreadedFFIPluginPartialSimulator>>sizeof: (in category 'simulation support') -----
+ sizeof: aType
+ ^sizes
+ ifNil: [super sizeof: aType]
+ ifNotNil: [sizes at: aType]!

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

Item was added:
+ ----- Method: ThreadedFFIPluginPartialSimulator>>sizes: (in category 'accessing') -----
+ sizes: anObject
+
+ sizes := anObject.!

Item was added:
+ ----- Method: VMStructType class>>ensureStructTypeCache (in category 'translation') -----
+ ensureStructTypeCache
+ ^StructTypeNameCache ifNil:
+ [StructTypeNameCache := Set new.
+ self allSubclassesDo:
+ [:sc| sc addStructTypeNamesTo: StructTypeNameCache].
+ StructTypeNameCache]!

Item was removed:
- ----- Method: VMStructType class>>ensureStructTypeNameCache (in category 'translation') -----
- ensureStructTypeNameCache
- ^StructTypeNameCache ifNil:
- [StructTypeNameCache := Set new.
- self allSubclassesDo:
- [:sc| sc addStructTypeNamesTo: StructTypeNameCache].
- StructTypeNameCache]!

Item was changed:
  ----- Method: VMStructType class>>isTypePointerToStruct: (in category 'translation') -----
  isTypePointerToStruct: type
  | index |
  ^type notNil
   and: [(index := type indexOf: $*) > 0
+  and: [self ensureStructTypeCache anySatisfy:
-  and: [self ensureStructTypeNameCache anySatisfy:
  [:structType|
  (type beginsWith: structType)
  and: [index > structType size]]]]!

Item was changed:
  ----- Method: VMStructType class>>isTypeStruct: (in category 'translation') -----
  isTypeStruct: type
+ self ensureStructTypeCache.
- StructTypeNameCache ifNil:
- [StructTypeNameCache := Set new.
- self allSubclassesDo:
- [:sc| StructTypeNameCache add: sc name; add: sc structTypeName]].
  ^type notNil
   and: [StructTypeNameCache anySatisfy:
  [:structType|
  type = structType]]!

Item was changed:
  ----- Method: VMStructType class>>structTargetKindForDeclaration: (in category 'translation') -----
  structTargetKindForDeclaration: decl
  ^(decl notNil
+   and: [(self ensureStructTypeCache includes: decl)
-   and: [(self ensureStructTypeNameCache includes: decl)
  or: [StructTypeNameCache anySatisfy:
  [:structType|
  (decl beginsWith: structType)
  and: [(decl indexOf: $* ifAbsent: [decl indexOf: Character space]) > structType size]]]]) ifTrue:
  [(decl indexOf: $*) > 0
  ifTrue: [#pointer]
  ifFalse: [#struct]]!

Item was changed:
  ----- Method: VMStructType class>>structTargetKindForType: (in category 'translation') -----
  structTargetKindForType: type
+ self ensureStructTypeCache.
- StructTypeNameCache ifNil:
- [StructTypeNameCache := Set new.
- self allSubclassesDo:
- [:sc| StructTypeNameCache add: sc name; add: sc structTypeName ]].
  ^(type notNil
    and: [StructTypeNameCache anySatisfy:
  [:structType|
  (type beginsWith: structType)
  and: [type size = structType size
  or: [(type at: structType size + 1) isAlphaNumeric not]]]]) ifTrue:
  [(type includes: $*)
  ifTrue: [#pointer]
  ifFalse: [#struct]]!