VM Maker: VMMaker.oscog-eem.2779.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.2779.mcz

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

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

Name: VMMaker.oscog-eem.2779
Author: eem
Time: 25 July 2020, 1:02:37.771342 pm
UUID: 69eafb1b-0a60-46f9-ad35-00f4a863fe8a
Ancestors: VMMaker.oscog-eem.2778

Slang:
Implement and support cppIf:ifTrue:cppIf:ifTrue:ifFalse: for ARMv8 cache flushing.  As a result of the changes to generateInlineCppIfElse:asArgument:on:indent: clean-up generating indents and terminating semicolons.  In particular don't add a trailing semicolo to a statement list when prepending, leaving it to the sender.
Clean up generating switches, avoiding emitting a bogus newline before hand, and a newline before break jumps.
Change generateV3RemapOopIn:on:indent: to terminate the last statement with a semicolon.

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

Item was changed:
  ----- Method: CCodeGenerator>>generateInlineCppIfElse:asArgument:on:indent: (in category 'C translation') -----
  generateInlineCppIfElse: msgNode asArgument: asArgument on: aStream indent: level
  "Generate the C code for this message onto the given stream."
+ | putStatement allAlternativesWereDeterminable expr pos |
- | expr putStatement |
  "Compile-time expansion for constants set in the options dictionary,
  e.g. to cut down on noise for MULTIPLEBYTECODESETS."
  putStatement := asArgument
  ifTrue: "emitCCodeAsArgumentOn: doesn't indent, the code needs indenting if it takes multiple lines, so post-process."
  [[:node| | expansion |
   expansion := String streamContents: [:s| node emitCCodeAsArgumentOn: s level: level generator: self].
   aStream nextPutAll:
   ((expansion includes: Character cr)
  ifTrue:
  [(String streamContents:
  [:s|
  s position > 0 ifTrue: [s tab: level + 1].
  node emitCCodeAsArgumentOn: s level: level generator: self])
  copyReplaceAll: (String with: Character cr)
  with: (String with: Character cr), (String new: level + 1 withAll: Character tab)]
  ifFalse: [expansion])]]
  ifFalse:
  [[:node| | expansion |
   expansion := String streamContents: [:s| node emitCCodeOn: s level: level generator: self].
  "Remove tabs from first line to avoid indenting a second time"
  expansion ifNotEmpty:
  [expansion := expansion allButFirst: (expansion findFirst: [:c| c ~~ Character tab]) - 1].
  aStream nextPutAll: expansion]].
 
