[Vm-dev] VM Maker: VMMaker.oscog-nice.2001.mcz

commits at source.squeak.org commits at source.squeak.org
Sun Nov 27 21:31:02 UTC 2016


Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.2001.mcz

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

Name: VMMaker.oscog-nice.2001
Author: nice
Time: 27 November 2016, 7:17:07.355232 pm
UUID: ec391a53-4fcd-4591-a8e7-18058ef51295
Ancestors: VMMaker.oscog-nice.2000

Correctly marshal the trampoline arguments for Win64 x64 ABI.
The registers for passing first 4 integer/pointer parameters are RCX, RDX, R8, R9.

More over, it's necessary to reserve shadow space on the stack so that the callee can save those 4 registers even when there is less than 4.
Consequently, it's mandatory for cogit to invoke genRemoveNArgsFromStack: even when numArgs = 0, and let the backEnd decide what to do.

Correct a typo in cResultRegister comment.

=============== Diff against VMMaker.oscog-nice.2000 ===============

Item was changed:
  ----- Method: CogIA32Compiler>>genRemoveNArgsFromStack: (in category 'abi') -----
  genRemoveNArgsFromStack: n 
+ 	n = 0 ifFalse: [cogit AddCq: n * 4 R: ESP].
- 	cogit AddCq: n * 4 R: ESP.
  	^0!

Item was changed:
  ----- Method: CogX64Compiler>>cResultRegister (in category 'accessing') -----
  cResultRegister
+ 	"Answer the register through which C functions return integral results."
- 	"Answer the register through which C funcitons return integral results."
  	<inline: true>
  	^RAX!

Item was changed:
  ----- Method: CogX64Compiler>>genMarshallNArgs:arg:arg:arg:arg: (in category 'abi') -----
  genMarshallNArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3
  	"Generate the code to pass up to four arguments in a C run-time call.  Hack: each argument is
  	 either a negative number, which encodes a constant, or a non-negative number, that of a register.
  
  	 Run-time calls have no more than four arguments, so chosen so that on ARM, where in its C ABI the
  	 first four integer arguments are passed in registers, all arguments can be passed in registers.  We
  	 defer to the back end to generate this code not so much that the back end knows whether it uses
  	 the stack or registers to pass arguments (it does, but...). In fact we defer for an extremely evil reason.
  	 Doing so allows the x64 (where up to 6 args are passed) to assign the register arguments in an order
  	 that allows some of the argument registers to be used for specific abstract  registers, specifically
  	 ReceiverResultReg and ClassReg.  This is evil, evil, evil, but also it's really nice to keep using the old
  	 register assignments the original author has grown accustomed to.
  
  	 How can this possibly work?  Look at Cogit class>>runtime for a list of the run-time calls and their
  	 arguments, including which arguments are passed in which registers.  Look at CogX64Compiler's
  	 subclass implementations of initializeAbstractRegisters.  There are no calls in which ReceiverResultReg
  	 (RDX) and/or ClassReg (RCX) are passed along with Arg0Reg and Arg1Reg, and none in which the use of
  	 either ReceiverResultReg or ClassReg conflict for args 3 & 4.  So if args are assigned in order, the
  	 registers do not get overwritten.  Yes, this is evil, but it's so nice to continue to use RCX & RDX.
  
+ 	 Argument registers for args 0 to 3 in SysV are RDI RSI RDX RCX, and in Win64 are RCX RDX R8 R9"
- 	 Argument registers for args 0 to 3 in SysV are RDI RSI RDX RCX, and in Win64 are RDI RSI R8 R9"
  	<inline: true>
+ 	self 
+ 		cppIf: #WIN64
+ 		ifTrue:
+ 			["WIN64 ABI allways reserve shadow space on the stack for callee to save up to 4 register parameters"
+ 			cogit SubCq: 32 R: RSP].
  	numArgs = 0 ifTrue: [^self].
