[Vm-dev] VM Maker: VMMaker.oscog-eem.2779.mcz

commits at source.squeak.org commits at source.squeak.org
Sat Jul 25 20:02:47 UTC 2020


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]!



More information about the Vm-dev mailing list