+ "First attempt to expand statically..."
+ allAlternativesWereDeterminable := true.
+ 1 to: msgNode args size - 1 by: 2 do: "Deal with cppIf:ifTrue:, cppIf:ifTrue:ifFalse:, cppIf:ifTrue:cppIf:ifTrue:ifFalse:, etc"
+ [:conditionIndex|
+ (self nilOrBooleanConditionFor: (msgNode args at: conditionIndex))
+ ifNil: [allAlternativesWereDeterminable := false]
+ ifNotNil:
+ [:condition|
+ condition ifTrue:
+ [putStatement value: (msgNode args at: conditionIndex + 1).
+ ^self]]].
+ allAlternativesWereDeterminable ifTrue:
+ [msgNode args size odd ifTrue: "there is an ifFalse:"
+ [putStatement value: msgNode args last].
- (self nilOrBooleanConditionFor: msgNode args first) ifNotNil:
- [:condition|
- condition
- ifTrue:
- [putStatement value: msgNode args second]
- ifFalse:
- [msgNode args size >= 3 ifTrue:
- [putStatement value: msgNode args third]].
  ^self].
 
+ "Expand for compile-time evaluation. Full #if ... #else..."
- "Full #if ... #else..."
  putStatement := asArgument
  ifTrue: "emitCCodeAsArgumentOn: doesn't indent, the code needs indenting in this case, so post-process."
  [[:node|
   aStream nextPutAll:
  ((String streamContents:
  [:s|
  s next: level + 1 put: Character tab.
  node emitCCodeAsArgumentOn: s level: level generator: self])
  copyReplaceAll: (String with: Character cr)
  with: (String with: Character cr), (String new: level + 1 withAll: Character tab))]]
  ifFalse:
  [[:node| node emitCCodeOn: aStream level: level generator: self]].
 
+ 1 to: msgNode args size - 1 by: 2 do: "Deal with cppIf:ifTrue:, cppIf:ifTrue:ifFalse:, cppIf:ifTrue:cppIf:ifTrue:ifFalse:, etc"
+ [:conditionIndex| | condition |
+ condition := String streamContents:
+ [:es|
+ (msgNode args at: conditionIndex)
+ emitCCodeAsArgumentOn: es
+ level: 0
+ generator: self].
+ [condition last isSeparator] whileTrue:
+ [condition := condition allButLast].
+ aStream
+ ensureCr;
+ nextPut: $#; next: level * 2 put: Character space; nextPutAll: (conditionIndex = 1 ifTrue: ['if '] ifFalse: ['elif ']); nextPutAll: condition; cr.
- expr := String streamContents:
- [:es|
- msgNode args first
- emitCCodeAsArgumentOn: es
- level: 0
- generator: self].
- [expr last isSeparator] whileTrue:
- [expr := expr allButLast].
- aStream
- ensureCr;
- nextPut: $#; next: level * 2 put: Character space; nextPutAll: 'if '; nextPutAll: expr; cr.
 
+ pos := aStream position.
+ self with: (msgNode args at: conditionIndex)
+ ifAppropriateSetTo: true
+ do: [putStatement value: (msgNode args at: conditionIndex + 1)].
+ expr := (expr ifNil: [' /* '] ifNotNil: [expr, ' || ']), condition].
+ expr := expr, ' */'.
+ msgNode args size odd ifTrue: "there is an ifFalse:"
- self with: msgNode args first
- ifAppropriateSetTo: true
- do: [putStatement value: msgNode args second].
- expr := ' /* ', expr, ' */'.
- msgNode args size >= 3 ifTrue:
  [aStream
  ensureCr;
+ nextPut: $#; next: level * 2 put: Character space; nextPutAll: 'else'.
+ aStream position - pos >= 128 ifTrue:
+ [aStream nextPutAll: expr].
+ aStream cr.
+ pos := aStream position.
+ msgNode args size <= 3
+ ifTrue: "ifTrue:ifFalse:, so negate condition for ifFalse:"
+ [self with: msgNode args last
+ ifAppropriateSetTo: false
+ do: [putStatement value: msgNode args third]]
+ ifFalse:
+ [putStatement value: msgNode args last]].
- nextPut: $#; next: level * 2 put: Character space; nextPutAll: 'else'; nextPutAll: expr;
- cr.
- self with: msgNode args first
- ifAppropriateSetTo: false
- do: [putStatement value: msgNode args third]].
  aStream
  ensureCr;
+ nextPut: $#; next: level * 2 put: Character space; nextPutAll: 'endif'.
+ aStream position - pos >= 128 ifTrue:
+ [aStream nextPutAll: expr].
+ aStream cr.
- nextPut: $#; next: level * 2 put: Character space; nextPutAll: 'endif'; nextPutAll: expr;
- cr.
  asArgument ifTrue:
  [aStream next: level + 1 put: Character tab]!

Item was changed:
  ----- Method: CCodeGenerator>>generateToByDo:on:indent: (in category 'C translation') -----
  generateToByDo: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
  "N.B. MessageNode>>asTranslatorNodeIn: adds the limit var as a hidden fourth argument."
  | blockExpr iterationVar limitExpr mayHaveSideEffects limitVar step |
  blockExpr := msgNode args third.
  blockExpr args size = 1 ifFalse:
  [self error: 'wrong number of block arguments'].
  iterationVar := blockExpr args first.
  limitExpr := msgNode args first.
  aStream nextPutAll: 'for (', iterationVar, ' = '.
  self noteUsedVariableName: iterationVar.
  self emitCExpression: msgNode receiver on: aStream.
  mayHaveSideEffects := msgNode args size = 4. "See TMethod>>prepareMethodIn:"
  mayHaveSideEffects ifTrue:
  [limitVar := msgNode args last.
  aStream nextPutAll: ', ', limitVar name, ' = '.
  self emitCExpression: limitExpr on: aStream.
  limitExpr := limitVar].
  aStream nextPutAll: '; ', iterationVar.
  step := msgNode args at: 2.
  self generateToByDoLimitExpression: limitExpr
  negative: (self stepExpressionIsNegative: step)
  on: aStream.
  aStream nextPutAll: '; ', iterationVar, ' += '.
  self emitCExpression: step on: aStream.
  aStream nextPutAll: ') {'; cr.
  blockExpr emitCCodeOn: aStream level: level + 1 generator: self.