+ 	self 
+ 		cppIf: #WIN64
+ 		ifTrue:
+ 			[(cogit isTrampolineArgConstant: regOrConst0)
+ 				ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst0) R: RCX] "a.k.a. Arg0Reg"
+ 				ifFalse:
+ 					[regOrConst0 ~= RCX ifTrue:
+ 						[cogit MoveR: regOrConst0 R: RCX]].
+ 			numArgs = 1 ifTrue: [^self].
+ 			(cogit isTrampolineArgConstant: regOrConst1)
+ 				ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst1) R: RDX] "a.k.a. Arg1Reg"
+ 				ifFalse:
+ 					[regOrConst1 ~= RDX ifTrue:
+ 						[cogit MoveR: regOrConst1 R: RDX]].
+ 			numArgs = 2 ifTrue: [^self].
+ 			(cogit isTrampolineArgConstant: regOrConst2)
+ 				ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst2) R: R8] "a.k.a. RISCTempReg in CogInLineLiteralsX64Compiler and Extra6Reg in CogOutOfLineLiteralsX64Compiler"
+ 				ifFalse:
+ 					[regOrConst2 ~= R8 ifTrue:
+ 						[cogit MoveR: regOrConst2 R: R8]].
+ 			 numArgs = 3 ifTrue: [^self].
+ 			 (cogit isTrampolineArgConstant: regOrConst3)
+ 					ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst3) R: R9] "a.k.a. SendNumArgsReg"
+ 					ifFalse:
+ 						[regOrConst3 ~= R9 ifTrue:
+ 							[cogit MoveR: regOrConst3 R: R9]]]
- 	(cogit isTrampolineArgConstant: regOrConst0)
- 		ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst0) R: RDI] "a.k.a. Arg0Reg"
  		ifFalse:
+ 			[(cogit isTrampolineArgConstant: regOrConst0)
+ 				ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst0) R: RDI] "a.k.a. Arg0Reg"
- 			[regOrConst0 ~= RDI ifTrue:
- 				[cogit MoveR: regOrConst0 R: RDI]].
- 	numArgs = 1 ifTrue: [^self].
- 	(cogit isTrampolineArgConstant: regOrConst1)
- 		ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst1) R: RSI] "a.k.a. Arg1Reg"
- 		ifFalse:
- 			[regOrConst1 ~= RSI ifTrue:
- 				[cogit MoveR: regOrConst1 R: RSI]].
- 	numArgs = 2 ifTrue: [^self].
- 	self cppIf: ABI == #SysV ifTrue:
- 		[(cogit isTrampolineArgConstant: regOrConst2)
- 			ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst2) R: RDX] "a.k.a. ReceiverResultReg"
- 			ifFalse:
- 				[regOrConst2 ~= RDX ifTrue:
- 					[cogit MoveR: regOrConst2 R: RDX]].
- 		 numArgs = 3 ifTrue: [^self].
- 		 (cogit isTrampolineArgConstant: regOrConst3)
- 				ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst3) R: RCX] "a.k.a. ClassReg"
  				ifFalse:
+ 					[regOrConst0 ~= RDI ifTrue:
+ 						[cogit MoveR: regOrConst0 R: RDI]].
+ 			numArgs = 1 ifTrue: [^self].
+ 			(cogit isTrampolineArgConstant: regOrConst1)
+ 				ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst1) R: RSI] "a.k.a. Arg1Reg"
- 					[regOrConst3 ~= RCX ifTrue:
- 						[cogit MoveR: regOrConst3 R: RCX]]].
- 	self cppIf: ABI == #MSVC ifTrue: "completely untested..."
- 		[(cogit isTrampolineArgConstant: regOrConst2)
- 			ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst2) R: R8] "a.k.a. RISCTempReg in CogInLineLiteralsX64Compiler and Extra6Reg in CogOutOfLineLiteralsX64Compiler"
- 			ifFalse:
- 				[regOrConst2 ~= R8 ifTrue:
- 					[cogit MoveR: regOrConst2 R: R8]].
- 		 numArgs = 3 ifTrue: [^self].
- 		 (cogit isTrampolineArgConstant: regOrConst3)
- 				ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst3) R: R9] "a.k.a. SendNumArgsReg"
  				ifFalse:
+ 					[regOrConst1 ~= RSI ifTrue:
+ 						[cogit MoveR: regOrConst1 R: RSI]].
+ 			numArgs = 2 ifTrue: [^self].
+ 			(cogit isTrampolineArgConstant: regOrConst2)
+ 				ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst2) R: RDX] "a.k.a. ReceiverResultReg"
+ 				ifFalse:
+ 					[regOrConst2 ~= RDX ifTrue:
+ 						[cogit MoveR: regOrConst2 R: RDX]].
+ 			 numArgs = 3 ifTrue: [^self].
+ 			 (cogit isTrampolineArgConstant: regOrConst3)
+ 					ifTrue: [cogit MoveCq: (cogit trampolineArgValue: regOrConst3) R: RCX] "a.k.a. ClassReg"
+ 					ifFalse:
+ 						[regOrConst3 ~= RCX ifTrue:
+ 							[cogit MoveR: regOrConst3 R: RCX]]].
- 					[regOrConst3 ~= R9 ifTrue:
- 						[cogit MoveR: regOrConst3 R: R9]]].
  	self assert: numArgs <= 4!

Item was changed:
  ----- Method: CogX64Compiler>>genRemoveNArgsFromStack: (in category 'abi') -----
  genRemoveNArgsFromStack: n
+ 	"This is a no-op on x64 SysV since the ABI passes up to 6 args in registers and trampolines currently observe a limit of 4.
+ 	But the WIN64 ABI allways reserve shadow space for saving up to 4 parameter registers (even if less than 4 args)."
+ 	self assert: n <= 4.
+ 	self cppIf: #WIN64 ifTrue:
+ 		[cogit AddCq: 32 R: RSP].
- 	"This is a no-op on x64 since the ABI passes up to 6 args in registers and trampolines currently observe a limit of 4."
- 	self assert: n <= 6.
  	^0!

Item was changed:
  ----- Method: Cogit>>compileCallFor:numArgs:arg:arg:arg:arg:floatResultReg:regsToSave: (in category 'initialization') -----
  compileCallFor: aRoutine numArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3 floatResultReg: resultRegOrNone regsToSave: regMask
  	"Generate a call to aRoutine with up to 4 arguments.  If resultRegOrNone is not
  	 NoReg assign the C result to resultRegOrNone.  If saveRegs, save all registers.
  	 Hack: a negative arg value indicates an abstract register, a non-negative value
  	 indicates a constant."
  	<var: #aRoutine type: #'void *'>
  	<inline: false>
  	| regsToSave |
  	regsToSave := resultRegOrNone = NoReg
  						ifTrue: [regMask]
  						ifFalse: [regMask bitClear: (self registerMaskFor: resultRegOrNone)].
  	cStackAlignment > objectMemory wordSize ifTrue:
  		[backEnd
  			genAlignCStackSavingRegisters: regsToSave
  			numArgs: numArgs
  			wordAlignment: cStackAlignment / objectMemory wordSize].
  	backEnd
  		genSaveRegs: regsToSave;
  		genMarshallNArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3.
  	self CallFullRT: (self cCode: [aRoutine asUnsignedInteger]
  						inSmalltalk: [self simulatedTrampolineFor: aRoutine]).
  	resultRegOrNone ~= NoReg ifTrue:
  		[backEnd cFloatResultToRd: resultRegOrNone].
+ 	 backEnd genRemoveNArgsFromStack: numArgs.
- 	 numArgs > 0 ifTrue:
- 		[backEnd genRemoveNArgsFromStack: numArgs].
  	backEnd genRestoreRegs: regsToSave!

