1f08c3bdfSopenharmony_ci/*
2f08c3bdfSopenharmony_ci * Example usage:
3f08c3bdfSopenharmony_ci *	./sparse-llvm hello.c | llc | as -o hello.o
4f08c3bdfSopenharmony_ci */
5f08c3bdfSopenharmony_ci
6f08c3bdfSopenharmony_ci#include <llvm-c/Core.h>
7f08c3bdfSopenharmony_ci#include <llvm-c/BitWriter.h>
8f08c3bdfSopenharmony_ci#include <llvm-c/Analysis.h>
9f08c3bdfSopenharmony_ci#include <llvm-c/Target.h>
10f08c3bdfSopenharmony_ci
11f08c3bdfSopenharmony_ci#include <stdbool.h>
12f08c3bdfSopenharmony_ci#include <stdio.h>
13f08c3bdfSopenharmony_ci#include <unistd.h>
14f08c3bdfSopenharmony_ci#include <string.h>
15f08c3bdfSopenharmony_ci#include <assert.h>
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci#include "symbol.h"
18f08c3bdfSopenharmony_ci#include "expression.h"
19f08c3bdfSopenharmony_ci#include "linearize.h"
20f08c3bdfSopenharmony_ci#include "flow.h"
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_cistruct function {
23f08c3bdfSopenharmony_ci	LLVMBuilderRef			builder;
24f08c3bdfSopenharmony_ci	LLVMValueRef			fn;
25f08c3bdfSopenharmony_ci	LLVMModuleRef			module;
26f08c3bdfSopenharmony_ci};
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_cistatic LLVMTypeRef symbol_type(struct symbol *sym);
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_cistatic LLVMTypeRef func_return_type(struct symbol *sym)
31f08c3bdfSopenharmony_ci{
32f08c3bdfSopenharmony_ci	return symbol_type(sym->ctype.base_type);
33f08c3bdfSopenharmony_ci}
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_cistatic LLVMTypeRef sym_func_type(struct symbol *sym)
36f08c3bdfSopenharmony_ci{
37f08c3bdfSopenharmony_ci	int n_arg = symbol_list_size(sym->arguments);
38f08c3bdfSopenharmony_ci	LLVMTypeRef *arg_type = calloc(n_arg, sizeof(LLVMTypeRef));
39f08c3bdfSopenharmony_ci	LLVMTypeRef ret_type = func_return_type(sym);
40f08c3bdfSopenharmony_ci	struct symbol *arg;
41f08c3bdfSopenharmony_ci	int idx = 0;
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_ci	FOR_EACH_PTR(sym->arguments, arg) {
44f08c3bdfSopenharmony_ci		struct symbol *arg_sym = arg->ctype.base_type;
45f08c3bdfSopenharmony_ci
46f08c3bdfSopenharmony_ci		arg_type[idx++] = symbol_type(arg_sym);
47f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(arg);
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_ci	return LLVMFunctionType(ret_type, arg_type, n_arg, sym->variadic);
50f08c3bdfSopenharmony_ci}
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_cistatic LLVMTypeRef sym_array_type(struct symbol *sym)
53f08c3bdfSopenharmony_ci{
54f08c3bdfSopenharmony_ci	LLVMTypeRef elem_type;
55f08c3bdfSopenharmony_ci	struct symbol *base_type;
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ci	base_type = sym->ctype.base_type;
58f08c3bdfSopenharmony_ci	/* empty struct is undefined [6.7.2.1(8)] */
59f08c3bdfSopenharmony_ci	assert(base_type->bit_size > 0);
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_ci	elem_type = symbol_type(base_type);
62f08c3bdfSopenharmony_ci	if (!elem_type)
63f08c3bdfSopenharmony_ci		return NULL;
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ci	return LLVMArrayType(elem_type, sym->bit_size / base_type->bit_size);
66f08c3bdfSopenharmony_ci}
67f08c3bdfSopenharmony_ci
68f08c3bdfSopenharmony_ci#define MAX_STRUCT_MEMBERS 64
69f08c3bdfSopenharmony_ci
70f08c3bdfSopenharmony_cistatic LLVMTypeRef sym_struct_type(struct symbol *sym)
71f08c3bdfSopenharmony_ci{
72f08c3bdfSopenharmony_ci	LLVMTypeRef elem_types[MAX_STRUCT_MEMBERS];
73f08c3bdfSopenharmony_ci	struct symbol *member;
74f08c3bdfSopenharmony_ci	char buffer[256];
75f08c3bdfSopenharmony_ci	LLVMTypeRef ret;
76f08c3bdfSopenharmony_ci	unsigned nr = 0;
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	snprintf(buffer, sizeof(buffer), "struct.%s", sym->ident ? sym->ident->name : "anno");
79f08c3bdfSopenharmony_ci	ret = LLVMStructCreateNamed(LLVMGetGlobalContext(), buffer);
80f08c3bdfSopenharmony_ci	/* set ->aux to avoid recursion */
81f08c3bdfSopenharmony_ci	sym->aux = ret;
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_ci	FOR_EACH_PTR(sym->symbol_list, member) {
84f08c3bdfSopenharmony_ci		LLVMTypeRef member_type;
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_ci		assert(nr < MAX_STRUCT_MEMBERS);
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ci		member_type = symbol_type(member);
89f08c3bdfSopenharmony_ci
90f08c3bdfSopenharmony_ci		elem_types[nr++] = member_type;
91f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(member);
92f08c3bdfSopenharmony_ci
93f08c3bdfSopenharmony_ci	LLVMStructSetBody(ret, elem_types, nr, 0 /* packed? */);
94f08c3bdfSopenharmony_ci	return ret;
95f08c3bdfSopenharmony_ci}
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_cistatic LLVMTypeRef sym_union_type(struct symbol *sym)
98f08c3bdfSopenharmony_ci{
99f08c3bdfSopenharmony_ci	LLVMTypeRef elements;
100f08c3bdfSopenharmony_ci	unsigned union_size;
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_ci	/*
103f08c3bdfSopenharmony_ci	 * There's no union support in the LLVM API so we treat unions as
104f08c3bdfSopenharmony_ci	 * opaque structs. The downside is that we lose type information on the
105f08c3bdfSopenharmony_ci	 * members but as LLVM doesn't care, neither do we.
106f08c3bdfSopenharmony_ci	 */
107f08c3bdfSopenharmony_ci	union_size = sym->bit_size / 8;
108f08c3bdfSopenharmony_ci
109f08c3bdfSopenharmony_ci	elements = LLVMArrayType(LLVMInt8Type(), union_size);
110f08c3bdfSopenharmony_ci
111f08c3bdfSopenharmony_ci	return LLVMStructType(&elements, 1, 0 /* packed? */);
112f08c3bdfSopenharmony_ci}
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_cistatic LLVMTypeRef sym_ptr_type(struct symbol *sym)
115f08c3bdfSopenharmony_ci{
116f08c3bdfSopenharmony_ci	LLVMTypeRef type;
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci	/* 'void *' is treated like 'char *' */
119f08c3bdfSopenharmony_ci	if (is_void_type(sym->ctype.base_type))
120f08c3bdfSopenharmony_ci		type = LLVMInt8Type();
121f08c3bdfSopenharmony_ci	else
122f08c3bdfSopenharmony_ci		type = symbol_type(sym->ctype.base_type);
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_ci	return LLVMPointerType(type, 0);
125f08c3bdfSopenharmony_ci}
126f08c3bdfSopenharmony_ci
127f08c3bdfSopenharmony_cistatic LLVMTypeRef sym_basetype_type(struct symbol *sym)
128f08c3bdfSopenharmony_ci{
129f08c3bdfSopenharmony_ci	LLVMTypeRef ret = NULL;
130f08c3bdfSopenharmony_ci
131f08c3bdfSopenharmony_ci	if (is_float_type(sym)) {
132f08c3bdfSopenharmony_ci		switch (sym->bit_size) {
133f08c3bdfSopenharmony_ci		case 32:
134f08c3bdfSopenharmony_ci			ret = LLVMFloatType();
135f08c3bdfSopenharmony_ci			break;
136f08c3bdfSopenharmony_ci		case 64:
137f08c3bdfSopenharmony_ci			ret = LLVMDoubleType();
138f08c3bdfSopenharmony_ci			break;
139f08c3bdfSopenharmony_ci		case 80:
140f08c3bdfSopenharmony_ci			ret = LLVMX86FP80Type();
141f08c3bdfSopenharmony_ci			break;
142f08c3bdfSopenharmony_ci		default:
143f08c3bdfSopenharmony_ci			die("invalid bit size %d for type %d", sym->bit_size, sym->type);
144f08c3bdfSopenharmony_ci			break;
145f08c3bdfSopenharmony_ci		}
146f08c3bdfSopenharmony_ci	} else {
147f08c3bdfSopenharmony_ci		switch (sym->bit_size) {
148f08c3bdfSopenharmony_ci		case -1:
149f08c3bdfSopenharmony_ci			ret = LLVMVoidType();
150f08c3bdfSopenharmony_ci			break;
151f08c3bdfSopenharmony_ci		case 1:
152f08c3bdfSopenharmony_ci			ret = LLVMInt1Type();
153f08c3bdfSopenharmony_ci			break;
154f08c3bdfSopenharmony_ci		case 8:
155f08c3bdfSopenharmony_ci			ret = LLVMInt8Type();
156f08c3bdfSopenharmony_ci			break;
157f08c3bdfSopenharmony_ci		case 16:
158f08c3bdfSopenharmony_ci			ret = LLVMInt16Type();
159f08c3bdfSopenharmony_ci			break;
160f08c3bdfSopenharmony_ci		case 32:
161f08c3bdfSopenharmony_ci			ret = LLVMInt32Type();
162f08c3bdfSopenharmony_ci			break;
163f08c3bdfSopenharmony_ci		case 64:
164f08c3bdfSopenharmony_ci			ret = LLVMInt64Type();
165f08c3bdfSopenharmony_ci			break;
166f08c3bdfSopenharmony_ci		default:
167f08c3bdfSopenharmony_ci			die("invalid bit size %d for type %d", sym->bit_size, sym->type);
168f08c3bdfSopenharmony_ci			break;
169f08c3bdfSopenharmony_ci		}
170f08c3bdfSopenharmony_ci	}
171f08c3bdfSopenharmony_ci
172f08c3bdfSopenharmony_ci	return ret;
173f08c3bdfSopenharmony_ci}
174f08c3bdfSopenharmony_ci
175f08c3bdfSopenharmony_cistatic LLVMTypeRef symbol_type(struct symbol *sym)
176f08c3bdfSopenharmony_ci{
177f08c3bdfSopenharmony_ci	LLVMTypeRef ret = NULL;
178f08c3bdfSopenharmony_ci
179f08c3bdfSopenharmony_ci	/* don't cache the result for SYM_NODE */
180f08c3bdfSopenharmony_ci	if (sym->type == SYM_NODE)
181f08c3bdfSopenharmony_ci		return symbol_type(sym->ctype.base_type);
182f08c3bdfSopenharmony_ci
183f08c3bdfSopenharmony_ci	if (sym->aux)
184f08c3bdfSopenharmony_ci		return sym->aux;
185f08c3bdfSopenharmony_ci
186f08c3bdfSopenharmony_ci	switch (sym->type) {
187f08c3bdfSopenharmony_ci	case SYM_BITFIELD:
188f08c3bdfSopenharmony_ci		ret = LLVMIntType(sym->bit_size);
189f08c3bdfSopenharmony_ci		break;
190f08c3bdfSopenharmony_ci	case SYM_RESTRICT:
191f08c3bdfSopenharmony_ci	case SYM_ENUM:
192f08c3bdfSopenharmony_ci		ret = symbol_type(sym->ctype.base_type);
193f08c3bdfSopenharmony_ci		break;
194f08c3bdfSopenharmony_ci	case SYM_BASETYPE:
195f08c3bdfSopenharmony_ci		ret = sym_basetype_type(sym);
196f08c3bdfSopenharmony_ci		break;
197f08c3bdfSopenharmony_ci	case SYM_PTR:
198f08c3bdfSopenharmony_ci		ret = sym_ptr_type(sym);
199f08c3bdfSopenharmony_ci		break;
200f08c3bdfSopenharmony_ci	case SYM_UNION:
201f08c3bdfSopenharmony_ci		ret = sym_union_type(sym);
202f08c3bdfSopenharmony_ci		break;
203f08c3bdfSopenharmony_ci	case SYM_STRUCT:
204f08c3bdfSopenharmony_ci		ret = sym_struct_type(sym);
205f08c3bdfSopenharmony_ci		break;
206f08c3bdfSopenharmony_ci	case SYM_ARRAY:
207f08c3bdfSopenharmony_ci		ret = sym_array_type(sym);
208f08c3bdfSopenharmony_ci		break;
209f08c3bdfSopenharmony_ci	case SYM_FN:
210f08c3bdfSopenharmony_ci		ret = sym_func_type(sym);
211f08c3bdfSopenharmony_ci		break;
212f08c3bdfSopenharmony_ci	default:
213f08c3bdfSopenharmony_ci		assert(0);
214f08c3bdfSopenharmony_ci	}
215f08c3bdfSopenharmony_ci
216f08c3bdfSopenharmony_ci	/* cache the result */
217f08c3bdfSopenharmony_ci	sym->aux = ret;
218f08c3bdfSopenharmony_ci	return ret;
219f08c3bdfSopenharmony_ci}
220f08c3bdfSopenharmony_ci
221f08c3bdfSopenharmony_cistatic LLVMTypeRef insn_symbol_type(struct instruction *insn)
222f08c3bdfSopenharmony_ci{
223f08c3bdfSopenharmony_ci	if (insn->type)
224f08c3bdfSopenharmony_ci		return symbol_type(insn->type);
225f08c3bdfSopenharmony_ci
226f08c3bdfSopenharmony_ci	switch (insn->size) {
227f08c3bdfSopenharmony_ci		case 8:		return LLVMInt8Type();
228f08c3bdfSopenharmony_ci		case 16:	return LLVMInt16Type();
229f08c3bdfSopenharmony_ci		case 32:	return LLVMInt32Type();
230f08c3bdfSopenharmony_ci		case 64:	return LLVMInt64Type();
231f08c3bdfSopenharmony_ci
232f08c3bdfSopenharmony_ci		default:
233f08c3bdfSopenharmony_ci			die("invalid bit size %d", insn->size);
234f08c3bdfSopenharmony_ci			break;
235f08c3bdfSopenharmony_ci	}
236f08c3bdfSopenharmony_ci
237f08c3bdfSopenharmony_ci	return NULL;	/* not reached */
238f08c3bdfSopenharmony_ci}
239f08c3bdfSopenharmony_ci
240f08c3bdfSopenharmony_cistatic LLVMLinkage data_linkage(struct symbol *sym)
241f08c3bdfSopenharmony_ci{
242f08c3bdfSopenharmony_ci	if (sym->ctype.modifiers & MOD_STATIC)
243f08c3bdfSopenharmony_ci		return LLVMPrivateLinkage;
244f08c3bdfSopenharmony_ci
245f08c3bdfSopenharmony_ci	return LLVMExternalLinkage;
246f08c3bdfSopenharmony_ci}
247f08c3bdfSopenharmony_ci
248f08c3bdfSopenharmony_cistatic LLVMLinkage function_linkage(struct symbol *sym)
249f08c3bdfSopenharmony_ci{
250f08c3bdfSopenharmony_ci	if (sym->ctype.modifiers & MOD_STATIC)
251f08c3bdfSopenharmony_ci		return LLVMInternalLinkage;
252f08c3bdfSopenharmony_ci
253f08c3bdfSopenharmony_ci	return LLVMExternalLinkage;
254f08c3bdfSopenharmony_ci}
255f08c3bdfSopenharmony_ci
256f08c3bdfSopenharmony_ci#define MAX_PSEUDO_NAME 64
257f08c3bdfSopenharmony_ci
258f08c3bdfSopenharmony_cistatic const char *pseudo_name(pseudo_t pseudo, char *buf)
259f08c3bdfSopenharmony_ci{
260f08c3bdfSopenharmony_ci	switch (pseudo->type) {
261f08c3bdfSopenharmony_ci	case PSEUDO_REG:
262f08c3bdfSopenharmony_ci		snprintf(buf, MAX_PSEUDO_NAME, "R%d.", pseudo->nr);
263f08c3bdfSopenharmony_ci		break;
264f08c3bdfSopenharmony_ci	case PSEUDO_PHI:
265f08c3bdfSopenharmony_ci		snprintf(buf, MAX_PSEUDO_NAME, "PHI%d.", pseudo->nr);
266f08c3bdfSopenharmony_ci		break;
267f08c3bdfSopenharmony_ci	case PSEUDO_SYM:
268f08c3bdfSopenharmony_ci	case PSEUDO_VAL:
269f08c3bdfSopenharmony_ci	case PSEUDO_ARG:
270f08c3bdfSopenharmony_ci	case PSEUDO_VOID:
271f08c3bdfSopenharmony_ci		buf[0] = '\0';
272f08c3bdfSopenharmony_ci		break;
273f08c3bdfSopenharmony_ci	case PSEUDO_UNDEF:
274f08c3bdfSopenharmony_ci		assert(0);
275f08c3bdfSopenharmony_ci		break;
276f08c3bdfSopenharmony_ci	default:
277f08c3bdfSopenharmony_ci		assert(0);
278f08c3bdfSopenharmony_ci	}
279f08c3bdfSopenharmony_ci
280f08c3bdfSopenharmony_ci	return buf;
281f08c3bdfSopenharmony_ci}
282f08c3bdfSopenharmony_ci
283f08c3bdfSopenharmony_cistatic LLVMValueRef get_sym_value(LLVMModuleRef module, struct symbol *sym)
284f08c3bdfSopenharmony_ci{
285f08c3bdfSopenharmony_ci	const char *name = show_ident(sym->ident);
286f08c3bdfSopenharmony_ci	LLVMTypeRef type = symbol_type(sym);
287f08c3bdfSopenharmony_ci	LLVMValueRef result = NULL;
288f08c3bdfSopenharmony_ci	struct expression *expr;
289f08c3bdfSopenharmony_ci
290f08c3bdfSopenharmony_ci	assert(sym->bb_target == NULL);
291f08c3bdfSopenharmony_ci
292f08c3bdfSopenharmony_ci	expr = sym->initializer;
293f08c3bdfSopenharmony_ci	if (expr && !sym->ident) {
294f08c3bdfSopenharmony_ci		switch (expr->type) {
295f08c3bdfSopenharmony_ci		case EXPR_STRING: {
296f08c3bdfSopenharmony_ci			const char *s = expr->string->data;
297f08c3bdfSopenharmony_ci			LLVMValueRef indices[] = { LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt64Type(), 0, 0) };
298f08c3bdfSopenharmony_ci			LLVMValueRef data;
299f08c3bdfSopenharmony_ci
300f08c3bdfSopenharmony_ci			data = LLVMAddGlobal(module, LLVMArrayType(LLVMInt8Type(), strlen(s) + 1), ".str");
301f08c3bdfSopenharmony_ci			LLVMSetLinkage(data, LLVMPrivateLinkage);
302f08c3bdfSopenharmony_ci			LLVMSetGlobalConstant(data, 1);
303f08c3bdfSopenharmony_ci			LLVMSetInitializer(data, LLVMConstString(strdup(s), strlen(s) + 1, true));
304f08c3bdfSopenharmony_ci
305f08c3bdfSopenharmony_ci			result = LLVMConstGEP(data, indices, ARRAY_SIZE(indices));
306f08c3bdfSopenharmony_ci			return result;
307f08c3bdfSopenharmony_ci		}
308f08c3bdfSopenharmony_ci		default:
309f08c3bdfSopenharmony_ci			break;
310f08c3bdfSopenharmony_ci		}
311f08c3bdfSopenharmony_ci	}
312f08c3bdfSopenharmony_ci
313f08c3bdfSopenharmony_ci	if (LLVMGetTypeKind(type) == LLVMFunctionTypeKind) {
314f08c3bdfSopenharmony_ci		result = LLVMGetNamedFunction(module, name);
315f08c3bdfSopenharmony_ci		if (!result)
316f08c3bdfSopenharmony_ci			result = LLVMAddFunction(module, name, type);
317f08c3bdfSopenharmony_ci	} else {
318f08c3bdfSopenharmony_ci		result = LLVMGetNamedGlobal(module, name);
319f08c3bdfSopenharmony_ci		if (!result)
320f08c3bdfSopenharmony_ci			result = LLVMAddGlobal(module, type, name);
321f08c3bdfSopenharmony_ci	}
322f08c3bdfSopenharmony_ci
323f08c3bdfSopenharmony_ci	return result;
324f08c3bdfSopenharmony_ci}
325f08c3bdfSopenharmony_ci
326f08c3bdfSopenharmony_cistatic LLVMValueRef constant_value(unsigned long long val, LLVMTypeRef dtype)
327f08c3bdfSopenharmony_ci{
328f08c3bdfSopenharmony_ci	LLVMValueRef result;
329f08c3bdfSopenharmony_ci
330f08c3bdfSopenharmony_ci	switch (LLVMGetTypeKind(dtype)) {
331f08c3bdfSopenharmony_ci	case LLVMPointerTypeKind:
332f08c3bdfSopenharmony_ci		if (val != 0) {	 // for example: ... = (void*) 0x123;
333f08c3bdfSopenharmony_ci			LLVMTypeRef itype = LLVMIntType(bits_in_pointer);
334f08c3bdfSopenharmony_ci			result = LLVMConstInt(itype, val, 1);
335f08c3bdfSopenharmony_ci			result = LLVMConstIntToPtr(result, dtype);
336f08c3bdfSopenharmony_ci		} else {
337f08c3bdfSopenharmony_ci			result = LLVMConstPointerNull(dtype);
338f08c3bdfSopenharmony_ci		}
339f08c3bdfSopenharmony_ci		break;
340f08c3bdfSopenharmony_ci	case LLVMIntegerTypeKind:
341f08c3bdfSopenharmony_ci		result = LLVMConstInt(dtype, val, 1);
342f08c3bdfSopenharmony_ci		break;
343f08c3bdfSopenharmony_ci	case LLVMArrayTypeKind:
344f08c3bdfSopenharmony_ci	case LLVMStructTypeKind:
345f08c3bdfSopenharmony_ci		if (val != 0)
346f08c3bdfSopenharmony_ci			return NULL;
347f08c3bdfSopenharmony_ci		result = LLVMConstNull(dtype);
348f08c3bdfSopenharmony_ci		break;
349f08c3bdfSopenharmony_ci	default:
350f08c3bdfSopenharmony_ci		return NULL;
351f08c3bdfSopenharmony_ci	}
352f08c3bdfSopenharmony_ci	return result;
353f08c3bdfSopenharmony_ci}
354f08c3bdfSopenharmony_ci
355f08c3bdfSopenharmony_cistatic LLVMValueRef val_to_value(unsigned long long val, struct symbol *ctype)
356f08c3bdfSopenharmony_ci{
357f08c3bdfSopenharmony_ci	LLVMValueRef result;
358f08c3bdfSopenharmony_ci	LLVMTypeRef dtype;
359f08c3bdfSopenharmony_ci
360f08c3bdfSopenharmony_ci	assert(ctype);
361f08c3bdfSopenharmony_ci	dtype = symbol_type(ctype);
362f08c3bdfSopenharmony_ci	result = constant_value(val, dtype);
363f08c3bdfSopenharmony_ci	if (result)
364f08c3bdfSopenharmony_ci		return result;
365f08c3bdfSopenharmony_ci	sparse_error(ctype->pos, "no value possible for %s", show_typename(ctype));
366f08c3bdfSopenharmony_ci	return LLVMGetUndef(symbol_type(ctype));
367f08c3bdfSopenharmony_ci}
368f08c3bdfSopenharmony_ci
369f08c3bdfSopenharmony_cistatic LLVMValueRef pseudo_to_value(struct function *fn, struct symbol *ctype, pseudo_t pseudo)
370f08c3bdfSopenharmony_ci{
371f08c3bdfSopenharmony_ci	LLVMValueRef result = NULL;
372f08c3bdfSopenharmony_ci
373f08c3bdfSopenharmony_ci	switch (pseudo->type) {
374f08c3bdfSopenharmony_ci	case PSEUDO_REG:
375f08c3bdfSopenharmony_ci		result = pseudo->priv;
376f08c3bdfSopenharmony_ci		break;
377f08c3bdfSopenharmony_ci	case PSEUDO_SYM:
378f08c3bdfSopenharmony_ci		result = get_sym_value(fn->module, pseudo->sym);
379f08c3bdfSopenharmony_ci		break;
380f08c3bdfSopenharmony_ci	case PSEUDO_VAL:
381f08c3bdfSopenharmony_ci		result = val_to_value(pseudo->value, ctype);
382f08c3bdfSopenharmony_ci		break;
383f08c3bdfSopenharmony_ci	case PSEUDO_ARG: {
384f08c3bdfSopenharmony_ci		result = LLVMGetParam(fn->fn, pseudo->nr - 1);
385f08c3bdfSopenharmony_ci		break;
386f08c3bdfSopenharmony_ci	}
387f08c3bdfSopenharmony_ci	case PSEUDO_PHI:
388f08c3bdfSopenharmony_ci		result = pseudo->priv;
389f08c3bdfSopenharmony_ci		break;
390f08c3bdfSopenharmony_ci	case PSEUDO_VOID:
391f08c3bdfSopenharmony_ci		result = NULL;
392f08c3bdfSopenharmony_ci		break;
393f08c3bdfSopenharmony_ci	case PSEUDO_UNDEF:
394f08c3bdfSopenharmony_ci		result = LLVMGetUndef(symbol_type(ctype));
395f08c3bdfSopenharmony_ci		break;
396f08c3bdfSopenharmony_ci	default:
397f08c3bdfSopenharmony_ci		assert(0);
398f08c3bdfSopenharmony_ci	}
399f08c3bdfSopenharmony_ci
400f08c3bdfSopenharmony_ci	return result;
401f08c3bdfSopenharmony_ci}
402f08c3bdfSopenharmony_ci
403f08c3bdfSopenharmony_cistatic LLVMValueRef pseudo_to_rvalue(struct function *fn, struct symbol *ctype, pseudo_t pseudo)
404f08c3bdfSopenharmony_ci{
405f08c3bdfSopenharmony_ci	LLVMValueRef val = pseudo_to_value(fn, ctype, pseudo);
406f08c3bdfSopenharmony_ci	LLVMTypeRef dtype = symbol_type(ctype);
407f08c3bdfSopenharmony_ci	char name[MAX_PSEUDO_NAME];
408f08c3bdfSopenharmony_ci
409f08c3bdfSopenharmony_ci	pseudo_name(pseudo, name);
410f08c3bdfSopenharmony_ci	return LLVMBuildBitCast(fn->builder, val, dtype, name);
411f08c3bdfSopenharmony_ci}
412f08c3bdfSopenharmony_ci
413f08c3bdfSopenharmony_cistatic LLVMValueRef value_to_ivalue(struct function *fn, struct symbol *ctype, LLVMValueRef val)
414f08c3bdfSopenharmony_ci{
415f08c3bdfSopenharmony_ci	const char *name = LLVMGetValueName(val);
416f08c3bdfSopenharmony_ci	LLVMTypeRef dtype = symbol_type(ctype);
417f08c3bdfSopenharmony_ci
418f08c3bdfSopenharmony_ci	if (LLVMGetTypeKind(LLVMTypeOf(val)) == LLVMPointerTypeKind) {
419f08c3bdfSopenharmony_ci		LLVMTypeRef dtype = LLVMIntType(bits_in_pointer);
420f08c3bdfSopenharmony_ci		val = LLVMBuildPtrToInt(fn->builder, val, dtype, name);
421f08c3bdfSopenharmony_ci	}
422f08c3bdfSopenharmony_ci	if (ctype && is_int_type(ctype)) {
423f08c3bdfSopenharmony_ci		val = LLVMBuildIntCast(fn->builder, val, dtype, name);
424f08c3bdfSopenharmony_ci	}
425f08c3bdfSopenharmony_ci	return val;
426f08c3bdfSopenharmony_ci}
427f08c3bdfSopenharmony_ci
428f08c3bdfSopenharmony_cistatic LLVMValueRef value_to_pvalue(struct function *fn, struct symbol *ctype, LLVMValueRef val)
429f08c3bdfSopenharmony_ci{
430f08c3bdfSopenharmony_ci	const char *name = LLVMGetValueName(val);
431f08c3bdfSopenharmony_ci	LLVMTypeRef dtype = symbol_type(ctype);
432f08c3bdfSopenharmony_ci
433f08c3bdfSopenharmony_ci	assert(is_ptr_type(ctype));
434f08c3bdfSopenharmony_ci	switch (LLVMGetTypeKind(LLVMTypeOf(val))) {
435f08c3bdfSopenharmony_ci	case LLVMIntegerTypeKind:
436f08c3bdfSopenharmony_ci		val = LLVMBuildIntToPtr(fn->builder, val, dtype, name);
437f08c3bdfSopenharmony_ci		break;
438f08c3bdfSopenharmony_ci	case LLVMPointerTypeKind:
439f08c3bdfSopenharmony_ci		val = LLVMBuildBitCast(fn->builder, val, dtype, name);
440f08c3bdfSopenharmony_ci		break;
441f08c3bdfSopenharmony_ci	default:
442f08c3bdfSopenharmony_ci		break;
443f08c3bdfSopenharmony_ci	}
444f08c3bdfSopenharmony_ci	return val;
445f08c3bdfSopenharmony_ci}
446f08c3bdfSopenharmony_ci
447f08c3bdfSopenharmony_cistatic LLVMValueRef adjust_type(struct function *fn, struct symbol *ctype, LLVMValueRef val)
448f08c3bdfSopenharmony_ci{
449f08c3bdfSopenharmony_ci	if (is_int_type(ctype))
450f08c3bdfSopenharmony_ci		return value_to_ivalue(fn, ctype, val);
451f08c3bdfSopenharmony_ci	if (is_ptr_type(ctype))
452f08c3bdfSopenharmony_ci		return value_to_pvalue(fn, ctype, val);
453f08c3bdfSopenharmony_ci	return val;
454f08c3bdfSopenharmony_ci}
455f08c3bdfSopenharmony_ci
456f08c3bdfSopenharmony_ci/*
457f08c3bdfSopenharmony_ci * Get the LLVMValue corresponding to the pseudo
458f08c3bdfSopenharmony_ci * and force the type corresponding to ctype.
459f08c3bdfSopenharmony_ci */
460f08c3bdfSopenharmony_cistatic LLVMValueRef get_operand(struct function *fn, struct symbol *ctype, pseudo_t pseudo)
461f08c3bdfSopenharmony_ci{
462f08c3bdfSopenharmony_ci	LLVMValueRef target = pseudo_to_value(fn, ctype, pseudo);
463f08c3bdfSopenharmony_ci	return adjust_type(fn, ctype, target);
464f08c3bdfSopenharmony_ci}
465f08c3bdfSopenharmony_ci
466f08c3bdfSopenharmony_ci/*
467f08c3bdfSopenharmony_ci * Get the LLVMValue corresponding to the pseudo
468f08c3bdfSopenharmony_ci * and force the type corresponding to ctype but
469f08c3bdfSopenharmony_ci * map all pointers to intptr_t.
470f08c3bdfSopenharmony_ci */
471f08c3bdfSopenharmony_cistatic LLVMValueRef get_ioperand(struct function *fn, struct symbol *ctype, pseudo_t pseudo)
472f08c3bdfSopenharmony_ci{
473f08c3bdfSopenharmony_ci	LLVMValueRef target = pseudo_to_value(fn, ctype, pseudo);
474f08c3bdfSopenharmony_ci	return value_to_ivalue(fn, ctype, target);
475f08c3bdfSopenharmony_ci}
476f08c3bdfSopenharmony_ci
477f08c3bdfSopenharmony_cistatic LLVMValueRef calc_gep(LLVMBuilderRef builder, LLVMValueRef base, LLVMValueRef off)
478f08c3bdfSopenharmony_ci{
479f08c3bdfSopenharmony_ci	LLVMTypeRef type = LLVMTypeOf(base);
480f08c3bdfSopenharmony_ci	unsigned int as = LLVMGetPointerAddressSpace(type);
481f08c3bdfSopenharmony_ci	LLVMTypeRef bytep = LLVMPointerType(LLVMInt8Type(), as);
482f08c3bdfSopenharmony_ci	LLVMValueRef addr;
483f08c3bdfSopenharmony_ci	const char *name = LLVMGetValueName(off);
484f08c3bdfSopenharmony_ci
485f08c3bdfSopenharmony_ci	/* convert base to char* type */
486f08c3bdfSopenharmony_ci	base = LLVMBuildPointerCast(builder, base, bytep, name);
487f08c3bdfSopenharmony_ci	/* addr = base + off */
488f08c3bdfSopenharmony_ci	addr = LLVMBuildInBoundsGEP(builder, base, &off, 1, name);
489f08c3bdfSopenharmony_ci	/* convert back to the actual pointer type */
490f08c3bdfSopenharmony_ci	addr = LLVMBuildPointerCast(builder, addr, type, name);
491f08c3bdfSopenharmony_ci	return addr;
492f08c3bdfSopenharmony_ci}
493f08c3bdfSopenharmony_ci
494f08c3bdfSopenharmony_cistatic LLVMRealPredicate translate_fop(int opcode)
495f08c3bdfSopenharmony_ci{
496f08c3bdfSopenharmony_ci	static const LLVMRealPredicate trans_tbl[] = {
497f08c3bdfSopenharmony_ci		[OP_FCMP_ORD]	= LLVMRealORD,
498f08c3bdfSopenharmony_ci		[OP_FCMP_OEQ]	= LLVMRealOEQ,
499f08c3bdfSopenharmony_ci		[OP_FCMP_ONE]	= LLVMRealONE,
500f08c3bdfSopenharmony_ci		[OP_FCMP_OLE]	= LLVMRealOLE,
501f08c3bdfSopenharmony_ci		[OP_FCMP_OGE]	= LLVMRealOGE,
502f08c3bdfSopenharmony_ci		[OP_FCMP_OLT]	= LLVMRealOLT,
503f08c3bdfSopenharmony_ci		[OP_FCMP_OGT]	= LLVMRealOGT,
504f08c3bdfSopenharmony_ci		[OP_FCMP_UEQ]	= LLVMRealUEQ,
505f08c3bdfSopenharmony_ci		[OP_FCMP_UNE]	= LLVMRealUNE,
506f08c3bdfSopenharmony_ci		[OP_FCMP_ULE]	= LLVMRealULE,
507f08c3bdfSopenharmony_ci		[OP_FCMP_UGE]	= LLVMRealUGE,
508f08c3bdfSopenharmony_ci		[OP_FCMP_ULT]	= LLVMRealULT,
509f08c3bdfSopenharmony_ci		[OP_FCMP_UGT]	= LLVMRealUGT,
510f08c3bdfSopenharmony_ci		[OP_FCMP_UNO]	= LLVMRealUNO,
511f08c3bdfSopenharmony_ci	};
512f08c3bdfSopenharmony_ci
513f08c3bdfSopenharmony_ci	return trans_tbl[opcode];
514f08c3bdfSopenharmony_ci}
515f08c3bdfSopenharmony_ci
516f08c3bdfSopenharmony_cistatic LLVMIntPredicate translate_op(int opcode)
517f08c3bdfSopenharmony_ci{
518f08c3bdfSopenharmony_ci	static const LLVMIntPredicate trans_tbl[] = {
519f08c3bdfSopenharmony_ci		[OP_SET_EQ]	= LLVMIntEQ,
520f08c3bdfSopenharmony_ci		[OP_SET_NE]	= LLVMIntNE,
521f08c3bdfSopenharmony_ci		[OP_SET_LE]	= LLVMIntSLE,
522f08c3bdfSopenharmony_ci		[OP_SET_GE]	= LLVMIntSGE,
523f08c3bdfSopenharmony_ci		[OP_SET_LT]	= LLVMIntSLT,
524f08c3bdfSopenharmony_ci		[OP_SET_GT]	= LLVMIntSGT,
525f08c3bdfSopenharmony_ci		[OP_SET_B]	= LLVMIntULT,
526f08c3bdfSopenharmony_ci		[OP_SET_A]	= LLVMIntUGT,
527f08c3bdfSopenharmony_ci		[OP_SET_BE]	= LLVMIntULE,
528f08c3bdfSopenharmony_ci		[OP_SET_AE]	= LLVMIntUGE,
529f08c3bdfSopenharmony_ci	};
530f08c3bdfSopenharmony_ci
531f08c3bdfSopenharmony_ci	return trans_tbl[opcode];
532f08c3bdfSopenharmony_ci}
533f08c3bdfSopenharmony_ci
534f08c3bdfSopenharmony_cistatic void output_op_binary(struct function *fn, struct instruction *insn)
535f08c3bdfSopenharmony_ci{
536f08c3bdfSopenharmony_ci	LLVMValueRef lhs, rhs, target;
537f08c3bdfSopenharmony_ci	char target_name[64];
538f08c3bdfSopenharmony_ci
539f08c3bdfSopenharmony_ci	lhs = get_ioperand(fn, insn->type, insn->src1);
540f08c3bdfSopenharmony_ci	rhs = get_ioperand(fn, insn->type, insn->src2);
541f08c3bdfSopenharmony_ci
542f08c3bdfSopenharmony_ci	pseudo_name(insn->target, target_name);
543f08c3bdfSopenharmony_ci
544f08c3bdfSopenharmony_ci	switch (insn->opcode) {
545f08c3bdfSopenharmony_ci	/* Binary */
546f08c3bdfSopenharmony_ci	case OP_ADD:
547f08c3bdfSopenharmony_ci		target = LLVMBuildAdd(fn->builder, lhs, rhs, target_name);
548f08c3bdfSopenharmony_ci		break;
549f08c3bdfSopenharmony_ci	case OP_SUB:
550f08c3bdfSopenharmony_ci		target = LLVMBuildSub(fn->builder, lhs, rhs, target_name);
551f08c3bdfSopenharmony_ci		break;
552f08c3bdfSopenharmony_ci	case OP_MUL:
553f08c3bdfSopenharmony_ci		target = LLVMBuildMul(fn->builder, lhs, rhs, target_name);
554f08c3bdfSopenharmony_ci		break;
555f08c3bdfSopenharmony_ci	case OP_DIVU:
556f08c3bdfSopenharmony_ci		target = LLVMBuildUDiv(fn->builder, lhs, rhs, target_name);
557f08c3bdfSopenharmony_ci		break;
558f08c3bdfSopenharmony_ci	case OP_DIVS:
559f08c3bdfSopenharmony_ci		assert(!is_float_type(insn->type));
560f08c3bdfSopenharmony_ci		target = LLVMBuildSDiv(fn->builder, lhs, rhs, target_name);
561f08c3bdfSopenharmony_ci		break;
562f08c3bdfSopenharmony_ci	case OP_MODU:
563f08c3bdfSopenharmony_ci		assert(!is_float_type(insn->type));
564f08c3bdfSopenharmony_ci		target = LLVMBuildURem(fn->builder, lhs, rhs, target_name);
565f08c3bdfSopenharmony_ci		break;
566f08c3bdfSopenharmony_ci	case OP_MODS:
567f08c3bdfSopenharmony_ci		assert(!is_float_type(insn->type));
568f08c3bdfSopenharmony_ci		target = LLVMBuildSRem(fn->builder, lhs, rhs, target_name);
569f08c3bdfSopenharmony_ci		break;
570f08c3bdfSopenharmony_ci	case OP_SHL:
571f08c3bdfSopenharmony_ci		assert(!is_float_type(insn->type));
572f08c3bdfSopenharmony_ci		target = LLVMBuildShl(fn->builder, lhs, rhs, target_name);
573f08c3bdfSopenharmony_ci		break;
574f08c3bdfSopenharmony_ci	case OP_LSR:
575f08c3bdfSopenharmony_ci		assert(!is_float_type(insn->type));
576f08c3bdfSopenharmony_ci		target = LLVMBuildLShr(fn->builder, lhs, rhs, target_name);
577f08c3bdfSopenharmony_ci		break;
578f08c3bdfSopenharmony_ci	case OP_ASR:
579f08c3bdfSopenharmony_ci		assert(!is_float_type(insn->type));
580f08c3bdfSopenharmony_ci		target = LLVMBuildAShr(fn->builder, lhs, rhs, target_name);
581f08c3bdfSopenharmony_ci		break;
582f08c3bdfSopenharmony_ci
583f08c3bdfSopenharmony_ci	/* floating-point */
584f08c3bdfSopenharmony_ci	case OP_FADD:
585f08c3bdfSopenharmony_ci		target = LLVMBuildFAdd(fn->builder, lhs, rhs, target_name);
586f08c3bdfSopenharmony_ci		break;
587f08c3bdfSopenharmony_ci	case OP_FSUB:
588f08c3bdfSopenharmony_ci		target = LLVMBuildFSub(fn->builder, lhs, rhs, target_name);
589f08c3bdfSopenharmony_ci		break;
590f08c3bdfSopenharmony_ci	case OP_FMUL:
591f08c3bdfSopenharmony_ci		target = LLVMBuildFMul(fn->builder, lhs, rhs, target_name);
592f08c3bdfSopenharmony_ci		break;
593f08c3bdfSopenharmony_ci	case OP_FDIV:
594f08c3bdfSopenharmony_ci		target = LLVMBuildFDiv(fn->builder, lhs, rhs, target_name);
595f08c3bdfSopenharmony_ci		break;
596f08c3bdfSopenharmony_ci
597f08c3bdfSopenharmony_ci	/* Logical */
598f08c3bdfSopenharmony_ci	case OP_AND:
599f08c3bdfSopenharmony_ci		assert(!is_float_type(insn->type));
600f08c3bdfSopenharmony_ci		target = LLVMBuildAnd(fn->builder, lhs, rhs, target_name);
601f08c3bdfSopenharmony_ci		break;
602f08c3bdfSopenharmony_ci	case OP_OR:
603f08c3bdfSopenharmony_ci		assert(!is_float_type(insn->type));
604f08c3bdfSopenharmony_ci		target = LLVMBuildOr(fn->builder, lhs, rhs, target_name);
605f08c3bdfSopenharmony_ci		break;
606f08c3bdfSopenharmony_ci	case OP_XOR:
607f08c3bdfSopenharmony_ci		assert(!is_float_type(insn->type));
608f08c3bdfSopenharmony_ci		target = LLVMBuildXor(fn->builder, lhs, rhs, target_name);
609f08c3bdfSopenharmony_ci		break;
610f08c3bdfSopenharmony_ci	default:
611f08c3bdfSopenharmony_ci		assert(0);
612f08c3bdfSopenharmony_ci		break;
613f08c3bdfSopenharmony_ci	}
614f08c3bdfSopenharmony_ci
615f08c3bdfSopenharmony_ci	target = adjust_type(fn, insn->type, target);
616f08c3bdfSopenharmony_ci	insn->target->priv = target;
617f08c3bdfSopenharmony_ci}
618f08c3bdfSopenharmony_ci
619f08c3bdfSopenharmony_cistatic void output_op_compare(struct function *fn, struct instruction *insn)
620f08c3bdfSopenharmony_ci{
621f08c3bdfSopenharmony_ci	LLVMValueRef lhs, rhs, target;
622f08c3bdfSopenharmony_ci	char target_name[64];
623f08c3bdfSopenharmony_ci
624f08c3bdfSopenharmony_ci	lhs = pseudo_to_value(fn, NULL, insn->src1);
625f08c3bdfSopenharmony_ci	if (insn->src2->type == PSEUDO_VAL)
626f08c3bdfSopenharmony_ci		rhs = constant_value(insn->src2->value, LLVMTypeOf(lhs));
627f08c3bdfSopenharmony_ci	else
628f08c3bdfSopenharmony_ci		rhs = pseudo_to_value(fn, NULL, insn->src2);
629f08c3bdfSopenharmony_ci	if (!rhs)
630f08c3bdfSopenharmony_ci		rhs = LLVMGetUndef(symbol_type(insn->type));
631f08c3bdfSopenharmony_ci
632f08c3bdfSopenharmony_ci	pseudo_name(insn->target, target_name);
633f08c3bdfSopenharmony_ci
634f08c3bdfSopenharmony_ci	LLVMTypeRef dst_type = insn_symbol_type(insn);
635f08c3bdfSopenharmony_ci
636f08c3bdfSopenharmony_ci	switch  (LLVMGetTypeKind(LLVMTypeOf(lhs))) {
637f08c3bdfSopenharmony_ci	case LLVMPointerTypeKind:
638f08c3bdfSopenharmony_ci		lhs = value_to_pvalue(fn, &ptr_ctype, lhs);
639f08c3bdfSopenharmony_ci		rhs = value_to_pvalue(fn, &ptr_ctype, rhs);
640f08c3bdfSopenharmony_ci		/* fall through */
641f08c3bdfSopenharmony_ci
642f08c3bdfSopenharmony_ci	case LLVMIntegerTypeKind: {
643f08c3bdfSopenharmony_ci		LLVMIntPredicate op = translate_op(insn->opcode);
644f08c3bdfSopenharmony_ci
645f08c3bdfSopenharmony_ci		if (LLVMGetTypeKind(LLVMTypeOf(rhs)) == LLVMPointerTypeKind) {
646f08c3bdfSopenharmony_ci			LLVMTypeRef ltype = LLVMTypeOf(lhs);
647f08c3bdfSopenharmony_ci			rhs = LLVMBuildPtrToInt(fn->builder, rhs, ltype, "");
648f08c3bdfSopenharmony_ci		}
649f08c3bdfSopenharmony_ci		target = LLVMBuildICmp(fn->builder, op, lhs, rhs, target_name);
650f08c3bdfSopenharmony_ci		break;
651f08c3bdfSopenharmony_ci	}
652f08c3bdfSopenharmony_ci	case LLVMHalfTypeKind:
653f08c3bdfSopenharmony_ci	case LLVMFloatTypeKind:
654f08c3bdfSopenharmony_ci	case LLVMDoubleTypeKind:
655f08c3bdfSopenharmony_ci	case LLVMX86_FP80TypeKind:
656f08c3bdfSopenharmony_ci	case LLVMFP128TypeKind:
657f08c3bdfSopenharmony_ci	case LLVMPPC_FP128TypeKind: {
658f08c3bdfSopenharmony_ci		LLVMRealPredicate op = translate_fop(insn->opcode);
659f08c3bdfSopenharmony_ci
660f08c3bdfSopenharmony_ci		target = LLVMBuildFCmp(fn->builder, op, lhs, rhs, target_name);
661f08c3bdfSopenharmony_ci		break;
662f08c3bdfSopenharmony_ci	}
663f08c3bdfSopenharmony_ci	default:
664f08c3bdfSopenharmony_ci		assert(0);
665f08c3bdfSopenharmony_ci	}
666f08c3bdfSopenharmony_ci
667f08c3bdfSopenharmony_ci	target = LLVMBuildZExt(fn->builder, target, dst_type, target_name);
668f08c3bdfSopenharmony_ci
669f08c3bdfSopenharmony_ci	insn->target->priv = target;
670f08c3bdfSopenharmony_ci}
671f08c3bdfSopenharmony_ci
672f08c3bdfSopenharmony_cistatic void output_op_ret(struct function *fn, struct instruction *insn)
673f08c3bdfSopenharmony_ci{
674f08c3bdfSopenharmony_ci	pseudo_t pseudo = insn->src;
675f08c3bdfSopenharmony_ci
676f08c3bdfSopenharmony_ci	if (pseudo && pseudo != VOID) {
677f08c3bdfSopenharmony_ci		LLVMValueRef result = get_operand(fn, insn->type, pseudo);
678f08c3bdfSopenharmony_ci		LLVMBuildRet(fn->builder, result);
679f08c3bdfSopenharmony_ci	} else
680f08c3bdfSopenharmony_ci		LLVMBuildRetVoid(fn->builder);
681f08c3bdfSopenharmony_ci}
682f08c3bdfSopenharmony_ci
683f08c3bdfSopenharmony_cistatic LLVMValueRef calc_memop_addr(struct function *fn, struct instruction *insn)
684f08c3bdfSopenharmony_ci{
685f08c3bdfSopenharmony_ci	LLVMTypeRef int_type, addr_type;
686f08c3bdfSopenharmony_ci	LLVMValueRef src, off, addr;
687f08c3bdfSopenharmony_ci	unsigned int as;
688f08c3bdfSopenharmony_ci
689f08c3bdfSopenharmony_ci	/* int type large enough to hold a pointer */
690f08c3bdfSopenharmony_ci	int_type = LLVMIntType(bits_in_pointer);
691f08c3bdfSopenharmony_ci	off = LLVMConstInt(int_type, insn->offset, 0);
692f08c3bdfSopenharmony_ci
693f08c3bdfSopenharmony_ci	/* convert src to the effective pointer type */
694f08c3bdfSopenharmony_ci	src = pseudo_to_value(fn, insn->type, insn->src);
695f08c3bdfSopenharmony_ci	as = LLVMGetPointerAddressSpace(LLVMTypeOf(src));
696f08c3bdfSopenharmony_ci	addr_type = LLVMPointerType(insn_symbol_type(insn), as);
697f08c3bdfSopenharmony_ci	src = LLVMBuildPointerCast(fn->builder, src, addr_type, LLVMGetValueName(src));
698f08c3bdfSopenharmony_ci
699f08c3bdfSopenharmony_ci	/* addr = src + off */
700f08c3bdfSopenharmony_ci	addr = calc_gep(fn->builder, src, off);
701f08c3bdfSopenharmony_ci	return addr;
702f08c3bdfSopenharmony_ci}
703f08c3bdfSopenharmony_ci
704f08c3bdfSopenharmony_ci
705f08c3bdfSopenharmony_cistatic void output_op_load(struct function *fn, struct instruction *insn)
706f08c3bdfSopenharmony_ci{
707f08c3bdfSopenharmony_ci	LLVMValueRef addr, target;
708f08c3bdfSopenharmony_ci	char name[MAX_PSEUDO_NAME];
709f08c3bdfSopenharmony_ci
710f08c3bdfSopenharmony_ci	addr = calc_memop_addr(fn, insn);
711f08c3bdfSopenharmony_ci
712f08c3bdfSopenharmony_ci	/* perform load */
713f08c3bdfSopenharmony_ci	pseudo_name(insn->target, name);
714f08c3bdfSopenharmony_ci	target = LLVMBuildLoad(fn->builder, addr, name);
715f08c3bdfSopenharmony_ci
716f08c3bdfSopenharmony_ci	insn->target->priv = target;
717f08c3bdfSopenharmony_ci}
718f08c3bdfSopenharmony_ci
719f08c3bdfSopenharmony_cistatic void output_op_store(struct function *fn, struct instruction *insn)
720f08c3bdfSopenharmony_ci{
721f08c3bdfSopenharmony_ci	LLVMValueRef addr, target_in;
722f08c3bdfSopenharmony_ci
723f08c3bdfSopenharmony_ci	addr = calc_memop_addr(fn, insn);
724f08c3bdfSopenharmony_ci
725f08c3bdfSopenharmony_ci	target_in = pseudo_to_rvalue(fn, insn->type, insn->target);
726f08c3bdfSopenharmony_ci
727f08c3bdfSopenharmony_ci	/* perform store */
728f08c3bdfSopenharmony_ci	LLVMBuildStore(fn->builder, target_in, addr);
729f08c3bdfSopenharmony_ci}
730f08c3bdfSopenharmony_ci
731f08c3bdfSopenharmony_cistatic LLVMValueRef bool_value(struct function *fn, LLVMValueRef value)
732f08c3bdfSopenharmony_ci{
733f08c3bdfSopenharmony_ci	if (LLVMTypeOf(value) != LLVMInt1Type())
734f08c3bdfSopenharmony_ci		value = LLVMBuildIsNotNull(fn->builder, value, LLVMGetValueName(value));
735f08c3bdfSopenharmony_ci
736f08c3bdfSopenharmony_ci	return value;
737f08c3bdfSopenharmony_ci}
738f08c3bdfSopenharmony_ci
739f08c3bdfSopenharmony_cistatic void output_op_cbr(struct function *fn, struct instruction *br)
740f08c3bdfSopenharmony_ci{
741f08c3bdfSopenharmony_ci	LLVMValueRef cond = bool_value(fn,
742f08c3bdfSopenharmony_ci			pseudo_to_value(fn, NULL, br->cond));
743f08c3bdfSopenharmony_ci
744f08c3bdfSopenharmony_ci	LLVMBuildCondBr(fn->builder, cond,
745f08c3bdfSopenharmony_ci			br->bb_true->priv,
746f08c3bdfSopenharmony_ci			br->bb_false->priv);
747f08c3bdfSopenharmony_ci}
748f08c3bdfSopenharmony_ci
749f08c3bdfSopenharmony_cistatic void output_op_br(struct function *fn, struct instruction *br)
750f08c3bdfSopenharmony_ci{
751f08c3bdfSopenharmony_ci	LLVMBuildBr(fn->builder, br->bb_true->priv);
752f08c3bdfSopenharmony_ci}
753f08c3bdfSopenharmony_ci
754f08c3bdfSopenharmony_cistatic void output_op_sel(struct function *fn, struct instruction *insn)
755f08c3bdfSopenharmony_ci{
756f08c3bdfSopenharmony_ci	LLVMValueRef target, src1, src2, src3;
757f08c3bdfSopenharmony_ci	char name[MAX_PSEUDO_NAME];
758f08c3bdfSopenharmony_ci
759f08c3bdfSopenharmony_ci	src1 = bool_value(fn, pseudo_to_value(fn, NULL, insn->src1));
760f08c3bdfSopenharmony_ci	src2 = get_operand(fn, insn->type, insn->src2);
761f08c3bdfSopenharmony_ci	src3 = get_operand(fn, insn->type, insn->src3);
762f08c3bdfSopenharmony_ci
763f08c3bdfSopenharmony_ci	pseudo_name(insn->target, name);
764f08c3bdfSopenharmony_ci	target = LLVMBuildSelect(fn->builder, src1, src2, src3, name);
765f08c3bdfSopenharmony_ci
766f08c3bdfSopenharmony_ci	insn->target->priv = adjust_type(fn, insn->type, target);
767f08c3bdfSopenharmony_ci}
768f08c3bdfSopenharmony_ci
769f08c3bdfSopenharmony_cistatic void output_op_switch(struct function *fn, struct instruction *insn)
770f08c3bdfSopenharmony_ci{
771f08c3bdfSopenharmony_ci	LLVMValueRef sw_val, target;
772f08c3bdfSopenharmony_ci	struct basic_block *def = NULL;
773f08c3bdfSopenharmony_ci	struct multijmp *jmp;
774f08c3bdfSopenharmony_ci	int n_jmp = 0;
775f08c3bdfSopenharmony_ci
776f08c3bdfSopenharmony_ci	FOR_EACH_PTR(insn->multijmp_list, jmp) {
777f08c3bdfSopenharmony_ci		if (jmp->begin <= jmp->end) {
778f08c3bdfSopenharmony_ci			n_jmp += (jmp->end - jmp->begin) + 1;
779f08c3bdfSopenharmony_ci		} else					/* default case */
780f08c3bdfSopenharmony_ci			def = jmp->target;
781f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(jmp);
782f08c3bdfSopenharmony_ci
783f08c3bdfSopenharmony_ci	sw_val = get_ioperand(fn, insn->type, insn->cond);
784f08c3bdfSopenharmony_ci	target = LLVMBuildSwitch(fn->builder, sw_val,
785f08c3bdfSopenharmony_ci				 def ? def->priv : NULL, n_jmp);
786f08c3bdfSopenharmony_ci
787f08c3bdfSopenharmony_ci	FOR_EACH_PTR(insn->multijmp_list, jmp) {
788f08c3bdfSopenharmony_ci		long long val;
789f08c3bdfSopenharmony_ci
790f08c3bdfSopenharmony_ci		for (val = jmp->begin; val <= jmp->end; val++) {
791f08c3bdfSopenharmony_ci			LLVMValueRef Val = val_to_value(val, insn->type);
792f08c3bdfSopenharmony_ci			LLVMAddCase(target, Val, jmp->target->priv);
793f08c3bdfSopenharmony_ci		}
794f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(jmp);
795f08c3bdfSopenharmony_ci}
796f08c3bdfSopenharmony_ci
797f08c3bdfSopenharmony_cistatic void output_op_call(struct function *fn, struct instruction *insn)
798f08c3bdfSopenharmony_ci{
799f08c3bdfSopenharmony_ci	LLVMValueRef target, func;
800f08c3bdfSopenharmony_ci	struct symbol *ctype;
801f08c3bdfSopenharmony_ci	int n_arg = 0, i;
802f08c3bdfSopenharmony_ci	struct pseudo *arg;
803f08c3bdfSopenharmony_ci	LLVMValueRef *args;
804f08c3bdfSopenharmony_ci	char name[64];
805f08c3bdfSopenharmony_ci
806f08c3bdfSopenharmony_ci	n_arg = pseudo_list_size(insn->arguments);
807f08c3bdfSopenharmony_ci	args = calloc(n_arg, sizeof(LLVMValueRef));
808f08c3bdfSopenharmony_ci
809f08c3bdfSopenharmony_ci	PREPARE_PTR_LIST(insn->fntypes, ctype);
810f08c3bdfSopenharmony_ci	if (insn->func->type == PSEUDO_REG || insn->func->type == PSEUDO_PHI)
811f08c3bdfSopenharmony_ci		func = get_operand(fn, ctype, insn->func);
812f08c3bdfSopenharmony_ci	else
813f08c3bdfSopenharmony_ci		func = pseudo_to_value(fn, ctype, insn->func);
814f08c3bdfSopenharmony_ci	i = 0;
815f08c3bdfSopenharmony_ci	FOR_EACH_PTR(insn->arguments, arg) {
816f08c3bdfSopenharmony_ci		NEXT_PTR_LIST(ctype);
817f08c3bdfSopenharmony_ci		args[i++] = pseudo_to_rvalue(fn, ctype, arg);
818f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(arg);
819f08c3bdfSopenharmony_ci	FINISH_PTR_LIST(ctype);
820f08c3bdfSopenharmony_ci
821f08c3bdfSopenharmony_ci	pseudo_name(insn->target, name);
822f08c3bdfSopenharmony_ci	target = LLVMBuildCall(fn->builder, func, args, n_arg, name);
823f08c3bdfSopenharmony_ci
824f08c3bdfSopenharmony_ci	insn->target->priv = target;
825f08c3bdfSopenharmony_ci}
826f08c3bdfSopenharmony_ci
827f08c3bdfSopenharmony_cistatic void output_op_phisrc(struct function *fn, struct instruction *insn)
828f08c3bdfSopenharmony_ci{
829f08c3bdfSopenharmony_ci	insn->src->priv = get_operand(fn, insn->type, insn->src);
830f08c3bdfSopenharmony_ci}
831f08c3bdfSopenharmony_ci
832f08c3bdfSopenharmony_cistatic void output_op_phi(struct function *fn, struct instruction *insn)
833f08c3bdfSopenharmony_ci{
834f08c3bdfSopenharmony_ci	LLVMTypeRef dst_type = insn_symbol_type(insn);
835f08c3bdfSopenharmony_ci
836f08c3bdfSopenharmony_ci	insn->target->priv = LLVMBuildPhi(fn->builder, dst_type, "");
837f08c3bdfSopenharmony_ci}
838f08c3bdfSopenharmony_ci
839f08c3bdfSopenharmony_cistatic void output_op_ptrcast(struct function *fn, struct instruction *insn)
840f08c3bdfSopenharmony_ci{
841f08c3bdfSopenharmony_ci	LLVMValueRef src, target;
842f08c3bdfSopenharmony_ci	LLVMTypeRef dtype;
843f08c3bdfSopenharmony_ci	struct symbol *otype = insn->orig_type;
844f08c3bdfSopenharmony_ci	LLVMOpcode op;
845f08c3bdfSopenharmony_ci	char target_name[64];
846f08c3bdfSopenharmony_ci
847f08c3bdfSopenharmony_ci	src = get_operand(fn, otype, insn->src);
848f08c3bdfSopenharmony_ci	pseudo_name(insn->target, target_name);
849f08c3bdfSopenharmony_ci
850f08c3bdfSopenharmony_ci	dtype = symbol_type(insn->type);
851f08c3bdfSopenharmony_ci	switch (insn->opcode) {
852f08c3bdfSopenharmony_ci	case OP_UTPTR:
853f08c3bdfSopenharmony_ci	case OP_SEXT:			// FIXME
854f08c3bdfSopenharmony_ci		assert(is_int_type(otype));
855f08c3bdfSopenharmony_ci		assert(is_ptr_type(insn->type));
856f08c3bdfSopenharmony_ci		op = LLVMIntToPtr;
857f08c3bdfSopenharmony_ci		break;
858f08c3bdfSopenharmony_ci	case OP_PTRTU:
859f08c3bdfSopenharmony_ci		assert(is_ptr_type(otype));
860f08c3bdfSopenharmony_ci		assert(is_int_type(insn->type));
861f08c3bdfSopenharmony_ci		op = LLVMPtrToInt;
862f08c3bdfSopenharmony_ci		break;
863f08c3bdfSopenharmony_ci	case OP_PTRCAST:
864f08c3bdfSopenharmony_ci	case OP_ZEXT:			// FIXME
865f08c3bdfSopenharmony_ci		assert(is_ptr_type(otype));
866f08c3bdfSopenharmony_ci		assert(is_ptr_type(insn->type));
867f08c3bdfSopenharmony_ci		op = LLVMBitCast;
868f08c3bdfSopenharmony_ci		break;
869f08c3bdfSopenharmony_ci	default:
870f08c3bdfSopenharmony_ci		assert(0);
871f08c3bdfSopenharmony_ci	}
872f08c3bdfSopenharmony_ci
873f08c3bdfSopenharmony_ci	target = LLVMBuildCast(fn->builder, op, src, dtype, target_name);
874f08c3bdfSopenharmony_ci	insn->target->priv = target;
875f08c3bdfSopenharmony_ci}
876f08c3bdfSopenharmony_ci
877f08c3bdfSopenharmony_cistatic void output_op_cast(struct function *fn, struct instruction *insn, LLVMOpcode op)
878f08c3bdfSopenharmony_ci{
879f08c3bdfSopenharmony_ci	LLVMValueRef src, target;
880f08c3bdfSopenharmony_ci	LLVMTypeRef dtype;
881f08c3bdfSopenharmony_ci	struct symbol *otype = insn->orig_type;
882f08c3bdfSopenharmony_ci	char target_name[64];
883f08c3bdfSopenharmony_ci
884f08c3bdfSopenharmony_ci	if (is_ptr_type(insn->type))	// cast to void* is OP_CAST ...
885f08c3bdfSopenharmony_ci		return output_op_ptrcast(fn, insn);
886f08c3bdfSopenharmony_ci
887f08c3bdfSopenharmony_ci	assert(is_int_type(insn->type));
888f08c3bdfSopenharmony_ci
889f08c3bdfSopenharmony_ci	src = get_operand(fn, otype, insn->src);
890f08c3bdfSopenharmony_ci	pseudo_name(insn->target, target_name);
891f08c3bdfSopenharmony_ci
892f08c3bdfSopenharmony_ci	dtype = symbol_type(insn->type);
893f08c3bdfSopenharmony_ci	if (is_ptr_type(otype)) {
894f08c3bdfSopenharmony_ci		op = LLVMPtrToInt;
895f08c3bdfSopenharmony_ci	} else if (is_float_type(otype)) {
896f08c3bdfSopenharmony_ci		assert(op == LLVMFPToUI || op == LLVMFPToSI);
897f08c3bdfSopenharmony_ci	} else if (is_int_type(otype)) {
898f08c3bdfSopenharmony_ci		unsigned int width = otype->bit_size;
899f08c3bdfSopenharmony_ci		if (insn->size < width)
900f08c3bdfSopenharmony_ci			op = LLVMTrunc;
901f08c3bdfSopenharmony_ci		else if (insn->size == width)
902f08c3bdfSopenharmony_ci			op = LLVMBitCast;
903f08c3bdfSopenharmony_ci	} else {
904f08c3bdfSopenharmony_ci		assert(0);
905f08c3bdfSopenharmony_ci	}
906f08c3bdfSopenharmony_ci
907f08c3bdfSopenharmony_ci	target = LLVMBuildCast(fn->builder, op, src, dtype, target_name);
908f08c3bdfSopenharmony_ci	insn->target->priv = target;
909f08c3bdfSopenharmony_ci}
910f08c3bdfSopenharmony_ci
911f08c3bdfSopenharmony_cistatic void output_op_fpcast(struct function *fn, struct instruction *insn)
912f08c3bdfSopenharmony_ci{
913f08c3bdfSopenharmony_ci	LLVMTypeRef dtype = symbol_type(insn->type);
914f08c3bdfSopenharmony_ci	LLVMValueRef src, target;
915f08c3bdfSopenharmony_ci	struct symbol *otype = insn->orig_type;
916f08c3bdfSopenharmony_ci	char name[64];
917f08c3bdfSopenharmony_ci
918f08c3bdfSopenharmony_ci	assert(is_float_type(insn->type));
919f08c3bdfSopenharmony_ci
920f08c3bdfSopenharmony_ci	pseudo_name(insn->target, name);
921f08c3bdfSopenharmony_ci	src = get_operand(fn, otype, insn->src);
922f08c3bdfSopenharmony_ci	switch (insn->opcode) {
923f08c3bdfSopenharmony_ci	case OP_FCVTF:
924f08c3bdfSopenharmony_ci		target = LLVMBuildFPCast(fn->builder, src, dtype, name);
925f08c3bdfSopenharmony_ci		break;
926f08c3bdfSopenharmony_ci	case OP_SCVTF:
927f08c3bdfSopenharmony_ci		target = LLVMBuildSIToFP(fn->builder, src, dtype, name);
928f08c3bdfSopenharmony_ci		break;
929f08c3bdfSopenharmony_ci	case OP_UCVTF:
930f08c3bdfSopenharmony_ci		target = LLVMBuildUIToFP(fn->builder, src, dtype, name);
931f08c3bdfSopenharmony_ci		break;
932f08c3bdfSopenharmony_ci	default:
933f08c3bdfSopenharmony_ci		assert(0);
934f08c3bdfSopenharmony_ci	}
935f08c3bdfSopenharmony_ci	insn->target->priv = target;
936f08c3bdfSopenharmony_ci}
937f08c3bdfSopenharmony_ci
938f08c3bdfSopenharmony_cistatic void output_op_label(struct function *fn, struct instruction *insn)
939f08c3bdfSopenharmony_ci{
940f08c3bdfSopenharmony_ci	insn->target->priv = LLVMBlockAddress(fn->fn, insn->bb_true->priv);
941f08c3bdfSopenharmony_ci}
942f08c3bdfSopenharmony_ci
943f08c3bdfSopenharmony_cistatic void output_op_setval(struct function *fn, struct instruction *insn)
944f08c3bdfSopenharmony_ci{
945f08c3bdfSopenharmony_ci	struct expression *val = insn->val;
946f08c3bdfSopenharmony_ci	LLVMValueRef target;
947f08c3bdfSopenharmony_ci
948f08c3bdfSopenharmony_ci	switch (val->type) {
949f08c3bdfSopenharmony_ci	case EXPR_LABEL:
950f08c3bdfSopenharmony_ci		target = LLVMBlockAddress(fn->fn, val->symbol->bb_target->priv);
951f08c3bdfSopenharmony_ci		break;
952f08c3bdfSopenharmony_ci	default:
953f08c3bdfSopenharmony_ci		assert(0);
954f08c3bdfSopenharmony_ci	}
955f08c3bdfSopenharmony_ci
956f08c3bdfSopenharmony_ci	insn->target->priv = target;
957f08c3bdfSopenharmony_ci}
958f08c3bdfSopenharmony_ci
959f08c3bdfSopenharmony_cistatic void output_op_setfval(struct function *fn, struct instruction *insn)
960f08c3bdfSopenharmony_ci{
961f08c3bdfSopenharmony_ci	LLVMTypeRef dtype = symbol_type(insn->type);
962f08c3bdfSopenharmony_ci	LLVMValueRef target;
963f08c3bdfSopenharmony_ci
964f08c3bdfSopenharmony_ci	target = LLVMConstReal(dtype, insn->fvalue);
965f08c3bdfSopenharmony_ci	insn->target->priv = target;
966f08c3bdfSopenharmony_ci}
967f08c3bdfSopenharmony_ci
968f08c3bdfSopenharmony_cistatic void output_insn(struct function *fn, struct instruction *insn)
969f08c3bdfSopenharmony_ci{
970f08c3bdfSopenharmony_ci	switch (insn->opcode) {
971f08c3bdfSopenharmony_ci	case OP_RET:
972f08c3bdfSopenharmony_ci		output_op_ret(fn, insn);
973f08c3bdfSopenharmony_ci		break;
974f08c3bdfSopenharmony_ci	case OP_BR:
975f08c3bdfSopenharmony_ci		output_op_br(fn, insn);
976f08c3bdfSopenharmony_ci		break;
977f08c3bdfSopenharmony_ci	case OP_CBR:
978f08c3bdfSopenharmony_ci		output_op_cbr(fn, insn);
979f08c3bdfSopenharmony_ci		break;
980f08c3bdfSopenharmony_ci	case OP_SYMADDR:
981f08c3bdfSopenharmony_ci		assert(0);
982f08c3bdfSopenharmony_ci		break;
983f08c3bdfSopenharmony_ci	case OP_LABEL:
984f08c3bdfSopenharmony_ci		output_op_label(fn, insn);
985f08c3bdfSopenharmony_ci		break;
986f08c3bdfSopenharmony_ci	case OP_SETVAL:
987f08c3bdfSopenharmony_ci		output_op_setval(fn, insn);
988f08c3bdfSopenharmony_ci		break;
989f08c3bdfSopenharmony_ci	case OP_SETFVAL:
990f08c3bdfSopenharmony_ci		output_op_setfval(fn, insn);
991f08c3bdfSopenharmony_ci		break;
992f08c3bdfSopenharmony_ci	case OP_SWITCH:
993f08c3bdfSopenharmony_ci		output_op_switch(fn, insn);
994f08c3bdfSopenharmony_ci		break;
995f08c3bdfSopenharmony_ci	case OP_COMPUTEDGOTO:
996f08c3bdfSopenharmony_ci		assert(0);
997f08c3bdfSopenharmony_ci		break;
998f08c3bdfSopenharmony_ci	case OP_PHISOURCE:
999f08c3bdfSopenharmony_ci		output_op_phisrc(fn, insn);
1000f08c3bdfSopenharmony_ci		break;
1001f08c3bdfSopenharmony_ci	case OP_PHI:
1002f08c3bdfSopenharmony_ci		output_op_phi(fn, insn);
1003f08c3bdfSopenharmony_ci		break;
1004f08c3bdfSopenharmony_ci	case OP_LOAD:
1005f08c3bdfSopenharmony_ci		output_op_load(fn, insn);
1006f08c3bdfSopenharmony_ci		break;
1007f08c3bdfSopenharmony_ci	case OP_STORE:
1008f08c3bdfSopenharmony_ci		output_op_store(fn, insn);
1009f08c3bdfSopenharmony_ci		break;
1010f08c3bdfSopenharmony_ci	case OP_INLINED_CALL:
1011f08c3bdfSopenharmony_ci		break;
1012f08c3bdfSopenharmony_ci	case OP_CALL:
1013f08c3bdfSopenharmony_ci		output_op_call(fn, insn);
1014f08c3bdfSopenharmony_ci		break;
1015f08c3bdfSopenharmony_ci	case OP_ZEXT:
1016f08c3bdfSopenharmony_ci		output_op_cast(fn, insn, LLVMZExt);
1017f08c3bdfSopenharmony_ci		break;
1018f08c3bdfSopenharmony_ci	case OP_SEXT:
1019f08c3bdfSopenharmony_ci		output_op_cast(fn, insn, LLVMSExt);
1020f08c3bdfSopenharmony_ci		break;
1021f08c3bdfSopenharmony_ci	case OP_TRUNC:
1022f08c3bdfSopenharmony_ci		output_op_cast(fn, insn, LLVMTrunc);
1023f08c3bdfSopenharmony_ci		break;
1024f08c3bdfSopenharmony_ci	case OP_FCVTU:
1025f08c3bdfSopenharmony_ci		output_op_cast(fn, insn, LLVMFPToUI);
1026f08c3bdfSopenharmony_ci		break;
1027f08c3bdfSopenharmony_ci	case OP_FCVTS:
1028f08c3bdfSopenharmony_ci		output_op_cast(fn, insn, LLVMFPToSI);
1029f08c3bdfSopenharmony_ci		break;
1030f08c3bdfSopenharmony_ci	case OP_UCVTF: case OP_SCVTF:
1031f08c3bdfSopenharmony_ci	case OP_FCVTF:
1032f08c3bdfSopenharmony_ci		output_op_fpcast(fn, insn);
1033f08c3bdfSopenharmony_ci		break;
1034f08c3bdfSopenharmony_ci	case OP_UTPTR:
1035f08c3bdfSopenharmony_ci	case OP_PTRTU:
1036f08c3bdfSopenharmony_ci	case OP_PTRCAST:
1037f08c3bdfSopenharmony_ci		output_op_ptrcast(fn, insn);
1038f08c3bdfSopenharmony_ci		break;
1039f08c3bdfSopenharmony_ci	case OP_BINARY ... OP_BINARY_END:
1040f08c3bdfSopenharmony_ci		output_op_binary(fn, insn);
1041f08c3bdfSopenharmony_ci		break;
1042f08c3bdfSopenharmony_ci	case OP_FPCMP ... OP_BINCMP_END:
1043f08c3bdfSopenharmony_ci		output_op_compare(fn, insn);
1044f08c3bdfSopenharmony_ci		break;
1045f08c3bdfSopenharmony_ci	case OP_SEL:
1046f08c3bdfSopenharmony_ci		output_op_sel(fn, insn);
1047f08c3bdfSopenharmony_ci		break;
1048f08c3bdfSopenharmony_ci	case OP_SLICE:
1049f08c3bdfSopenharmony_ci		assert(0);
1050f08c3bdfSopenharmony_ci		break;
1051f08c3bdfSopenharmony_ci	case OP_NOT: {
1052f08c3bdfSopenharmony_ci		LLVMValueRef src, target;
1053f08c3bdfSopenharmony_ci		char target_name[64];
1054f08c3bdfSopenharmony_ci
1055f08c3bdfSopenharmony_ci		src = pseudo_to_value(fn, insn->type, insn->src);
1056f08c3bdfSopenharmony_ci
1057f08c3bdfSopenharmony_ci		pseudo_name(insn->target, target_name);
1058f08c3bdfSopenharmony_ci
1059f08c3bdfSopenharmony_ci		target = LLVMBuildNot(fn->builder, src, target_name);
1060f08c3bdfSopenharmony_ci
1061f08c3bdfSopenharmony_ci		insn->target->priv = target;
1062f08c3bdfSopenharmony_ci		break;
1063f08c3bdfSopenharmony_ci	}
1064f08c3bdfSopenharmony_ci	case OP_FNEG:
1065f08c3bdfSopenharmony_ci	case OP_NEG: {
1066f08c3bdfSopenharmony_ci		LLVMValueRef src, target;
1067f08c3bdfSopenharmony_ci		char target_name[64];
1068f08c3bdfSopenharmony_ci
1069f08c3bdfSopenharmony_ci		src = pseudo_to_value(fn, insn->type, insn->src);
1070f08c3bdfSopenharmony_ci
1071f08c3bdfSopenharmony_ci		pseudo_name(insn->target, target_name);
1072f08c3bdfSopenharmony_ci
1073f08c3bdfSopenharmony_ci		if (insn->opcode == OP_FNEG)
1074f08c3bdfSopenharmony_ci			target = LLVMBuildFNeg(fn->builder, src, target_name);
1075f08c3bdfSopenharmony_ci		else
1076f08c3bdfSopenharmony_ci			target = LLVMBuildNeg(fn->builder, src, target_name);
1077f08c3bdfSopenharmony_ci
1078f08c3bdfSopenharmony_ci		insn->target->priv = target;
1079f08c3bdfSopenharmony_ci		break;
1080f08c3bdfSopenharmony_ci	}
1081f08c3bdfSopenharmony_ci	case OP_CONTEXT:
1082f08c3bdfSopenharmony_ci		assert(0);
1083f08c3bdfSopenharmony_ci		break;
1084f08c3bdfSopenharmony_ci	case OP_RANGE:
1085f08c3bdfSopenharmony_ci		assert(0);
1086f08c3bdfSopenharmony_ci		break;
1087f08c3bdfSopenharmony_ci	case OP_NOP:
1088f08c3bdfSopenharmony_ci		assert(0);
1089f08c3bdfSopenharmony_ci		break;
1090f08c3bdfSopenharmony_ci	case OP_DEATHNOTE:
1091f08c3bdfSopenharmony_ci		break;
1092f08c3bdfSopenharmony_ci	case OP_ASM:
1093f08c3bdfSopenharmony_ci		assert(0);
1094f08c3bdfSopenharmony_ci		break;
1095f08c3bdfSopenharmony_ci	case OP_COPY:
1096f08c3bdfSopenharmony_ci		assert(0);
1097f08c3bdfSopenharmony_ci		break;
1098f08c3bdfSopenharmony_ci	default:
1099f08c3bdfSopenharmony_ci		break;
1100f08c3bdfSopenharmony_ci	}
1101f08c3bdfSopenharmony_ci}
1102f08c3bdfSopenharmony_ci
1103f08c3bdfSopenharmony_cistatic void output_bb(struct function *fn, struct basic_block *bb)
1104f08c3bdfSopenharmony_ci{
1105f08c3bdfSopenharmony_ci	struct instruction *insn;
1106f08c3bdfSopenharmony_ci
1107f08c3bdfSopenharmony_ci	FOR_EACH_PTR(bb->insns, insn) {
1108f08c3bdfSopenharmony_ci		if (!insn->bb)
1109f08c3bdfSopenharmony_ci			continue;
1110f08c3bdfSopenharmony_ci
1111f08c3bdfSopenharmony_ci		output_insn(fn, insn);
1112f08c3bdfSopenharmony_ci	}
1113f08c3bdfSopenharmony_ci	END_FOR_EACH_PTR(insn);
1114f08c3bdfSopenharmony_ci}
1115f08c3bdfSopenharmony_ci
1116f08c3bdfSopenharmony_ci#define MAX_ARGS	64
1117f08c3bdfSopenharmony_ci
1118f08c3bdfSopenharmony_cistatic void output_fn(LLVMModuleRef module, struct entrypoint *ep)
1119f08c3bdfSopenharmony_ci{
1120f08c3bdfSopenharmony_ci	struct symbol *sym = ep->name;
1121f08c3bdfSopenharmony_ci	struct symbol *base_type = sym->ctype.base_type;
1122f08c3bdfSopenharmony_ci	struct function function = { .module = module };
1123f08c3bdfSopenharmony_ci	struct basic_block *bb;
1124f08c3bdfSopenharmony_ci	int nr_args = 0;
1125f08c3bdfSopenharmony_ci	int i;
1126f08c3bdfSopenharmony_ci
1127f08c3bdfSopenharmony_ci	function.fn = get_sym_value(module, sym);
1128f08c3bdfSopenharmony_ci	LLVMSetFunctionCallConv(function.fn, LLVMCCallConv);
1129f08c3bdfSopenharmony_ci	LLVMSetLinkage(function.fn, function_linkage(sym));
1130f08c3bdfSopenharmony_ci
1131f08c3bdfSopenharmony_ci	function.builder = LLVMCreateBuilder();
1132f08c3bdfSopenharmony_ci
1133f08c3bdfSopenharmony_ci	/* give a name to each argument */
1134f08c3bdfSopenharmony_ci	nr_args = symbol_list_size(base_type->arguments);
1135f08c3bdfSopenharmony_ci	for (i = 0; i < nr_args; i++) {
1136f08c3bdfSopenharmony_ci		char name[MAX_PSEUDO_NAME];
1137f08c3bdfSopenharmony_ci		LLVMValueRef arg;
1138f08c3bdfSopenharmony_ci
1139f08c3bdfSopenharmony_ci		arg = LLVMGetParam(function.fn, i);
1140f08c3bdfSopenharmony_ci		snprintf(name, sizeof(name), "ARG%d.", i+1);
1141f08c3bdfSopenharmony_ci		LLVMSetValueName(arg, name);
1142f08c3bdfSopenharmony_ci	}
1143f08c3bdfSopenharmony_ci
1144f08c3bdfSopenharmony_ci	/* create the BBs */
1145f08c3bdfSopenharmony_ci	FOR_EACH_PTR(ep->bbs, bb) {
1146f08c3bdfSopenharmony_ci		static int nr_bb;
1147f08c3bdfSopenharmony_ci		LLVMBasicBlockRef bbr;
1148f08c3bdfSopenharmony_ci		char bbname[32];
1149f08c3bdfSopenharmony_ci
1150f08c3bdfSopenharmony_ci		sprintf(bbname, "L%d", nr_bb++);
1151f08c3bdfSopenharmony_ci		bbr = LLVMAppendBasicBlock(function.fn, bbname);
1152f08c3bdfSopenharmony_ci
1153f08c3bdfSopenharmony_ci		bb->priv = bbr;
1154f08c3bdfSopenharmony_ci	}
1155f08c3bdfSopenharmony_ci	END_FOR_EACH_PTR(bb);
1156f08c3bdfSopenharmony_ci
1157f08c3bdfSopenharmony_ci	FOR_EACH_PTR(ep->bbs, bb) {
1158f08c3bdfSopenharmony_ci		LLVMPositionBuilderAtEnd(function.builder, bb->priv);
1159f08c3bdfSopenharmony_ci
1160f08c3bdfSopenharmony_ci		output_bb(&function, bb);
1161f08c3bdfSopenharmony_ci	}
1162f08c3bdfSopenharmony_ci	END_FOR_EACH_PTR(bb);
1163f08c3bdfSopenharmony_ci
1164f08c3bdfSopenharmony_ci	FOR_EACH_PTR(ep->bbs, bb) {	// complete the OP_PHIs
1165f08c3bdfSopenharmony_ci		struct instruction *insn;
1166f08c3bdfSopenharmony_ci
1167f08c3bdfSopenharmony_ci		FOR_EACH_PTR(bb->insns, insn) {
1168f08c3bdfSopenharmony_ci			pseudo_t phi;
1169f08c3bdfSopenharmony_ci
1170f08c3bdfSopenharmony_ci			if (!insn->bb || insn->opcode != OP_PHI)
1171f08c3bdfSopenharmony_ci				continue;
1172f08c3bdfSopenharmony_ci
1173f08c3bdfSopenharmony_ci			FOR_EACH_PTR(insn->phi_list, phi) {
1174f08c3bdfSopenharmony_ci				struct instruction *phisrc;
1175f08c3bdfSopenharmony_ci				LLVMBasicBlockRef bref;
1176f08c3bdfSopenharmony_ci				LLVMValueRef vref;
1177f08c3bdfSopenharmony_ci
1178f08c3bdfSopenharmony_ci				if (phi == VOID)
1179f08c3bdfSopenharmony_ci					continue;
1180f08c3bdfSopenharmony_ci
1181f08c3bdfSopenharmony_ci				phisrc = phi->def;
1182f08c3bdfSopenharmony_ci				bref = phisrc->bb->priv;
1183f08c3bdfSopenharmony_ci				vref = phisrc->src->priv;
1184f08c3bdfSopenharmony_ci				LLVMAddIncoming(insn->target->priv, &vref, &bref, 1);
1185f08c3bdfSopenharmony_ci			} END_FOR_EACH_PTR(phi);
1186f08c3bdfSopenharmony_ci		} END_FOR_EACH_PTR(insn);
1187f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(bb);
1188f08c3bdfSopenharmony_ci}
1189f08c3bdfSopenharmony_ci
1190f08c3bdfSopenharmony_cistatic LLVMValueRef output_data(LLVMModuleRef module, struct symbol *sym)
1191f08c3bdfSopenharmony_ci{
1192f08c3bdfSopenharmony_ci	struct expression *initializer = sym->initializer;
1193f08c3bdfSopenharmony_ci	LLVMValueRef initial_value;
1194f08c3bdfSopenharmony_ci	LLVMValueRef data;
1195f08c3bdfSopenharmony_ci	const char *name;
1196f08c3bdfSopenharmony_ci
1197f08c3bdfSopenharmony_ci	if (initializer) {
1198f08c3bdfSopenharmony_ci		switch (initializer->type) {
1199f08c3bdfSopenharmony_ci		case EXPR_VALUE:
1200f08c3bdfSopenharmony_ci			initial_value = LLVMConstInt(symbol_type(sym), initializer->value, 1);
1201f08c3bdfSopenharmony_ci			break;
1202f08c3bdfSopenharmony_ci		case EXPR_FVALUE:
1203f08c3bdfSopenharmony_ci			initial_value = LLVMConstReal(symbol_type(sym), initializer->fvalue);
1204f08c3bdfSopenharmony_ci			break;
1205f08c3bdfSopenharmony_ci		case EXPR_SYMBOL: {
1206f08c3bdfSopenharmony_ci			struct symbol *sym = initializer->symbol;
1207f08c3bdfSopenharmony_ci
1208f08c3bdfSopenharmony_ci			initial_value = LLVMGetNamedGlobal(module, show_ident(sym->ident));
1209f08c3bdfSopenharmony_ci			if (!initial_value)
1210f08c3bdfSopenharmony_ci				initial_value = output_data(module, sym);
1211f08c3bdfSopenharmony_ci			break;
1212f08c3bdfSopenharmony_ci		}
1213f08c3bdfSopenharmony_ci		case EXPR_STRING: {
1214f08c3bdfSopenharmony_ci			const char *s = initializer->string->data;
1215f08c3bdfSopenharmony_ci
1216f08c3bdfSopenharmony_ci			initial_value = LLVMConstString(strdup(s), strlen(s) + 1, true);
1217f08c3bdfSopenharmony_ci			break;
1218f08c3bdfSopenharmony_ci		}
1219f08c3bdfSopenharmony_ci		default:
1220f08c3bdfSopenharmony_ci			warning(initializer->pos, "can't initialize type: %s", show_typename(sym));
1221f08c3bdfSopenharmony_ci			initial_value = NULL;
1222f08c3bdfSopenharmony_ci			break;
1223f08c3bdfSopenharmony_ci		}
1224f08c3bdfSopenharmony_ci	} else {
1225f08c3bdfSopenharmony_ci		LLVMTypeRef type = symbol_type(sym);
1226f08c3bdfSopenharmony_ci
1227f08c3bdfSopenharmony_ci		initial_value = LLVMConstNull(type);
1228f08c3bdfSopenharmony_ci	}
1229f08c3bdfSopenharmony_ci
1230f08c3bdfSopenharmony_ci	if (!initial_value)
1231f08c3bdfSopenharmony_ci		return NULL;
1232f08c3bdfSopenharmony_ci
1233f08c3bdfSopenharmony_ci	name = sym->ident ? show_ident(sym->ident) : "" ;
1234f08c3bdfSopenharmony_ci
1235f08c3bdfSopenharmony_ci	data = LLVMAddGlobal(module, LLVMTypeOf(initial_value), name);
1236f08c3bdfSopenharmony_ci
1237f08c3bdfSopenharmony_ci	LLVMSetLinkage(data, data_linkage(sym));
1238f08c3bdfSopenharmony_ci	if (sym->ctype.modifiers & MOD_CONST)
1239f08c3bdfSopenharmony_ci		LLVMSetGlobalConstant(data, 1);
1240f08c3bdfSopenharmony_ci	if (sym->ctype.modifiers & MOD_TLS)
1241f08c3bdfSopenharmony_ci		LLVMSetThreadLocal(data, 1);
1242f08c3bdfSopenharmony_ci	if (sym->ctype.alignment)
1243f08c3bdfSopenharmony_ci		LLVMSetAlignment(data, sym->ctype.alignment);
1244f08c3bdfSopenharmony_ci
1245f08c3bdfSopenharmony_ci	if (!(sym->ctype.modifiers & MOD_EXTERN))
1246f08c3bdfSopenharmony_ci		LLVMSetInitializer(data, initial_value);
1247f08c3bdfSopenharmony_ci
1248f08c3bdfSopenharmony_ci	return data;
1249f08c3bdfSopenharmony_ci}
1250f08c3bdfSopenharmony_ci
1251f08c3bdfSopenharmony_cistatic int is_prototype(struct symbol *sym)
1252f08c3bdfSopenharmony_ci{
1253f08c3bdfSopenharmony_ci	if (sym->type == SYM_NODE)
1254f08c3bdfSopenharmony_ci		sym = sym->ctype.base_type;
1255f08c3bdfSopenharmony_ci	return sym && sym->type == SYM_FN && !sym->stmt;
1256f08c3bdfSopenharmony_ci}
1257f08c3bdfSopenharmony_ci
1258f08c3bdfSopenharmony_cistatic int compile(LLVMModuleRef module, struct symbol_list *list)
1259f08c3bdfSopenharmony_ci{
1260f08c3bdfSopenharmony_ci	struct symbol *sym;
1261f08c3bdfSopenharmony_ci
1262f08c3bdfSopenharmony_ci	FOR_EACH_PTR(list, sym) {
1263f08c3bdfSopenharmony_ci		struct entrypoint *ep;
1264f08c3bdfSopenharmony_ci		expand_symbol(sym);
1265f08c3bdfSopenharmony_ci
1266f08c3bdfSopenharmony_ci		if (is_prototype(sym)) {
1267f08c3bdfSopenharmony_ci			// this will do the LLVMAddFunction() we want
1268f08c3bdfSopenharmony_ci			get_sym_value(module, sym);
1269f08c3bdfSopenharmony_ci			continue;
1270f08c3bdfSopenharmony_ci		}
1271f08c3bdfSopenharmony_ci
1272f08c3bdfSopenharmony_ci		ep = linearize_symbol(sym);
1273f08c3bdfSopenharmony_ci		if (ep)
1274f08c3bdfSopenharmony_ci			output_fn(module, ep);
1275f08c3bdfSopenharmony_ci		else
1276f08c3bdfSopenharmony_ci			output_data(module, sym);
1277f08c3bdfSopenharmony_ci	}
1278f08c3bdfSopenharmony_ci	END_FOR_EACH_PTR(sym);
1279f08c3bdfSopenharmony_ci
1280f08c3bdfSopenharmony_ci	return 0;
1281f08c3bdfSopenharmony_ci}
1282f08c3bdfSopenharmony_ci
1283f08c3bdfSopenharmony_ci#ifndef LLVM_DEFAULT_TARGET_TRIPLE
1284f08c3bdfSopenharmony_ci#define LLVM_DEFAULT_TARGET_TRIPLE LLVM_HOSTTRIPLE
1285f08c3bdfSopenharmony_ci#endif
1286f08c3bdfSopenharmony_ci
1287f08c3bdfSopenharmony_ci#define X86_LINUX_LAYOUT \
1288f08c3bdfSopenharmony_ci	"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" \
1289f08c3bdfSopenharmony_ci	"i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-" \
1290f08c3bdfSopenharmony_ci	"a0:0:64-f80:32:32-n8:16:32-S128"
1291f08c3bdfSopenharmony_ci
1292f08c3bdfSopenharmony_ci#define X86_64_LINUX_LAYOUT \
1293f08c3bdfSopenharmony_ci	"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" \
1294f08c3bdfSopenharmony_ci	"i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" \
1295f08c3bdfSopenharmony_ci	"a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
1296f08c3bdfSopenharmony_ci
1297f08c3bdfSopenharmony_cistatic void set_target(LLVMModuleRef module)
1298f08c3bdfSopenharmony_ci{
1299f08c3bdfSopenharmony_ci	char target[] = LLVM_DEFAULT_TARGET_TRIPLE;
1300f08c3bdfSopenharmony_ci	const char *arch, *vendor, *os, *env, *layout = NULL;
1301f08c3bdfSopenharmony_ci	char triple[256];
1302f08c3bdfSopenharmony_ci
1303f08c3bdfSopenharmony_ci	arch = strtok(target, "-");
1304f08c3bdfSopenharmony_ci	vendor = strtok(NULL, "-");
1305f08c3bdfSopenharmony_ci	os = strtok(NULL, "-");
1306f08c3bdfSopenharmony_ci	env = strtok(NULL, "-");
1307f08c3bdfSopenharmony_ci
1308f08c3bdfSopenharmony_ci	if (!os)
1309f08c3bdfSopenharmony_ci		return;
1310f08c3bdfSopenharmony_ci	if (!env)
1311f08c3bdfSopenharmony_ci		env = "unknown";
1312f08c3bdfSopenharmony_ci
1313f08c3bdfSopenharmony_ci	if (!strcmp(arch, "x86_64") && !strcmp(os, "linux")) {
1314f08c3bdfSopenharmony_ci		if (arch_m64) {
1315f08c3bdfSopenharmony_ci			layout = X86_64_LINUX_LAYOUT;
1316f08c3bdfSopenharmony_ci		} else {
1317f08c3bdfSopenharmony_ci			arch = "i386";
1318f08c3bdfSopenharmony_ci			layout = X86_LINUX_LAYOUT;
1319f08c3bdfSopenharmony_ci		}
1320f08c3bdfSopenharmony_ci	}
1321f08c3bdfSopenharmony_ci
1322f08c3bdfSopenharmony_ci	/* unsupported target */
1323f08c3bdfSopenharmony_ci	if (!layout)
1324f08c3bdfSopenharmony_ci		return;
1325f08c3bdfSopenharmony_ci
1326f08c3bdfSopenharmony_ci	snprintf(triple, sizeof(triple), "%s-%s-%s-%s", arch, vendor, os, env);
1327f08c3bdfSopenharmony_ci	LLVMSetTarget(module, triple);
1328f08c3bdfSopenharmony_ci	LLVMSetDataLayout(module, layout);
1329f08c3bdfSopenharmony_ci}
1330f08c3bdfSopenharmony_ci
1331f08c3bdfSopenharmony_ciint main(int argc, char **argv)
1332f08c3bdfSopenharmony_ci{
1333f08c3bdfSopenharmony_ci	struct string_list *filelist = NULL;
1334f08c3bdfSopenharmony_ci	struct symbol_list *symlist;
1335f08c3bdfSopenharmony_ci	LLVMModuleRef module;
1336f08c3bdfSopenharmony_ci	char *file;
1337f08c3bdfSopenharmony_ci
1338f08c3bdfSopenharmony_ci	symlist = sparse_initialize(argc, argv, &filelist);
1339f08c3bdfSopenharmony_ci
1340f08c3bdfSopenharmony_ci	module = LLVMModuleCreateWithName("sparse");
1341f08c3bdfSopenharmony_ci	set_target(module);
1342f08c3bdfSopenharmony_ci
1343f08c3bdfSopenharmony_ci	compile(module, symlist);
1344f08c3bdfSopenharmony_ci
1345f08c3bdfSopenharmony_ci	FOR_EACH_PTR(filelist, file) {
1346f08c3bdfSopenharmony_ci		symlist = sparse(file);
1347f08c3bdfSopenharmony_ci		if (die_if_error)
1348f08c3bdfSopenharmony_ci			return 1;
1349f08c3bdfSopenharmony_ci		compile(module, symlist);
1350f08c3bdfSopenharmony_ci	} END_FOR_EACH_PTR(file);
1351f08c3bdfSopenharmony_ci
1352f08c3bdfSopenharmony_ci	LLVMVerifyModule(module, LLVMPrintMessageAction, NULL);
1353f08c3bdfSopenharmony_ci
1354f08c3bdfSopenharmony_ci	LLVMWriteBitcodeToFD(module, STDOUT_FILENO, 0, 0);
1355f08c3bdfSopenharmony_ci
1356f08c3bdfSopenharmony_ci	LLVMDisposeModule(module);
1357f08c3bdfSopenharmony_ci
1358f08c3bdfSopenharmony_ci	report_stats();
1359f08c3bdfSopenharmony_ci	return 0;
1360f08c3bdfSopenharmony_ci}
1361