+ aStream tab: level; nextPut: $}!
- aStream tab: level.
- aStream nextPut: $}!

Item was changed:
  ----- Method: CCodeGenerator>>generateToDo:on:indent: (in category 'C translation') -----
  generateToDo: msgNode on: aStream indent: level
  "Generate the C code for this message onto the given stream."
 
  | iterationVar |
  (msgNode args last args size = 1) ifFalse: [
  self error: 'wrong number of block arguments'.
  ].
  iterationVar := msgNode args last args first.
  aStream nextPutAll: 'for (', iterationVar, ' = '.
  self emitCExpression: msgNode receiver on: aStream.
  aStream nextPutAll: '; ', iterationVar.
  self generateToByDoLimitExpression: msgNode args first negative: false on: aStream.
  aStream nextPutAll: '; ', iterationVar, '++) {'; cr.
  msgNode args last emitCCodeOn: aStream level: level + 1 generator: self.
+ aStream tab: level; nextPut: $}!
- level timesRepeat: [ aStream tab ].
- aStream nextPutAll: '}'.!

Item was changed:
  ----- Method: CCodeGenerator>>initializeCTranslationDictionary (in category 'C translation support') -----
  initializeCTranslationDictionary
  "Initialize the dictionary mapping message names to actions for C code generation."
 
  | pairs |
 
  translationDict := Dictionary new: 200.
  pairs := #(
  #& #generateAnd:on:indent:
  #| #generateOr:on:indent:
  #abs #generateAbs:on:indent:
  #and: #generateSequentialAnd:on:indent:
  #or: #generateSequentialOr:on:indent:
  #not #generateNot:on:indent:
 
  #+ #generatePlus:on:indent:
  #- #generateMinus:on:indent:
  #negated #generateNegated:on:indent:
  #* #generateTimes:on:indent:
  #/ #generateDivide:on:indent:
  #// #generateDivide:on:indent:
  #\\ #generateModulo:on:indent:
  #<< #generateShiftLeft:on:indent:
  #>> #generateShiftRight:on:indent:
  #>>> #generateSignedShiftRight:on:indent:
  #, #generateComma:on:indent:
  #min: #generateMin:on:indent:
  #max: #generateMax:on:indent:
  #between:and: #generateBetweenAnd:on:indent:
 
  #bitAnd: #generateBitAnd:on:indent:
  #bitOr: #generateBitOr:on:indent:
  #bitXor: #generateBitXor:on:indent:
  #bitShift: #generateBitShift:on:indent:
  #signedBitShift: #generateSignedBitShift:on:indent:
  #bitInvert32 #generateBitInvert:on:indent:
  #bitInvert64 #generateBitInvert:on:indent:
  #bitClear: #generateBitClear:on:indent:
  #truncateTo: #generateTruncateTo:on:indent:
  #rounded #generateRounded:on:indent:
  #even #generateEven:on:indent:
  #odd #generateOdd:on:indent:
 
  #byteSwap32 #generateByteSwap32:on:indent:
  #byteSwap64 #generateByteSwap64:on:indent:
  #byteSwapped32IfBigEndian: generateByteSwap32IfBigEndian:on:indent:
  #byteSwapped64IfBigEndian: generateByteSwap64IfBigEndian:on:indent:
 
  #< #generateLessThan:on:indent:
  #<= #generateLessThanOrEqual:on:indent:
  #= #generateEqual:on:indent:
  #> #generateGreaterThan:on:indent:
  #>= #generateGreaterThanOrEqual:on:indent:
  #~= #generateNotEqual:on:indent:
  #== #generateEqual:on:indent:
  #~~ #generateNotEqual:on:indent:
  #isNil #generateIsNil:on:indent:
  #notNil #generateNotNil:on:indent:
 
  #whileTrue: #generateWhileTrue:on:indent:
  #whileFalse: #generateWhileFalse:on:indent:
  #whileTrue #generateDoWhileTrue:on:indent:
  #whileFalse #generateDoWhileFalse:on:indent:
  #to:do: #generateToDo:on:indent:
  #to:by:do: #generateToByDo:on:indent:
  #repeat #generateRepeat:on:indent:
  #timesRepeat: #generateTimesRepeat:on:indent:
 
  #ifTrue: #generateIfTrue:on:indent:
  #ifFalse: #generateIfFalse:on:indent:
  #ifTrue:ifFalse: #generateIfTrueIfFalse:on:indent:
  #ifFalse:ifTrue: #generateIfFalseIfTrue:on:indent:
 
  #ifNotNil: #generateIfNotNil:on:indent:
  #ifNil: #generateIfNil:on:indent:
  #ifNotNil:ifNil: #generateIfNotNilIfNil:on:indent:
  #ifNil:ifNotNil: #generateIfNilIfNotNil:on:indent:
 
