File: hints.bs

package info (click to toggle)
storm-lang 0.7.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 51,836 kB
  • sloc: ansic: 261,420; cpp: 138,870; sh: 14,877; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (157 lines) | stat: -rw-r--r-- 4,148 bytes parent folder | download | duplicates (5)
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
use core:asm;
use core:lang;
use lang:bs:macro;

// Hints for the C++ module.
progvis:program:Hints hints() {
	progvis:program:Hints(CppCodeHints(), CppViewHints());
}

/**
 * Code hints.
 *
 * We can take all local variables and just put them inside a Variant directly, since they are
 * already allocated that way.
 */
class CppCodeHints extends progvis:program:CodeHints {
	init() {
		init() {
			// Anything not starting with a letter is an operator.
			operators("[^a-zA-Z_].*");
		}
	}

	// Regex for matching operators.
	lang:bnf:Regex operators;

	Fn<void>? findMain(Package pkg) : override {
		if (fn = pkg.find(SimplePart("main"), Scope(pkg)) as Function) {
			var ptr = fn.pointer;
			if (ptr as Fn<void>)
				return ptr;

			// TODO: Wrap output in a better way.
			if (ptr as Fn<Int>)
				return &ptr.wrapMain();
		}

		// TODO: Perhaps support "argc, argv" parameters as well!
		null;
	}

	Bool handlesFunction(Function fn) : override {
		if (fn as CppFunction)
			true;
		else
			false;
	}

	Str cleanName(Function fn, Package pkg) : override {
		Str name = fn.name;
		if (fn.isMember()) {
			if (t = fn.params[0].type) {
				if (fn.name == "__destroy") {
					return "~" + t.name + "()";
				} else if (fn.name == "__init") {
					name = t.name;
				} else if (operators.match(fn.name)) {
					name = "operator " + fn.name;
				}
			}
		}

		// TODO!
		name + "(...)";
	}

	Bool patchExternal(Function fn) : override {
		// Patch functions in our runtime. Otherwise memory accesses are not tracked very
		// well. Additionally, we need to patch things inside the Ptr<> classes.
		if (fn.hasParent(named{runtime}))
			return true;

		if (ptr = fn.parent as PtrType)
			return true;

		false;
	}

	progvis:program:Barrier functionBarrier(Function fn) : override {
		// No extra barriers for functions in our runtime.
		if (fn.hasParent(named{runtime}))
			return progvis:program:Barrier:none;

		// Neither for things in core.
		if (fn.hasParent(named{core}))
			return progvis:program:Barrier:none;

		// For other functions in Progvis, no barrier there either. These are implementation details
		// that we don't want to be visible.
		if (fn.hasParent(named{progvis}))
			return progvis:program:Barrier:none;

		// All other functions, we insert a barrier for. We don't know what they do.
		return progvis:program:Barrier:full;
	}

	Save saveVariable(Listing to, Var var, Listing:VarInfo info, Operand dest) : override {
		if (!info.ref)
			return Save:none;

		// If the variable is a reference to a value and a parameter, we assume that it originates
		// from a pointer allocation somewhere. It could, however, be allocated on the stack, which
		// in itself is fine as long as we don't try to read the type information from the RawPtr
		// created in the end.
		if (to.isParam(var)) {
			// Variables like this are followed by an integer variable specifying their original offset.
			Var next = nextParam(var, to);
			if (next == Var())
				return Save:none;

			if (next.size != sNat)
				return Save:none;

			unless (type = (named{}).find(SimplePart("Ptr", [Value(info.type)]), Scope()) as Type)
				throw InternalError("Could not find a pointer type for ${info.type}.");

			to << fnParam(ptrDesc, type.typeRef);
			to << fnParam(ptrDesc, ptrConst(1));
			to << fnCall(ref(BuiltIn:allocArray), false, ptrDesc, ptrA);

			to << mov(ptrB, var);
			to << ucast(ptrC, next);
			to << sub(ptrB, ptrC);

			to << mov(ptrRel(ptrA, Offset(sPtr)), ptrConst(1)); // filled
			to << mov(ptrRel(ptrA, Offset(sPtr*2)), ptrB); // base
			to << mov(intRel(ptrA, Offset(sPtr*3)), next); // offset

			to << mov(dest, ptrA);
		} else {
			to << mov(dest, var);
		}
		Save:ref;
	}

	// Find the next parameter.
	private Var nextParam(Var param, Listing in) : static {
		Var[] params = in.allParams();
		for (i, v in params) {
			if (v == param) {
				if (i + 1 < params.count)
					return params[i + 1];
			}
		}

		return Var();
	}
}

void wrapMain(Fn<Int> fn) {
	var program = progvis:program:findProgram();
	var result = fn.call.toS();
	if (program) {
		program.addOutput("\nMain returned ${result}\n");
		program.notifyChange(true);
	}
}