File: FnState.cpp

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • 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 (83 lines) | stat: -rw-r--r-- 2,175 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
#include "stdafx.h"
#include "FnState.h"
#include "Code/Block.h"
#include "Code/Exception.h"

namespace code {

	Nat encodeFnState(Nat block, Nat activation) {
		if (block != Block().key() && block > 0xFFFE)
			throw new (runtime::someEngine()) InvalidValue(S("The X86 backend does not support more than 65535 blocks."));
		if (activation > 0xFFFF)
			throw new (runtime::someEngine()) InvalidValue(S("The X86 backend does not support more than 65536 activations."));

		if (block == Block().key())
			block = 0xFFFF;

		return (block << 16) | activation;
	}

	void decodeFnState(Nat original, Nat &block, Nat &activation) {
		block = (original >> 16) & 0xFFFF;
		activation = original & 0xFFFF;

		if (block == 0xFFFF)
			block = Block().key();
	}


	/**
	 * Description of the data at the end of each function.
	 */
	struct FnData {
		// Number of entries in the block table.
		size_t blockCount;
	};

	/**
	 * Description of a single entry in the block table.
	 */
	struct FnBlock {
		// At which offset do we start?
		Nat offset;

		// Which block?
		Nat block;
	};

	// Get the block data from a function.
	static const FnBlock *getBlocks(const FnData *data) {
		const FnBlock *end = (const FnBlock *)data;
		return end - data->blockCount;
	}

	// Compare object.
	struct BlockCompare {
		bool operator()(Nat offset, const FnBlock &block) const {
			return offset < block.offset;
		}
	};

	Nat findFunctionState(const void *function, size_t offset) {
		size_t size = runtime::codeSize(function);
		return findFunctionStateFromEnd((const byte *)function + size, offset);
	}

	Nat findFunctionStateFromEnd(const void *end, size_t offset) {
		const FnData *data = (const FnData *)end - 1;
		const FnBlock *blocks = getBlocks(data);

		Nat invalid = Block().key();
		// The entries are sorted by their 'offset' member. We can perform a binary search!
		// Note: if there are multiple elements that are equal, we need to pick the last one.
		const FnBlock *found = std::upper_bound(blocks, blocks + data->blockCount, Nat(offset), BlockCompare());
		if (found == blocks) {
			// Before any block, nothing to do!
			return invalid;
		}
		found--;

		return found->block;
	}

}