+ #at: #generateAt:on:indent:
+ #at:put: #generateAtPut:on:indent:
- #at: #generateAt:on:indent:
- #at:put: #generateAtPut:on:indent:
  #basicAt: #generateAt:on:indent:
  #basicAt:put: #generateAtPut:on:indent:
 
  #integerValueOf: #generateIntegerValueOf:on:indent:
  #integerObjectOf: #generateIntegerObjectOf:on:indent:
  #isIntegerObject: #generateIsIntegerObject:on:indent:
  #cCode: #generateInlineCCode:on:indent:
+ #cCode:inSmalltalk: #generateInlineCCode:on:indent:
- #cCode:inSmalltalk: #generateInlineCCode:on:indent:
  #cPreprocessorDirective: #generateInlineCPreprocessorDirective:on:indent:
+ #cppIf:ifTrue:ifFalse: #generateInlineCppIfElse:on:indent:
+ #cppIf:ifTrue:cppIf:ifTrue:ifFalse: #generateInlineCppIfElse:on:indent:
+ #cppIf:ifTrue: #generateInlineCppIfElse:on:indent:
- #cppIf:ifTrue:ifFalse: #generateInlineCppIfElse:on:indent:
- #cppIf:ifTrue: #generateInlineCppIfElse:on:indent:
  #cCoerce:to: #generateCCoercion:on:indent:
  #cCoerceSimple:to: #generateCCoercion:on:indent:
  #addressOf: #generateAddressOf:on:indent:
  #addressOf:put: #generateAddressOf:on:indent:
  #asAddress:put: #generateAsAddress:on:indent:
+ #signedIntFromLong64 #generateSignedIntFromLong64:on:indent:
- #signedIntFromLong64 #generateSignedIntFromLong64:on:indent:
  #signedIntFromLong #generateSignedIntFromLong:on:indent:
  #signedIntFromShort #generateSignedIntFromShort:on:indent:
  #signedIntToLong64 #generateSignedIntToLong64:on:indent:
  #signedIntToLong #generateSignedIntToLong:on:indent:
  #signedIntToShort #generateSignedIntToShort:on:indent:
  #preIncrement #generatePreIncrement:on:indent:
  #preDecrement #generatePreDecrement:on:indent:
  #inline: #generateInlineDirective:on:indent:
  #asFloat #generateAsFloat:on:indent:
  #asInteger #generateAsInteger:on:indent:
  #asIntegerPtr #generateAsIntegerPtr:on:indent:
  #asUnsignedInteger #generateAsUnsignedInteger:on:indent:
  #asUnsignedIntegerPtr #generateAsUnsignedIntegerPtr:on:indent:
  #asLong #generateAsLong:on:indent:
  #asUnsignedLong #generateAsUnsignedLong:on:indent:
  #asUnsignedLongLong #generateAsUnsignedLongLong:on:indent:
  #asVoidPointer #generateAsVoidPointer:on:indent:
  #asSymbol #generateAsSymbol:on:indent:
  #flag: #generateFlag:on:indent:
  #anyMask: #generateBitAnd:on:indent:
  #allMask: #generateAllMask:on:indent:
  #noMask: #generateNoMask:on:indent:
  #raisedTo: #generateRaisedTo:on:indent:
+ #touch: #generateTouch:on:indent:
- #touch: #generateTouch:on:indent:
 
  #bytesPerOop #generateBytesPerOop:on:indent:
  #bytesPerWord #generateBytesPerWord:on:indent:
  #wordSize #generateBytesPerWord:on:indent:
  #baseHeaderSize #generateBaseHeaderSize:on:indent:
  #minSmallInteger #generateSmallIntegerConstant:on:indent:
  #maxSmallInteger #generateSmallIntegerConstant:on:indent:
 
  #sharedCodeNamed:inCase: #generateSharedCodeDirective:on:indent:
 
  #perform: #generatePerform:on:indent:
  #perform:with: #generatePerform:on:indent:
+ #perform:with:with: #generatePerform:on:indent:
+ #perform:with:with:with: #generatePerform:on:indent:
- #perform:with:with: #generatePerform:on:indent:
- #perform:with:with:with: #generatePerform:on:indent:
  #perform:with:with:with:with: #generatePerform:on:indent:
  #perform:with:with:with:with:with: #generatePerform:on:indent:
 
+ #value #generateValue:on:indent:
+ #value: #generateValue:on:indent:
+ #value:value: #generateValue:on:indent:
+ #value:value:value: #generateValue:on:indent:
+ #value:value:value:value: #generateValue:on:indent:
- #value #generateValue:on:indent:
- #value: #generateValue:on:indent:
- #value:value: #generateValue:on:indent:
- #value:value:value: #generateValue:on:indent:
- #value:value:value:value: #generateValue:on:indent:
  #value:value:value:value:value: #generateValue:on:indent:
  #value:value:value:value:value:value: #generateValue:on:indent:
 
  #deny: #generateDeny:on:indent:
 
  #shouldNotImplement #generateSmalltalkMetaError:on:indent:
  #shouldBeImplemented #generateSmalltalkMetaError:on:indent:
+ #subclassResponsibility #generateSmalltalkMetaError:on:indent:
- #subclassResponsibility #generateSmalltalkMetaError:on:indent:
  ).
 
  1 to: pairs size by: 2 do: [:i |
  translationDict at: (pairs at: i) put: (pairs at: i + 1)].
 
  pairs := #(
+ #ifTrue: #generateIfTrueAsArgument:on:indent:
- #ifTrue: #generateIfTrueAsArgument:on:indent:
  #ifFalse: #generateIfFalseAsArgument:on:indent:
  #ifTrue:ifFalse: #generateIfTrueIfFalseAsArgument:on:indent:
  #ifFalse:ifTrue: #generateIfFalseIfTrueAsArgument:on:indent:
  #ifNotNil: #generateIfNotNilAsArgument:on:indent:
  #ifNil: #generateIfNilAsArgument:on:indent:
  #ifNotNil:ifNil: #generateIfNotNilIfNilAsArgument:on:indent:
  #ifNil:ifNotNil: #generateIfNilIfNotNilAsArgument:on:indent:
  #cCode: #generateInlineCCodeAsArgument:on:indent:
+ #cCode:inSmalltalk: #generateInlineCCodeAsArgument:on:indent:
- #cCode:inSmalltalk: #generateInlineCCodeAsArgument:on:indent:
  #cppIf:ifTrue:ifFalse: #generateInlineCppIfElseAsArgument:on:indent:
  #cppIf:ifTrue: #generateInlineCppIfElseAsArgument:on:indent:
 
  #value #generateValueAsArgument:on:indent:
  #value: #generateValueAsArgument:on:indent:
  #value:value: #generateValueAsArgument:on:indent:
  ).
 
  asArgumentTranslationDict := Dictionary new: 8.
  1 to: pairs size by: 2 do: [:i |
  asArgumentTranslationDict at: (pairs at: i) put: (pairs at: i + 1)].
  !

Item was changed:
  ----- Method: TCaseStmtNode>>emitCCodeOn:addToEndOfCases:level:generator: (in category 'C code generation') -----
  emitCCodeOn: aStream addToEndOfCases: aNodeOrNil level: level generator: aCodeGen
 
  | indent |
  indent := String new: level withAll: Character tab.
- aStream crtab: level.
  aStream nextPutAll: 'switch ('.
  expression emitCCodeAsArgumentOn: aStream level: level generator: aCodeGen.
  aStream nextPutAll: ') {'; cr.
  cases withIndexDo:
  [:case :i|
  (firsts at: i) to: (lasts at: i) do:
  [ :caseIndex |
  aStream nextPutAll: indent; nextPutAll: 'case '; print: caseIndex; nextPut: $:; cr].
   case emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level + 1 generator: aCodeGen.
   (aNodeOrNil notNil and: [aNodeOrNil isReturn]) ifFalse:
  [aStream crtab: level + 1; nextPutAll: 'break;']].
  aStream
  crtab: level;
  nextPutAll: 'default:';
  crtab: level + 1;
  nextPutAll: 'error("Case not found");'.
  aNodeOrNil ifNotNil:
  [aStream crtab: level + 1.
  (aNodeOrNil copy setExpression: (TConstantNode new setValue: -1))
  emitCCodeOn: aStream level: level generator: aCodeGen.
  aStream nextPut: $;].
  aStream
  crtab: level;
  nextPut: $}!

