File: Arena.h

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 52,004 kB
  • sloc: ansic: 261,462; cpp: 140,405; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (198 lines) | stat: -rw-r--r-- 7,801 bytes parent folder | download | duplicates (2)
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#pragma once
#include "Core/TObject.h"
#include "Core/EnginePtr.h"
#include "Output.h"
#include "Operand.h"

namespace code {
	STORM_PKG(core.asm);

	class Listing;
	class Binary;
	class RegSet;
	class TypeDesc;
	class Instr;

	/**
	 * An arena represents a collection of compiled code and external references for some architecture.
	 *
	 * Abstract class, there is one instantiation for each supported platform.
	 */
	class Arena : public ObjectOn<Compiler> {
		STORM_ABSTRACT_CLASS;
	public:
		// Create an arena.
		Arena();

		// Create external references.
		Ref external(const wchar *name, const void *ptr) const;
		RefSource *externalSource(const wchar *name, const void *ptr) const;

		/**
		 * Transform and translate code into machine code.
		 */

		// Detailed info from the transform operation.
		class TransformInfo {
			STORM_VALUE;
		public:
			// The final listing.
			Listing *listing;

			// The layout of all local variables.
			Array<Offset> *varLayout;

			// Create.
			STORM_CTOR TransformInfo(Listing *listing, Array<Offset> *layout)
				: listing(listing), varLayout(layout) {}
		};

		// Transform the code in preparation for this backend's code generation. This is
		// backend-specific. 'owner' is the binary object that will be called to handle exceptions.
		virtual TransformInfo STORM_FN transformInfo(Listing *src) const ABSTRACT;
		virtual Listing *STORM_FN transform(Listing *src) const;

		// Translate a previously transformed listing into machine code for this arena.
		virtual void STORM_FN output(Listing *src, Output *to) const ABSTRACT;

		/**
		 * Create output objects for this backend.
		 */

		// Create an offset-computing output.
		virtual LabelOutput *STORM_FN labelOutput() const ABSTRACT;

		// Create a code-generating output based on sizes computed by a LabelOutput.
		virtual CodeOutput *STORM_FN codeOutput(Binary *owner, LabelOutput *size) const ABSTRACT;

		// Remove all registers not preserved during a function call on this platform. This
		// implementation removes ptrA, ptrB and ptrC, but other Arena implementations may want to
		// remove others as well.
		virtual void STORM_FN removeFnRegs(RegSet *from) const;

		// Get a list of registers that may contain the return value from a function.
		virtual RegSet *STORM_FN fnResultRegs() const ABSTRACT;
		virtual Instr *STORM_FN saveFnResultReg(Reg reg, Operand to) const;
		virtual Instr *STORM_FN restoreFnResultReg(Reg reg, Operand from) const;


		/**
		 * Other backend-specific things.
		 */

		// Create a function that calls another function (optionally with a pointer sized parameter)
		// to figure out which function to actually call. Useful when implementing lazy compilation.
		//
		// Calls 'fn' with 'param' (always pointer-sized or empty) to compute the
		// actual function to call. The actual function (as well as the 'function' implemented by
		// the redirect) takes params as defined by 'params' and returns 'result'.
		//
		// These redirect objects are *not* platform independent!
		virtual Listing *STORM_FN redirect(Bool member, TypeDesc *result, Array<TypeDesc *> *params, Ref fn, Operand param) ABSTRACT;

		// Create a function that calls another (pre-determined) function and appends an 'EnginePtr'
		// object as the first parameter to the other function. Calling member functions in this
		// manner is not supported.
		virtual Listing *STORM_FN engineRedirect(TypeDesc *result, Array<TypeDesc *> *params, Ref fn, Operand engine) ABSTRACT;


