File: RemoveInvalid.h

package info (click to toggle)
storm-lang 0.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 52,028 kB
  • sloc: ansic: 261,471; cpp: 140,432; 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 (137 lines) | stat: -rw-r--r-- 5,442 bytes parent folder | download
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
#pragma once
#include "FnCall.h"
#include "../Transform.h"
#include "../OpTable.h"
#include "../Reg.h"
#include "../Instr.h"
#include "Core/Array.h"

namespace code {
	namespace arm64 {
		STORM_PKG(core.asm.arm64);

		/**
		 * Transform that removes invalid or otherwise non-supported OP-codes, replacing them with
		 * an equivalent sequence of supported OP-codes. In particular, ensures that all arithmetic
		 * operations operate on registers, not on memory.
		 */
		class RemoveInvalid : public Transform {
			STORM_CLASS;
		public:
			STORM_CTOR RemoveInvalid();

			// Start transform.
			virtual void STORM_FN before(Listing *dest, Listing *src);

			// Transform a single instruction.
			virtual void STORM_FN during(Listing *dest, Listing *src, Nat id);

			// Finalize transform.
			virtual void STORM_FN after(Listing *dest, Listing *src);

			// Helper function to create a constant for a large integer.
			Operand largeConstant(const Operand &constant);

		private:
			// Used registers for each line.
			Array<RegSet *> *used;

			// Current active block. Mainly used for introducing blocks inside the 'fnCall' transform.
			Block currentBlock;

			// Function parameters.
			Array<ParamInfo> *params;

			// Large operands. Emitted at the end of the function so that we can load them.
			Array<Operand> *large;

			// Label to the start of the large constants section.
			Label lblLarge;

			// Label to integer division by zero code, if necessary.
			Label lblDivZero;

			// Get the division by zero label if needed.
			Label divZeroLabel(Listing *l);

			// Signature for the table of transform functions.
			typedef void (RemoveInvalid::*TransformFn)(Listing *to, Instr *instr, Nat line);

			// Transform table.
			static const OpEntry<TransformFn> transformMap[];

			// Generic function for wrapping an instruction between loads and stores.
			void removeMemoryRefs(Listing *to, Instr *instr, Nat line);

			// Generic function for loading data into a register. Handles cases that a plain mov
			// instruction does not handle without transformation.
			void loadRegister(Listing *to, Reg reg, const Operand &load);

			// Load value into fp register.
			Reg loadFpRegister(Listing *to, const Operand &load, Nat line);

			// Limit operands with large constants to the desired length. Otherwise replaces it with
			// code to load the constant into a suitable register.
			Operand limitImm(Listing *to, const Operand &op, Nat line, Nat immBits, Bool immSigned);

			// Same as 'limitImm', but only affects the source of the instruction.
			Instr *limitImmSrc(Listing *to, Instr *instr, Nat line, Nat immBits, Bool immSigned);

			// Generate code that ensures that 'op' is either a constant of a particular size, or a
			// register.
			Operand regOrImm(Listing *to, const Operand &op, Nat line, Nat immBits, Bool immSigned);

			// Modify instructions for byte-sized operands.
			Instr *modifyByte(Listing *to, Instr *instr, Nat line);
			Operand modifyByte(Listing *to, const Operand &op, Nat line, Bool opSigned);

			// Function calls.
			void fnParamTfm(Listing *to, Instr *instr, Nat line);
			void fnParamRefTfm(Listing *to, Instr *instr, Nat line);
			void fnCallTfm(Listing *to, Instr *instr, Nat line);
			void fnCallRefTfm(Listing *to, Instr *instr, Nat line);

			// Keep track of the current part.
			void prologTfm(Listing *to, Instr *instr, Nat line);
			void epilogTfm(Listing *to, Instr *instr, Nat line);
			void beginBlockTfm(Listing *to, Instr *instr, Nat line);
			void endBlockTfm(Listing *to, Instr *instr, Nat line);

			// Fix constraints for specific operations.
			void movTfm(Listing *to, Instr *instr, Nat line);
			void shadowMovTfm(Listing *to, Instr *instr, Nat line);
			void leaTfm(Listing *to, Instr *instr, Nat line);
			void swapTfm(Listing *to, Instr *instr, Nat line);
			void cmpTfm(Listing *to, Instr *instr, Nat line);
			void testTfm(Listing *to, Instr *instr, Nat line);
			void setCondTfm(Listing *to, Instr *instr, Nat line);
			void icastTfm(Listing *to, Instr *instr, Nat line);
			void ucastTfm(Listing *to, Instr *instr, Nat line);
			void fcastTfm(Listing *to, Instr *instr, Nat line);
			void fcastiTfm(Listing *to, Instr *instr, Nat line);
			void fcastuTfm(Listing *to, Instr *instr, Nat line);
			void icastfTfm(Listing *to, Instr *instr, Nat line);
			void ucastfTfm(Listing *to, Instr *instr, Nat line);

			// Transform mod into div + multiply as needed. No mod operation on ARM!
			void idivTfm(Listing *to, Instr *instr, Nat line);
			void udivTfm(Listing *to, Instr *instr, Nat line);
			void imodTfm(Listing *to, Instr *instr, Nat line);
			void umodTfm(Listing *to, Instr *instr, Nat line);

			// Generic constraint fixing:
			// Constraints for data operations with a 12 bit immediate or a (shifted) register.
			void dataInstr12Tfm(Listing *to, Instr *instr, Nat line);
			// Constraints for data operations with a bitmask-type immediate or a (shifted) register.
			void bitmaskInstrTfm(Listing *to, Instr *instr, Nat line);
			// Constraints for 4-reg data operations where all operands need to be in memory.
			void dataInstr4RegTfm(Listing *to, Instr *instr, Nat line);
			// For shift operations, where 'src' is either an immediate (that needs to be small), or a register.
			void shiftInstrTfm(Listing *to, Instr *instr, Nat line);
			// For floating-point arithmetic operations.
			void fpInstrTfm(Listing *to, Instr *instr, Nat line);

		};

	}
}