Item was changed:
  ----- Method: TMethod>>statementsListsForInliningIn: (in category 'inlining') -----
  statementsListsForInliningIn: aCodeGen
  "Answer a collection of statement list nodes that are candidates for inlining.
  Currently, we cannot inline into the argument blocks of and: and or: messages.
  We do not want to inline code strings within cCode:inSmalltalk: blocks (those with a
  proper block for the cCode: argument are inlined in MessageNode>>asTranslatorNodeIn:).
  We do not want to inline code within assert: sends (because we want the assert to read nicely)."
 
  | stmtLists |
  stmtLists := OrderedCollection new: 10.
  parseTree
  nodesDo:
  [:node|
  node isStmtList ifTrue: [stmtLists add: node]]
  unless:
  [:node|
  node isSend
  and: [node selector == #cCode:inSmalltalk:
  or: [aCodeGen isAssertSelector: node selector]]].
  parseTree nodesDo:
  [:node|
  node isSend ifTrue:
  [node selector = #cCode:inSmalltalk: ifTrue:
  [node nodesDo:
  [:ccisNode| stmtLists remove: ccisNode ifAbsent: []]].
+ (node selector beginsWith: #cppIf:ifTrue:) ifTrue:
- (node selector = #cppIf:ifTrue:ifFalse: or: [node selector = #cppIf:ifTrue:]) ifTrue:
  [node args first nodesDo:
  [:inCondNode| stmtLists remove: inCondNode ifAbsent: []]].
  ((node selector = #and:) or: [node selector = #or:]) ifTrue:
  "Note: the PP 2.3 compiler produces two arg nodes for these selectors"
  [stmtLists remove: node args first ifAbsent: [].
  stmtLists remove: node args last ifAbsent: []].
  (#( #ifTrue: #ifFalse: #ifTrue:ifFalse: #ifFalse:ifTrue:
  #ifNil: #ifNotNil: #ifNil:ifNotNil: #ifNotNil:ifNil: ) includes: node selector) ifTrue:
  [stmtLists remove: node receiver ifAbsent: []].
  (#(whileTrue whileTrue: whilefalse whileFalse:) includes: node selector) ifTrue:
  "Allow inlining if it is a [...] whileTrue/whileFalse.
  This is identified by having more than one statement in the
  receiver block in which case the C code wouldn't work anyways"
  [node receiver statements size = 1 ifTrue:
  [stmtLists remove: node receiver ifAbsent: []]].
  (node selector = #to:do:) ifTrue:
  [stmtLists remove: node receiver ifAbsent: [].
  stmtLists remove: node args first ifAbsent: []].
  (node selector = #to:by:do:) ifTrue:
  [stmtLists remove: node receiver ifAbsent: [].
  stmtLists remove: node args first ifAbsent: [].
  stmtLists remove: node args second ifAbsent: []]].
  node isCaseStmt ifTrue: "don't inline cases"
  [node cases do: [:case| stmtLists remove: case ifAbsent: []]]].
  ^stmtLists!

Item was changed:
  ----- Method: TSendNode>>isPreprocessorDirective (in category 'testing') -----
  isPreprocessorDirective
+ ^#(cPreprocessorDirective: cppIf:ifTrue: cppIf:ifTrue:ifFalse: cppIf:ifTrue:cppIf:ifTrue:ifFalse:) includes: selector!
- ^#(cPreprocessorDirective: cppIf:ifTrue:ifFalse: cppIf:ifTrue:) includes: selector!

Item was changed:
  ----- Method: TSendNode>>needsTrailingSemicolon (in category 'testing') -----
  needsTrailingSemicolon
  "Answer if, when emitted as a statement (in particular in a TStmtList), the
  receiver needs a trailing semicolon.  Preprocessor directives and special expansions do not."
  ^(self isPreprocessorDirective
    or: [self isValueExpansion
+   or: [self isConditionalSend
+   or: [selector == #expandDereferenceInterpreterProxyFunctionTable]]]) not!
-   or: [selector == #expandDereferenceInterpreterProxyFunctionTable]]) not!

Item was changed:
  ----- Method: TStmtListNode>>emitCCodeOn:prependToEnd:level:generator: (in category 'C code generation') -----
  emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level generator: aCodeGen
  | statementToElide |
  self emitCCommentOn: aStream level: level generator: aCodeGen.
  (aNodeOrNil notNil or: [statements isEmpty or: [statements last hasEffect]]) ifFalse:
  [statementToElide := statements last].
  statements withIndexDo:
+ [:s :idx| | position  lastWhilePrepending |
- [:s :idx| | position |
  s emitCCommentOn: aStream level: level generator: aCodeGen.
  (s == statementToElide
  or: [s isLeaf and: [s isLabel not and: [aNodeOrNil isNil or: [idx < statements size]]]]) ifFalse:
+ [((s isSend and: [s isPreprocessorDirective]) or: [aStream peekLast == Character tab]) ifFalse:
- [aStream peekLast ~~ Character tab ifTrue:
  [aStream tab: level].
  position := aStream position.
+ (lastWhilePrepending := aNodeOrNil notNil and: [idx = statements size])
+ ifTrue: [s emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level generator: aCodeGen]
+ ifFalse: [s emitCCodeOn: aStream level: level generator: aCodeGen].
- (aNodeOrNil notNil
- and: [idx = statements size])
- ifTrue:
- [s emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level generator: aCodeGen]
- ifFalse:
- [s emitCCodeOn: aStream level: level generator: aCodeGen].
  aStream position > position ifTrue:
  [(self stream: aStream endsWithAnyOf: '};') ifFalse:
  [s needsTrailingSemicolon ifTrue:
  [aStream nextPut: $;]].
+ (lastWhilePrepending or: [aStream peekLast == Character cr]) ifFalse:
- aStream peekLast ~~ Character cr ifTrue:
  [aStream cr]]]]!

Item was changed:
  ----- Method: TSwitchStmtNode>>emitCCodeOn:addToEndOfCases:level:generator: (in category 'C code generation') -----
  emitCCodeOn: aStream addToEndOfCases: aNodeOrNil level: level generator: aCodeGen
 
- aStream crtab: level.
  aStream nextPutAll: 'switch ('.
  expression emitCCodeAsArgumentOn: aStream level: level generator: aCodeGen.
  aStream nextPutAll: ') {'.
  cases do:
  [:tuple|
  [:labels :case|
   labels do:
  [:label|
  aStream
  crtab: level;
  nextPutAll: 'case '.
  label emitCCodeAsArgumentOn: aStream level: level + 1 generator: aCodeGen.
  aStream nextPut: $:].
   aStream crtab: level + 1.
   case emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level + 1 generator: aCodeGen]
  valueWithArguments: tuple.
+  (aNodeOrNil notNil and: [aNodeOrNil isReturn])
+ ifTrue: [(self stream: aStream endsWithAnyOf: ';}') ifFalse: [aStream nextPut: $;]]
+ ifFalse: [aStream crtab: level + 1; nextPutAll: 'break;'].
+  aStream cr].
-  (aNodeOrNil notNil and: [aNodeOrNil isReturn]) ifFalse:
- [aStream crtab: level + 1; nextPutAll: 'break;']].
  aStream
  crtab: level;
  nextPutAll: 'default:';
  crtab: level + 1.
  otherwiseOrNil
  ifNotNil: [otherwiseOrNil emitCCodeOn: aStream prependToEnd: aNodeOrNil level: level + 1 generator: aCodeGen]
+ ifNil: [aStream nextPutAll: 'error("Case not found and no otherwise clause")'.
- ifNil: [aStream nextPutAll: 'error("Case not found and no otherwise clause");'.
    aNodeOrNil ifNotNil:
  [| defaultExpr type |
+ aStream nextPut: $;; crtab: level + 1.
- aStream crtab: level + 1.
  defaultExpr := TConstantNode new setValue: -1.
  (aNodeOrNil isAssignment
   and: [(type := aCodeGen typeFor: aNodeOrNil variable in: aCodeGen currentMethod) notNil
   and: [aCodeGen isPointerCType: type]]) ifTrue:
  [defaultExpr := TSendNode new
  setSelector: #cCoerceSimple:to:
  receiver: (TVariableNode new setName: 'self')
  arguments: {defaultExpr. TConstantNode new setValue: type}].
  (aNodeOrNil copy setExpression: defaultExpr)
+ emitCCodeOn: aStream level: level generator: aCodeGen]].
- emitCCodeOn: aStream level: level generator: aCodeGen.
- aStream nextPut: $;]].
  aStream
+ nextPut: $;;
  crtab: level;
  nextPut: $}!

Item was changed:
  ----- Method: TSwitchStmtNode>>emitCCodeOn:level:generator: (in category 'C code generation') -----
  emitCCodeOn: aStream level: level generator: aCodeGen
 
- aStream crtab: level.
  aStream nextPutAll: 'switch ('.
  expression emitCCodeAsArgumentOn: aStream level: level generator: aCodeGen.
  aStream nextPutAll: ') {'.
  cases do:
  [:tuple|
  [:labels :case|
   labels do:
  [:label|
  aStream
  crtab: level;
  nextPutAll: 'case '.
  label emitCCodeAsArgumentOn: aStream level: level + 1 generator: aCodeGen.
  aStream nextPut: $:].
   aStream crtab: level + 1.
   case emitCCodeOn: aStream level: level + 1 generator: aCodeGen.
   case endsWithReturn ifFalse:
  [aStream tab: level + 1; nextPutAll: 'break;']]
  valueWithArguments: tuple].
  aStream
  crtab: level;
  nextPutAll: 'default:';
  crtab: level + 1.
  otherwiseOrNil
  ifNotNil:
  [otherwiseOrNil emitCCodeOn: aStream level: level + 1 generator: aCodeGen.
  (self stream: aStream endsWithAnyOf: '};') ifFalse:
  [aStream nextPut: $;]]
  ifNil: [aStream nextPutAll: 'error("Case not found and no otherwise clause");'].
  aStream
  crtab: level;
  nextPut: $}!

Item was changed:
  ----- Method: TSwitchStmtNode>>printOn:level: (in category 'printing') -----
  printOn: aStream level: level
 
- aStream crtab: level.
  aStream nextPutAll: 'switch ('.
  expression printOn: aStream level: level.
  aStream nextPutAll: ') {'.
  cases do:
  [:tuple|
  [:labels :case|
   labels do:
  [:label|
  aStream
  crtab: level;
  nextPutAll: 'case '.
  label printOn: aStream level: level + 1.
  aStream nextPut: $:].
   aStream crtab: level + 1.
   case printOn: aStream level: level + 1.
   aStream crtab: level + 1; nextPutAll: 'break;']
  valueWithArguments: tuple].
  otherwiseOrNil ifNotNil:
  [aStream
  crtab: level;
  nextPutAll: 'default:';
  crtab: level + 1.
  otherwiseOrNil printOn: aStream level: level + 1].
  aStream
  crtab: level;
  nextPut: $}!

Item was added:
+ ----- Method: VMClass>>cppIf:ifTrue:cppIf:ifTrue:ifFalse: (in category 'translation support') -----
+ cppIf: firstCondition ifTrue: firstExpression cppIf: secondCondition ifTrue: secondExpression ifFalse: falseExpression
+ <doNotGenerate>
+ ^self cppIf: firstCondition
+ ifTrue: firstExpression
+ ifFalse:
+ [self cppIf: secondCondition ifTrue: secondExpression ifFalse: falseExpression]!

Item was changed:
  ----- Method: VMPluginCodeGenerator>>generateV3RemapOopIn:on:indent: (in category 'C translation') -----
  generateV3RemapOopIn: aNode on: aStream indent: level
  "Generate call on remapOop: for the variable oopOrList (or all of the
  variables in oopOrList) before evaluating aBlock, and restore them after.
  This keeps the oops valid if, as V3 will, there is a GC on allocation."
 
  | idList |
  pluginFunctionsUsed add: #pushRemappableOop:; add: #popRemappableOop.
  idList := aNode args first nameOrValue.
  idList class == Array ifFalse: [idList := Array with: idList].
  idList do:
  [:each |
  aStream
  tab: level;
  nextPutAll: 'pushRemappableOop(';
  nextPutAll: each asString;
  nextPutAll: ');']
  separatedBy: [aStream cr].
  aStream cr.
  aNode args second emitCCodeOn: aStream level: level generator: self.
  level timesRepeat: [aStream tab].
  idList reversed do:
  [:each |
+ aStream
+ tab: level;
- aStream
  nextPutAll: each asString;
+ nextPutAll: ' = popRemappableOop();']
+ separatedBy: [aStream cr]!
- nextPutAll: ' = popRemappableOop()']
- separatedBy: [aStream nextPut: $;; crtab: level]!