		/**
		 * Get the location of the first parameter for a function call. Assumes that a member function is called.
		 *
		 * The location is acquired in two steps: first, an implementation asks the ID of the
		 * parameter location by calling the 'firstParamId(TypeDesc *)' function. This returns one
		 * out of several possible integers describing the parameter location. The number of
		 * possible values can be acquired by calling 'firstParamId(null)'.
		 *
		 * The ID can then be passed to 'firstParamLoc' to get an Operand describing the location.
		 *
		 * This scheme is used so that classes like VTableCalls can detect when two functions with
		 * different return values have the same vtable stub. This allows it to re-use the stubs.
		 */

		// Get the ID of the location of the first param.
		virtual Nat STORM_FN firstParamId(MAYBE(TypeDesc *) desc) ABSTRACT;

		// Access the location of the first parameter in a function size. The returned Operand is
		// always pointer-sized.
		virtual Operand STORM_FN firstParamLoc(Nat id) ABSTRACT;

		// Get a parameter that can safely be used to implement function dispatches.
		virtual Reg STORM_FN functionDispatchReg() ABSTRACT;


		/**
		 * Machine-specific parts of the ability to replace active functions.
		 */

		// Information about a created skeleton.
		class Skeleton : public Object {
			STORM_CLASS;
		public:
			// Saved non-volatile registers.
			Array<Operand> *savedRegs;

			// Location of the non-volatile registers, relative to the frame pointer.
			Array<Operand> *savedLocs;

			// Variable offsets we know about. Some may be empty.
			Array<Operand> *varOffsets;

			// Listing containing variables to make the stack frame compatible the one in the Binary.
			Listing *listing;

			// Array of extra offsets that need to be restored during an update.
			Array<Offset> *extraMetadata;

			// Current block and activation.
			Nat currentBlock;
			Nat currentActivation;

			// How to access variables from a different stack frame of a larger size:
			// < 0: use same offsets as from the other stack frame.
			// >=0: offsets are relative to 'n' bytes after the end of this frame.
			Int accessMode;

			// Create.
			STORM_CTOR Skeleton(Listing *listing);
		};

		// Create a skeleton Listing that has a variable layout that is binary compatible with the
		// code in a given Binary object. The function may also initialize the listing with dummy
		// writes to callee saved registers in order to get the right layout.
		virtual Skeleton *STORM_FN compatibleFrameSkeleton(Binary *binary, Nat offset) ABSTRACT;

		// Update any exception information when replacing an active function.
		virtual void updateEhInfo(const void *function, size_t offset, void *framePointer);

		// Generate code to resize the stack frame of the current function to be as large as
		// required by 'newSize'.
		virtual void STORM_FN resizeStackFrame(Listing *out, Reg tmpReg, Binary *newSize) ABSTRACT;

	protected:

		// Helper function for the first step of 'compatibleFrameSkeleton':
		// Creates a listing, and populates it from the binary.
		Skeleton *frameSkeletonHead(Binary *binary);

		// Helper function for the last step of 'compatibleFrameSkeleton':
		// Assumes that 'preservedRegs' and 'preservedLocs' have been filled in after the first step.
		// Also, expects 'extraWords' indicating the number of words with "overhead" that is allocated
		// on the stack by the backend. Also expects that 'currentBlock' and 'currentActivation' are
		// populated. 'minAlign' is the minimum alignment imposed by the stack layout.
		void frameSkeletonTail(Binary *binary, Skeleton *skeleton, Nat extraWords, Nat minAlign, Bool is64);

		// Version of 'frameSkeletonTail', but for architectures where the frame pointer is placed
		// after the variables rather than before them (e.g. ARM).
		void frameSkeletonTailBelow(Binary *binary, Skeleton *skeleton, Nat extraBelow, Nat extraAbove, Nat minAlign, Bool is64);
	};

	// Create an arena for this platform.
	Arena *STORM_FN arena(EnginePtr e);

	// Extract the Binary associated with a function. This is only valid for code generated with the current backend.
	// 'fn' is expected to be a pointer to the start of a code allocation.
	Binary *codeBinary(const void *fn);
	Binary *codeBinaryImpl(GcCode *refs);

}