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