File size: 2,890 Bytes
8f3f8db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public
addMethodsForPrimitives: classAndSelectorList 
	| sel aClass source verbose meth primInstVars sharedInstVars assignedInstVars |
	classAndSelectorList do:[:classAndSelector | 
		aClass := Smalltalk at: (classAndSelector at: 1) ifAbsent:[nil].
		aClass ifNotNil:[
			self addAllClassVarsFor: aClass.
			"TPR - should pool vars also be added here?"

			"find the method in either the class or the metaclass"
			sel := classAndSelector at: 2.
			(aClass includesSelector: sel)
				ifTrue: [source := aClass sourceCodeAt: sel ifAbsent:[nil]]
				ifFalse: [source := aClass class sourceCodeAt: sel ifAbsent:[nil]].
		].
		source ifNil:[
			Transcript cr; show: 'WARNING: Compiled primitive ', classAndSelector first, '>>', classAndSelector last, ' not present'.
		] ifNotNil:[
			"compile the method source and convert to a suitable translation 
			method "
			meth := (Compiler new
						parse: source
						in: aClass
						notifying: nil)
						asTranslationMethodOfClass: self translationMethodClass.

			(aClass includesSelector: sel)
				ifTrue: [meth definingClass: aClass]
				ifFalse: [meth definingClass: aClass class].
			meth primitive > 0 ifTrue:[meth preparePrimitiveName].
			"for old-style array accessing: 
			meth covertToZeroBasedArrayReferences."
			meth replaceSizeMessages.
			self addMethod: meth.
		].
	].
	"method preparation"
	verbose := false.
	self prepareMethods.
	verbose
		ifTrue: 
			[self printUnboundCallWarnings.
			self printUnboundVariableReferenceWarnings.
			Transcript cr].

	"code generation"
	"self doInlining: false"

	primInstVars := Set new.			"inst vars used in primitives"
	sharedInstVars := Set new.			"inst vars used in non-primitives"
	assignedInstVars :=  Set new.		"inst vars modified in non-primitives"
	methods do:[:m|
		m primitive > 0 ifTrue: [
			primInstVars addAll: m freeVariableReferences.
		] ifFalse: [
			sharedInstVars addAll: m freeVariableReferences.
			assignedInstVars addAll: m variablesAssignedTo.
		].
	].
	methods do:[:m|
		"if this method is supposed to be a primitive (rather than a helper 
		routine), add assorted prolog and epilog items"
		m primitive > 0 ifTrue: [
			m preparePrimitivePrologueShared: sharedInstVars assigned: assignedInstVars ].
		"check for one-based array access"	
		m oneBasedArrays ifNotNil: [self oneBasedArrays: true].
	].
	"Add declarations for inst vars used in both prims and non-prims as global"
	((primInstVars intersection: sharedInstVars) difference: variables) do: [:var |
		methods do:[:m|
			m declarations at: var ifPresent: [:decl |
				variableDeclarations at: var
					ifPresent: [:existing |
						decl = existing ifFalse: [self error: 'decls do not match']]
					ifAbsent: [variableDeclarations at: var put: decl]]].
		variables add: var].
	"Add non-shared inst vars as local"
	methods do:[:m|
		m locals addAll: (m freeVariableReferences difference: sharedInstVars)].