Item was changed:
  ----- Method: Cogit>>compileCallFor:numArgs:arg:arg:arg:arg:resultReg:regsToSave: (in category 'initialization') -----
  compileCallFor: aRoutine numArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3 resultReg: resultRegOrNone regsToSave: regMask
  	"Generate a call to aRoutine with up to 4 arguments.  If resultRegOrNone is not
  	 NoReg assign the C result to resultRegOrNone.  If saveRegs, save all registers.
  	 Hack: a negative arg value indicates an abstract register, a non-negative value
  	 indicates a constant."
  	<var: #aRoutine type: #'void *'>
  	<inline: false>
  	| regsToSave |
  	regsToSave := resultRegOrNone = NoReg
  						ifTrue: [regMask]
  						ifFalse: [regMask bitClear: (self registerMaskFor: resultRegOrNone)].
  	cStackAlignment > objectMemory wordSize ifTrue:
  		[backEnd
  			genAlignCStackSavingRegisters: regsToSave
  			numArgs: numArgs
  			wordAlignment: cStackAlignment / objectMemory wordSize].
  	backEnd
  		genSaveRegs: regsToSave;
  		genMarshallNArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3.
  	self CallFullRT: (self cCode: [aRoutine asUnsignedInteger]
  						inSmalltalk: [self simulatedTrampolineFor: aRoutine]).
  	resultRegOrNone ~= NoReg ifTrue:
  		[backEnd genWriteCResultIntoReg: resultRegOrNone].
+ 	backEnd genRemoveNArgsFromStack: numArgs.
- 	 numArgs > 0 ifTrue:
- 		[backEnd genRemoveNArgsFromStack: numArgs].
  	backEnd genRestoreRegs: regsToSave!

Item was changed:
  ----- Method: Cogit>>compileCallFor:numArgs:arg:arg:arg:arg:resultReg:resultReg:regsToSave: (in category 'initialization') -----
  compileCallFor: aRoutine numArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3 resultReg: resultRegOrNone resultReg: resultReg2OrNone regsToSave: regMask
  	"Generate a call to aRoutine with up to 4 arguments.  If resultRegOrNone is not
  	 NoReg assign the C result to resultRegOrNone.  If saveRegs, save all registers.
  	 Hack: a negative arg value indicates an abstract register, a non-negative value
  	 indicates a constant."
  	<var: #aRoutine type: #'void *'>
  	<inline: false>
  	| regsToSave |
  	regsToSave := resultRegOrNone = NoReg
  						ifTrue: [regMask]
  						ifFalse: [regMask bitClear: (self registerMaskFor: resultRegOrNone)].
  	cStackAlignment > objectMemory wordSize ifTrue:
  		[backEnd
  			genAlignCStackSavingRegisters: regsToSave
  			numArgs: numArgs
  			wordAlignment: cStackAlignment / objectMemory wordSize].
  	backEnd
  		genSaveRegs: regsToSave;
  		genMarshallNArgs: numArgs arg: regOrConst0 arg: regOrConst1 arg: regOrConst2 arg: regOrConst3.
  	self CallFullRT: (self cCode: [aRoutine asUnsignedInteger]
  						inSmalltalk: [self simulatedTrampolineFor: aRoutine]).
  	resultRegOrNone ~= NoReg ifTrue:
  		[backEnd genWriteCResultIntoReg: resultRegOrNone].
  	resultReg2OrNone ~= NoReg ifTrue:
  		[backEnd genWriteCSecondResultIntoReg: resultReg2OrNone].
+ 	backEnd genRemoveNArgsFromStack: numArgs.
- 	 numArgs > 0 ifTrue:
- 		[backEnd genRemoveNArgsFromStack: numArgs].
  	backEnd genRestoreRegs: regsToSave!



More information about the Vm-dev mailing list