Print this page
new smatch

*** 19,102 **** #include "linearize.h" #include "flow.h" struct function { LLVMBuilderRef builder; - LLVMTypeRef type; LLVMValueRef fn; LLVMModuleRef module; }; ! static inline bool symbol_is_fp_type(struct symbol *sym) ! { ! if (!sym) ! return false; ! return sym->ctype.base_type == &fp_type; ! } ! ! static LLVMTypeRef symbol_type(LLVMModuleRef module, struct symbol *sym); ! ! static LLVMTypeRef func_return_type(LLVMModuleRef module, struct symbol *sym) { ! return symbol_type(module, sym->ctype.base_type); } ! static LLVMTypeRef sym_func_type(LLVMModuleRef module, struct symbol *sym) { ! LLVMTypeRef *arg_type; ! LLVMTypeRef func_type; ! LLVMTypeRef ret_type; struct symbol *arg; ! int n_arg = 0; - /* to avoid strangeness with varargs [for now], we build - * the function and type anew, for each call. This - * is probably wrong. We should look up the - * symbol declaration info. - */ - - ret_type = func_return_type(module, sym); - - /* count args, build argument type information */ FOR_EACH_PTR(sym->arguments, arg) { - n_arg++; - } END_FOR_EACH_PTR(arg); - - arg_type = calloc(n_arg, sizeof(LLVMTypeRef)); - - int idx = 0; - FOR_EACH_PTR(sym->arguments, arg) { struct symbol *arg_sym = arg->ctype.base_type; ! arg_type[idx++] = symbol_type(module, arg_sym); } END_FOR_EACH_PTR(arg); - func_type = LLVMFunctionType(ret_type, arg_type, n_arg, - sym->variadic); ! return func_type; } ! static LLVMTypeRef sym_array_type(LLVMModuleRef module, struct symbol *sym) { LLVMTypeRef elem_type; struct symbol *base_type; base_type = sym->ctype.base_type; /* empty struct is undefined [6.7.2.1(8)] */ assert(base_type->bit_size > 0); ! elem_type = symbol_type(module, base_type); if (!elem_type) return NULL; return LLVMArrayType(elem_type, sym->bit_size / base_type->bit_size); } #define MAX_STRUCT_MEMBERS 64 ! static LLVMTypeRef sym_struct_type(LLVMModuleRef module, struct symbol *sym) { LLVMTypeRef elem_types[MAX_STRUCT_MEMBERS]; struct symbol *member; char buffer[256]; LLVMTypeRef ret; --- 19,75 ---- #include "linearize.h" #include "flow.h" struct function { LLVMBuilderRef builder; LLVMValueRef fn; LLVMModuleRef module; }; ! static LLVMTypeRef symbol_type(struct symbol *sym); ! static LLVMTypeRef func_return_type(struct symbol *sym) { ! return symbol_type(sym->ctype.base_type); } ! static LLVMTypeRef sym_func_type(struct symbol *sym) { ! int n_arg = symbol_list_size(sym->arguments); ! LLVMTypeRef *arg_type = calloc(n_arg, sizeof(LLVMTypeRef)); ! LLVMTypeRef ret_type = func_return_type(sym); struct symbol *arg; ! int idx = 0; FOR_EACH_PTR(sym->arguments, arg) { struct symbol *arg_sym = arg->ctype.base_type; ! arg_type[idx++] = symbol_type(arg_sym); } END_FOR_EACH_PTR(arg); ! return LLVMFunctionType(ret_type, arg_type, n_arg, sym->variadic); } ! static LLVMTypeRef sym_array_type(struct symbol *sym) { LLVMTypeRef elem_type; struct symbol *base_type; base_type = sym->ctype.base_type; /* empty struct is undefined [6.7.2.1(8)] */ assert(base_type->bit_size > 0); ! elem_type = symbol_type(base_type); if (!elem_type) return NULL; return LLVMArrayType(elem_type, sym->bit_size / base_type->bit_size); } #define MAX_STRUCT_MEMBERS 64 ! static LLVMTypeRef sym_struct_type(struct symbol *sym) { LLVMTypeRef elem_types[MAX_STRUCT_MEMBERS]; struct symbol *member; char buffer[256]; LLVMTypeRef ret;
*** 110,129 **** FOR_EACH_PTR(sym->symbol_list, member) { LLVMTypeRef member_type; assert(nr < MAX_STRUCT_MEMBERS); ! member_type = symbol_type(module, member); elem_types[nr++] = member_type; } END_FOR_EACH_PTR(member); LLVMStructSetBody(ret, elem_types, nr, 0 /* packed? */); return ret; } ! static LLVMTypeRef sym_union_type(LLVMModuleRef module, struct symbol *sym) { LLVMTypeRef elements; unsigned union_size; /* --- 83,102 ---- FOR_EACH_PTR(sym->symbol_list, member) { LLVMTypeRef member_type; assert(nr < MAX_STRUCT_MEMBERS); ! member_type = symbol_type(member); elem_types[nr++] = member_type; } END_FOR_EACH_PTR(member); LLVMStructSetBody(ret, elem_types, nr, 0 /* packed? */); return ret; } ! static LLVMTypeRef sym_union_type(struct symbol *sym) { LLVMTypeRef elements; unsigned union_size; /*
*** 136,163 **** elements = LLVMArrayType(LLVMInt8Type(), union_size); return LLVMStructType(&elements, 1, 0 /* packed? */); } ! static LLVMTypeRef sym_ptr_type(LLVMModuleRef module, struct symbol *sym) { LLVMTypeRef type; /* 'void *' is treated like 'char *' */ if (is_void_type(sym->ctype.base_type)) type = LLVMInt8Type(); else ! type = symbol_type(module, sym->ctype.base_type); return LLVMPointerType(type, 0); } static LLVMTypeRef sym_basetype_type(struct symbol *sym) { LLVMTypeRef ret = NULL; ! if (symbol_is_fp_type(sym)) { switch (sym->bit_size) { case 32: ret = LLVMFloatType(); break; case 64: --- 109,136 ---- elements = LLVMArrayType(LLVMInt8Type(), union_size); return LLVMStructType(&elements, 1, 0 /* packed? */); } ! static LLVMTypeRef sym_ptr_type(struct symbol *sym) { LLVMTypeRef type; /* 'void *' is treated like 'char *' */ if (is_void_type(sym->ctype.base_type)) type = LLVMInt8Type(); else ! type = symbol_type(sym->ctype.base_type); return LLVMPointerType(type, 0); } static LLVMTypeRef sym_basetype_type(struct symbol *sym) { LLVMTypeRef ret = NULL; ! if (is_float_type(sym)) { switch (sym->bit_size) { case 32: ret = LLVMFloatType(); break; case 64:
*** 197,239 **** } return ret; } ! static LLVMTypeRef symbol_type(LLVMModuleRef module, struct symbol *sym) { LLVMTypeRef ret = NULL; /* don't cache the result for SYM_NODE */ if (sym->type == SYM_NODE) ! return symbol_type(module, sym->ctype.base_type); if (sym->aux) return sym->aux; switch (sym->type) { case SYM_BITFIELD: case SYM_ENUM: ! ret = symbol_type(module, sym->ctype.base_type); break; case SYM_BASETYPE: ret = sym_basetype_type(sym); break; case SYM_PTR: ! ret = sym_ptr_type(module, sym); break; case SYM_UNION: ! ret = sym_union_type(module, sym); break; case SYM_STRUCT: ! ret = sym_struct_type(module, sym); break; case SYM_ARRAY: ! ret = sym_array_type(module, sym); break; case SYM_FN: ! ret = sym_func_type(module, sym); break; default: assert(0); } --- 170,215 ---- } return ret; } ! static LLVMTypeRef symbol_type(struct symbol *sym) { LLVMTypeRef ret = NULL; /* don't cache the result for SYM_NODE */ if (sym->type == SYM_NODE) ! return symbol_type(sym->ctype.base_type); if (sym->aux) return sym->aux; switch (sym->type) { case SYM_BITFIELD: + ret = LLVMIntType(sym->bit_size); + break; + case SYM_RESTRICT: case SYM_ENUM: ! ret = symbol_type(sym->ctype.base_type); break; case SYM_BASETYPE: ret = sym_basetype_type(sym); break; case SYM_PTR: ! ret = sym_ptr_type(sym); break; case SYM_UNION: ! ret = sym_union_type(sym); break; case SYM_STRUCT: ! ret = sym_struct_type(sym); break; case SYM_ARRAY: ! ret = sym_array_type(sym); break; case SYM_FN: ! ret = sym_func_type(sym); break; default: assert(0); }
*** 240,273 **** /* cache the result */ sym->aux = ret; return ret; } ! static LLVMTypeRef int_type_by_size(int size) { ! switch (size) { ! case 1: return LLVMInt1Type(); case 8: return LLVMInt8Type(); case 16: return LLVMInt16Type(); case 32: return LLVMInt32Type(); case 64: return LLVMInt64Type(); default: ! die("invalid bit size %d", size); break; } return NULL; /* not reached */ } - static LLVMTypeRef insn_symbol_type(LLVMModuleRef module, struct instruction *insn) - { - if (insn->type) - return symbol_type(module, insn->type); - - return int_type_by_size(insn->size); - } - static LLVMLinkage data_linkage(struct symbol *sym) { if (sym->ctype.modifiers & MOD_STATIC) return LLVMPrivateLinkage; --- 216,244 ---- /* cache the result */ sym->aux = ret; return ret; } ! static LLVMTypeRef insn_symbol_type(struct instruction *insn) { ! if (insn->type) ! return symbol_type(insn->type); ! ! switch (insn->size) { case 8: return LLVMInt8Type(); case 16: return LLVMInt16Type(); case 32: return LLVMInt32Type(); case 64: return LLVMInt64Type(); default: ! die("invalid bit size %d", insn->size); break; } + return NULL; /* not reached */ } static LLVMLinkage data_linkage(struct symbol *sym) { if (sym->ctype.modifiers & MOD_STATIC) return LLVMPrivateLinkage;
*** 282,373 **** return LLVMExternalLinkage; } #define MAX_PSEUDO_NAME 64 ! static void pseudo_name(pseudo_t pseudo, char *buf) { switch (pseudo->type) { case PSEUDO_REG: ! snprintf(buf, MAX_PSEUDO_NAME, "R%d", pseudo->nr); break; ! case PSEUDO_SYM: ! assert(0); break; case PSEUDO_VAL: ! assert(0); break; ! case PSEUDO_ARG: { assert(0); break; - } - case PSEUDO_PHI: - snprintf(buf, MAX_PSEUDO_NAME, "PHI%d", pseudo->nr); - break; default: assert(0); } } ! static LLVMValueRef pseudo_to_value(struct function *fn, struct instruction *insn, pseudo_t pseudo) { LLVMValueRef result = NULL; - - switch (pseudo->type) { - case PSEUDO_REG: - result = pseudo->priv; - break; - case PSEUDO_SYM: { - struct symbol *sym = pseudo->sym; struct expression *expr; assert(sym->bb_target == NULL); expr = sym->initializer; ! if (expr) { switch (expr->type) { case EXPR_STRING: { const char *s = expr->string->data; LLVMValueRef indices[] = { LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt64Type(), 0, 0) }; LLVMValueRef data; ! data = LLVMAddGlobal(fn->module, LLVMArrayType(LLVMInt8Type(), strlen(s) + 1), ".str"); LLVMSetLinkage(data, LLVMPrivateLinkage); LLVMSetGlobalConstant(data, 1); LLVMSetInitializer(data, LLVMConstString(strdup(s), strlen(s) + 1, true)); result = LLVMConstGEP(data, indices, ARRAY_SIZE(indices)); ! break; } ! case EXPR_SYMBOL: { ! struct symbol *sym = expr->symbol; ! ! result = LLVMGetNamedGlobal(fn->module, show_ident(sym->ident)); ! assert(result != NULL); break; } - default: - assert(0); } - } else { - const char *name = show_ident(sym->ident); - LLVMTypeRef type = symbol_type(fn->module, sym); if (LLVMGetTypeKind(type) == LLVMFunctionTypeKind) { ! result = LLVMGetNamedFunction(fn->module, name); if (!result) ! result = LLVMAddFunction(fn->module, name, type); } else { ! result = LLVMGetNamedGlobal(fn->module, name); if (!result) ! result = LLVMAddGlobal(fn->module, type, name); } } break; } case PSEUDO_VAL: ! result = LLVMConstInt(int_type_by_size(pseudo->size), pseudo->value, 1); break; case PSEUDO_ARG: { result = LLVMGetParam(fn->fn, pseudo->nr - 1); break; } --- 253,386 ---- return LLVMExternalLinkage; } #define MAX_PSEUDO_NAME 64 ! static const char *pseudo_name(pseudo_t pseudo, char *buf) { switch (pseudo->type) { case PSEUDO_REG: ! snprintf(buf, MAX_PSEUDO_NAME, "R%d.", pseudo->nr); break; ! case PSEUDO_PHI: ! snprintf(buf, MAX_PSEUDO_NAME, "PHI%d.", pseudo->nr); break; + case PSEUDO_SYM: case PSEUDO_VAL: ! case PSEUDO_ARG: ! case PSEUDO_VOID: ! buf[0] = '\0'; break; ! case PSEUDO_UNDEF: assert(0); break; default: assert(0); } + + return buf; } ! static LLVMValueRef get_sym_value(LLVMModuleRef module, struct symbol *sym) { + const char *name = show_ident(sym->ident); + LLVMTypeRef type = symbol_type(sym); LLVMValueRef result = NULL; struct expression *expr; assert(sym->bb_target == NULL); expr = sym->initializer; ! if (expr && !sym->ident) { switch (expr->type) { case EXPR_STRING: { const char *s = expr->string->data; LLVMValueRef indices[] = { LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt64Type(), 0, 0) }; LLVMValueRef data; ! data = LLVMAddGlobal(module, LLVMArrayType(LLVMInt8Type(), strlen(s) + 1), ".str"); LLVMSetLinkage(data, LLVMPrivateLinkage); LLVMSetGlobalConstant(data, 1); LLVMSetInitializer(data, LLVMConstString(strdup(s), strlen(s) + 1, true)); result = LLVMConstGEP(data, indices, ARRAY_SIZE(indices)); ! return result; } ! default: break; } } if (LLVMGetTypeKind(type) == LLVMFunctionTypeKind) { ! result = LLVMGetNamedFunction(module, name); if (!result) ! result = LLVMAddFunction(module, name, type); } else { ! result = LLVMGetNamedGlobal(module, name); if (!result) ! result = LLVMAddGlobal(module, type, name); } + + return result; + } + + static LLVMValueRef constant_value(unsigned long long val, LLVMTypeRef dtype) + { + LLVMValueRef result; + + switch (LLVMGetTypeKind(dtype)) { + case LLVMPointerTypeKind: + if (val != 0) { // for example: ... = (void*) 0x123; + LLVMTypeRef itype = LLVMIntType(bits_in_pointer); + result = LLVMConstInt(itype, val, 1); + result = LLVMConstIntToPtr(result, dtype); + } else { + result = LLVMConstPointerNull(dtype); } break; + case LLVMIntegerTypeKind: + result = LLVMConstInt(dtype, val, 1); + break; + case LLVMArrayTypeKind: + case LLVMStructTypeKind: + if (val != 0) + return NULL; + result = LLVMConstNull(dtype); + break; + default: + return NULL; } + return result; + } + + static LLVMValueRef val_to_value(unsigned long long val, struct symbol *ctype) + { + LLVMValueRef result; + LLVMTypeRef dtype; + + assert(ctype); + dtype = symbol_type(ctype); + result = constant_value(val, dtype); + if (result) + return result; + sparse_error(ctype->pos, "no value possible for %s", show_typename(ctype)); + return LLVMGetUndef(symbol_type(ctype)); + } + + static LLVMValueRef pseudo_to_value(struct function *fn, struct symbol *ctype, pseudo_t pseudo) + { + LLVMValueRef result = NULL; + + switch (pseudo->type) { + case PSEUDO_REG: + result = pseudo->priv; + break; + case PSEUDO_SYM: + result = get_sym_value(fn->module, pseudo->sym); + break; case PSEUDO_VAL: ! result = val_to_value(pseudo->value, ctype); break; case PSEUDO_ARG: { result = LLVMGetParam(fn->fn, pseudo->nr - 1); break; }
*** 375,421 **** result = pseudo->priv; break; case PSEUDO_VOID: result = NULL; break; default: assert(0); } return result; } static LLVMValueRef calc_gep(LLVMBuilderRef builder, LLVMValueRef base, LLVMValueRef off) { LLVMTypeRef type = LLVMTypeOf(base); unsigned int as = LLVMGetPointerAddressSpace(type); LLVMTypeRef bytep = LLVMPointerType(LLVMInt8Type(), as); LLVMValueRef addr; /* convert base to char* type */ ! base = LLVMBuildPointerCast(builder, base, bytep, ""); /* addr = base + off */ ! addr = LLVMBuildInBoundsGEP(builder, base, &off, 1, ""); /* convert back to the actual pointer type */ ! addr = LLVMBuildPointerCast(builder, addr, type, ""); return addr; } static LLVMRealPredicate translate_fop(int opcode) { static const LLVMRealPredicate trans_tbl[] = { ! [OP_SET_EQ] = LLVMRealOEQ, ! [OP_SET_NE] = LLVMRealUNE, ! [OP_SET_LE] = LLVMRealOLE, ! [OP_SET_GE] = LLVMRealOGE, ! [OP_SET_LT] = LLVMRealOLT, ! [OP_SET_GT] = LLVMRealOGT, ! /* Are these used with FP? */ ! [OP_SET_B] = LLVMRealOLT, ! [OP_SET_A] = LLVMRealOGT, ! [OP_SET_BE] = LLVMRealOLE, ! [OP_SET_AE] = LLVMRealOGE, }; return trans_tbl[opcode]; } --- 388,515 ---- result = pseudo->priv; break; case PSEUDO_VOID: result = NULL; break; + case PSEUDO_UNDEF: + result = LLVMGetUndef(symbol_type(ctype)); + break; default: assert(0); } return result; } + static LLVMValueRef pseudo_to_rvalue(struct function *fn, struct symbol *ctype, pseudo_t pseudo) + { + LLVMValueRef val = pseudo_to_value(fn, ctype, pseudo); + LLVMTypeRef dtype = symbol_type(ctype); + char name[MAX_PSEUDO_NAME]; + + pseudo_name(pseudo, name); + return LLVMBuildBitCast(fn->builder, val, dtype, name); + } + + static LLVMValueRef value_to_ivalue(struct function *fn, struct symbol *ctype, LLVMValueRef val) + { + const char *name = LLVMGetValueName(val); + LLVMTypeRef dtype = symbol_type(ctype); + + if (LLVMGetTypeKind(LLVMTypeOf(val)) == LLVMPointerTypeKind) { + LLVMTypeRef dtype = LLVMIntType(bits_in_pointer); + val = LLVMBuildPtrToInt(fn->builder, val, dtype, name); + } + if (ctype && is_int_type(ctype)) { + val = LLVMBuildIntCast(fn->builder, val, dtype, name); + } + return val; + } + + static LLVMValueRef value_to_pvalue(struct function *fn, struct symbol *ctype, LLVMValueRef val) + { + const char *name = LLVMGetValueName(val); + LLVMTypeRef dtype = symbol_type(ctype); + + assert(is_ptr_type(ctype)); + switch (LLVMGetTypeKind(LLVMTypeOf(val))) { + case LLVMIntegerTypeKind: + val = LLVMBuildIntToPtr(fn->builder, val, dtype, name); + break; + case LLVMPointerTypeKind: + val = LLVMBuildBitCast(fn->builder, val, dtype, name); + break; + default: + break; + } + return val; + } + + static LLVMValueRef adjust_type(struct function *fn, struct symbol *ctype, LLVMValueRef val) + { + if (is_int_type(ctype)) + return value_to_ivalue(fn, ctype, val); + if (is_ptr_type(ctype)) + return value_to_pvalue(fn, ctype, val); + return val; + } + + /* + * Get the LLVMValue corresponding to the pseudo + * and force the type corresponding to ctype. + */ + static LLVMValueRef get_operand(struct function *fn, struct symbol *ctype, pseudo_t pseudo) + { + LLVMValueRef target = pseudo_to_value(fn, ctype, pseudo); + return adjust_type(fn, ctype, target); + } + + /* + * Get the LLVMValue corresponding to the pseudo + * and force the type corresponding to ctype but + * map all pointers to intptr_t. + */ + static LLVMValueRef get_ioperand(struct function *fn, struct symbol *ctype, pseudo_t pseudo) + { + LLVMValueRef target = pseudo_to_value(fn, ctype, pseudo); + return value_to_ivalue(fn, ctype, target); + } + static LLVMValueRef calc_gep(LLVMBuilderRef builder, LLVMValueRef base, LLVMValueRef off) { LLVMTypeRef type = LLVMTypeOf(base); unsigned int as = LLVMGetPointerAddressSpace(type); LLVMTypeRef bytep = LLVMPointerType(LLVMInt8Type(), as); LLVMValueRef addr; + const char *name = LLVMGetValueName(off); /* convert base to char* type */ ! base = LLVMBuildPointerCast(builder, base, bytep, name); /* addr = base + off */ ! addr = LLVMBuildInBoundsGEP(builder, base, &off, 1, name); /* convert back to the actual pointer type */ ! addr = LLVMBuildPointerCast(builder, addr, type, name); return addr; } static LLVMRealPredicate translate_fop(int opcode) { static const LLVMRealPredicate trans_tbl[] = { ! [OP_FCMP_ORD] = LLVMRealORD, ! [OP_FCMP_OEQ] = LLVMRealOEQ, ! [OP_FCMP_ONE] = LLVMRealONE, ! [OP_FCMP_OLE] = LLVMRealOLE, ! [OP_FCMP_OGE] = LLVMRealOGE, ! [OP_FCMP_OLT] = LLVMRealOLT, ! [OP_FCMP_OGT] = LLVMRealOGT, ! [OP_FCMP_UEQ] = LLVMRealUEQ, ! [OP_FCMP_UNE] = LLVMRealUNE, ! [OP_FCMP_ULE] = LLVMRealULE, ! [OP_FCMP_UGE] = LLVMRealUGE, ! [OP_FCMP_ULT] = LLVMRealULT, ! [OP_FCMP_UGT] = LLVMRealUGT, ! [OP_FCMP_UNO] = LLVMRealUNO, }; return trans_tbl[opcode]; }
*** 440,580 **** static void output_op_binary(struct function *fn, struct instruction *insn) { LLVMValueRef lhs, rhs, target; char target_name[64]; ! lhs = pseudo_to_value(fn, insn, insn->src1); - rhs = pseudo_to_value(fn, insn, insn->src2); - pseudo_name(insn->target, target_name); switch (insn->opcode) { /* Binary */ case OP_ADD: - if (symbol_is_fp_type(insn->type)) - target = LLVMBuildFAdd(fn->builder, lhs, rhs, target_name); - else target = LLVMBuildAdd(fn->builder, lhs, rhs, target_name); break; case OP_SUB: - if (symbol_is_fp_type(insn->type)) - target = LLVMBuildFSub(fn->builder, lhs, rhs, target_name); - else target = LLVMBuildSub(fn->builder, lhs, rhs, target_name); break; ! case OP_MULU: ! if (symbol_is_fp_type(insn->type)) ! target = LLVMBuildFMul(fn->builder, lhs, rhs, target_name); ! else target = LLVMBuildMul(fn->builder, lhs, rhs, target_name); break; - case OP_MULS: - assert(!symbol_is_fp_type(insn->type)); - target = LLVMBuildMul(fn->builder, lhs, rhs, target_name); - break; case OP_DIVU: - if (symbol_is_fp_type(insn->type)) - target = LLVMBuildFDiv(fn->builder, lhs, rhs, target_name); - else target = LLVMBuildUDiv(fn->builder, lhs, rhs, target_name); break; case OP_DIVS: ! assert(!symbol_is_fp_type(insn->type)); target = LLVMBuildSDiv(fn->builder, lhs, rhs, target_name); break; case OP_MODU: ! assert(!symbol_is_fp_type(insn->type)); target = LLVMBuildURem(fn->builder, lhs, rhs, target_name); break; case OP_MODS: ! assert(!symbol_is_fp_type(insn->type)); target = LLVMBuildSRem(fn->builder, lhs, rhs, target_name); break; case OP_SHL: ! assert(!symbol_is_fp_type(insn->type)); target = LLVMBuildShl(fn->builder, lhs, rhs, target_name); break; case OP_LSR: ! assert(!symbol_is_fp_type(insn->type)); target = LLVMBuildLShr(fn->builder, lhs, rhs, target_name); break; case OP_ASR: ! assert(!symbol_is_fp_type(insn->type)); target = LLVMBuildAShr(fn->builder, lhs, rhs, target_name); break; /* Logical */ case OP_AND: ! assert(!symbol_is_fp_type(insn->type)); target = LLVMBuildAnd(fn->builder, lhs, rhs, target_name); break; case OP_OR: ! assert(!symbol_is_fp_type(insn->type)); target = LLVMBuildOr(fn->builder, lhs, rhs, target_name); break; case OP_XOR: ! assert(!symbol_is_fp_type(insn->type)); target = LLVMBuildXor(fn->builder, lhs, rhs, target_name); break; - case OP_AND_BOOL: { - LLVMValueRef lhs_nz, rhs_nz; - LLVMTypeRef dst_type; - - lhs_nz = LLVMBuildIsNotNull(fn->builder, lhs, ""); - rhs_nz = LLVMBuildIsNotNull(fn->builder, rhs, ""); - target = LLVMBuildAnd(fn->builder, lhs_nz, rhs_nz, target_name); - - dst_type = insn_symbol_type(fn->module, insn); - target = LLVMBuildZExt(fn->builder, target, dst_type, target_name); - break; - } - case OP_OR_BOOL: { - LLVMValueRef lhs_nz, rhs_nz; - LLVMTypeRef dst_type; - - lhs_nz = LLVMBuildIsNotNull(fn->builder, lhs, ""); - rhs_nz = LLVMBuildIsNotNull(fn->builder, rhs, ""); - target = LLVMBuildOr(fn->builder, lhs_nz, rhs_nz, target_name); - - dst_type = insn_symbol_type(fn->module, insn); - target = LLVMBuildZExt(fn->builder, target, dst_type, target_name); - break; - } default: assert(0); break; } insn->target->priv = target; } static void output_op_compare(struct function *fn, struct instruction *insn) { LLVMValueRef lhs, rhs, target; char target_name[64]; ! lhs = pseudo_to_value(fn, insn, insn->src1); ! if (insn->src2->type == PSEUDO_VAL) ! rhs = LLVMConstInt(LLVMTypeOf(lhs), insn->src2->value, 1); else ! rhs = pseudo_to_value(fn, insn, insn->src2); pseudo_name(insn->target, target_name); ! LLVMTypeRef dst_type = insn_symbol_type(fn->module, insn); ! if (LLVMGetTypeKind(LLVMTypeOf(lhs)) == LLVMIntegerTypeKind) { LLVMIntPredicate op = translate_op(insn->opcode); target = LLVMBuildICmp(fn->builder, op, lhs, rhs, target_name); ! } else { LLVMRealPredicate op = translate_fop(insn->opcode); target = LLVMBuildFCmp(fn->builder, op, lhs, rhs, target_name); } target = LLVMBuildZExt(fn->builder, target, dst_type, target_name); insn->target->priv = target; } --- 534,670 ---- static void output_op_binary(struct function *fn, struct instruction *insn) { LLVMValueRef lhs, rhs, target; char target_name[64]; ! lhs = get_ioperand(fn, insn->type, insn->src1); ! rhs = get_ioperand(fn, insn->type, insn->src2); pseudo_name(insn->target, target_name); switch (insn->opcode) { /* Binary */ case OP_ADD: target = LLVMBuildAdd(fn->builder, lhs, rhs, target_name); break; case OP_SUB: target = LLVMBuildSub(fn->builder, lhs, rhs, target_name); break; ! case OP_MUL: target = LLVMBuildMul(fn->builder, lhs, rhs, target_name); break; case OP_DIVU: target = LLVMBuildUDiv(fn->builder, lhs, rhs, target_name); break; case OP_DIVS: ! assert(!is_float_type(insn->type)); target = LLVMBuildSDiv(fn->builder, lhs, rhs, target_name); break; case OP_MODU: ! assert(!is_float_type(insn->type)); target = LLVMBuildURem(fn->builder, lhs, rhs, target_name); break; case OP_MODS: ! assert(!is_float_type(insn->type)); target = LLVMBuildSRem(fn->builder, lhs, rhs, target_name); break; case OP_SHL: ! assert(!is_float_type(insn->type)); target = LLVMBuildShl(fn->builder, lhs, rhs, target_name); break; case OP_LSR: ! assert(!is_float_type(insn->type)); target = LLVMBuildLShr(fn->builder, lhs, rhs, target_name); break; case OP_ASR: ! assert(!is_float_type(insn->type)); target = LLVMBuildAShr(fn->builder, lhs, rhs, target_name); break; + /* floating-point */ + case OP_FADD: + target = LLVMBuildFAdd(fn->builder, lhs, rhs, target_name); + break; + case OP_FSUB: + target = LLVMBuildFSub(fn->builder, lhs, rhs, target_name); + break; + case OP_FMUL: + target = LLVMBuildFMul(fn->builder, lhs, rhs, target_name); + break; + case OP_FDIV: + target = LLVMBuildFDiv(fn->builder, lhs, rhs, target_name); + break; + /* Logical */ case OP_AND: ! assert(!is_float_type(insn->type)); target = LLVMBuildAnd(fn->builder, lhs, rhs, target_name); break; case OP_OR: ! assert(!is_float_type(insn->type)); target = LLVMBuildOr(fn->builder, lhs, rhs, target_name); break; case OP_XOR: ! assert(!is_float_type(insn->type)); target = LLVMBuildXor(fn->builder, lhs, rhs, target_name); break; default: assert(0); break; } + target = adjust_type(fn, insn->type, target); insn->target->priv = target; } static void output_op_compare(struct function *fn, struct instruction *insn) { LLVMValueRef lhs, rhs, target; char target_name[64]; ! lhs = pseudo_to_value(fn, NULL, insn->src1); if (insn->src2->type == PSEUDO_VAL) ! rhs = constant_value(insn->src2->value, LLVMTypeOf(lhs)); else ! rhs = pseudo_to_value(fn, NULL, insn->src2); ! if (!rhs) ! rhs = LLVMGetUndef(symbol_type(insn->type)); pseudo_name(insn->target, target_name); ! LLVMTypeRef dst_type = insn_symbol_type(insn); ! switch (LLVMGetTypeKind(LLVMTypeOf(lhs))) { ! case LLVMPointerTypeKind: ! lhs = value_to_pvalue(fn, &ptr_ctype, lhs); ! rhs = value_to_pvalue(fn, &ptr_ctype, rhs); ! /* fall through */ ! ! case LLVMIntegerTypeKind: { LLVMIntPredicate op = translate_op(insn->opcode); + if (LLVMGetTypeKind(LLVMTypeOf(rhs)) == LLVMPointerTypeKind) { + LLVMTypeRef ltype = LLVMTypeOf(lhs); + rhs = LLVMBuildPtrToInt(fn->builder, rhs, ltype, ""); + } target = LLVMBuildICmp(fn->builder, op, lhs, rhs, target_name); ! break; ! } ! case LLVMHalfTypeKind: ! case LLVMFloatTypeKind: ! case LLVMDoubleTypeKind: ! case LLVMX86_FP80TypeKind: ! case LLVMFP128TypeKind: ! case LLVMPPC_FP128TypeKind: { LLVMRealPredicate op = translate_fop(insn->opcode); target = LLVMBuildFCmp(fn->builder, op, lhs, rhs, target_name); + break; } + default: + assert(0); + } target = LLVMBuildZExt(fn->builder, target, dst_type, target_name); insn->target->priv = target; }
*** 582,593 **** static void output_op_ret(struct function *fn, struct instruction *insn) { pseudo_t pseudo = insn->src; if (pseudo && pseudo != VOID) { ! LLVMValueRef result = pseudo_to_value(fn, insn, pseudo); ! LLVMBuildRet(fn->builder, result); } else LLVMBuildRetVoid(fn->builder); } --- 672,682 ---- static void output_op_ret(struct function *fn, struct instruction *insn) { pseudo_t pseudo = insn->src; if (pseudo && pseudo != VOID) { ! LLVMValueRef result = get_operand(fn, insn->type, pseudo); LLVMBuildRet(fn->builder, result); } else LLVMBuildRetVoid(fn->builder); }
*** 600,613 **** /* int type large enough to hold a pointer */ int_type = LLVMIntType(bits_in_pointer); off = LLVMConstInt(int_type, insn->offset, 0); /* convert src to the effective pointer type */ ! src = pseudo_to_value(fn, insn, insn->src); as = LLVMGetPointerAddressSpace(LLVMTypeOf(src)); ! addr_type = LLVMPointerType(insn_symbol_type(fn->module, insn), as); ! src = LLVMBuildPointerCast(fn->builder, src, addr_type, ""); /* addr = src + off */ addr = calc_gep(fn->builder, src, off); return addr; } --- 689,702 ---- /* int type large enough to hold a pointer */ int_type = LLVMIntType(bits_in_pointer); off = LLVMConstInt(int_type, insn->offset, 0); /* convert src to the effective pointer type */ ! src = pseudo_to_value(fn, insn->type, insn->src); as = LLVMGetPointerAddressSpace(LLVMTypeOf(src)); ! addr_type = LLVMPointerType(insn_symbol_type(insn), as); ! src = LLVMBuildPointerCast(fn->builder, src, addr_type, LLVMGetValueName(src)); /* addr = src + off */ addr = calc_gep(fn->builder, src, off); return addr; }
*** 614,658 **** static void output_op_load(struct function *fn, struct instruction *insn) { LLVMValueRef addr, target; addr = calc_memop_addr(fn, insn); /* perform load */ ! target = LLVMBuildLoad(fn->builder, addr, "load_target"); insn->target->priv = target; } static void output_op_store(struct function *fn, struct instruction *insn) { ! LLVMValueRef addr, target, target_in; addr = calc_memop_addr(fn, insn); ! target_in = pseudo_to_value(fn, insn, insn->target); /* perform store */ ! target = LLVMBuildStore(fn->builder, target_in, addr); ! ! insn->target->priv = target; } static LLVMValueRef bool_value(struct function *fn, LLVMValueRef value) { if (LLVMTypeOf(value) != LLVMInt1Type()) ! value = LLVMBuildIsNotNull(fn->builder, value, "cond"); return value; } static void output_op_cbr(struct function *fn, struct instruction *br) { LLVMValueRef cond = bool_value(fn, ! pseudo_to_value(fn, br, br->cond)); LLVMBuildCondBr(fn->builder, cond, br->bb_true->priv, br->bb_false->priv); } --- 703,747 ---- static void output_op_load(struct function *fn, struct instruction *insn) { LLVMValueRef addr, target; + char name[MAX_PSEUDO_NAME]; addr = calc_memop_addr(fn, insn); /* perform load */ ! pseudo_name(insn->target, name); ! target = LLVMBuildLoad(fn->builder, addr, name); insn->target->priv = target; } static void output_op_store(struct function *fn, struct instruction *insn) { ! LLVMValueRef addr, target_in; addr = calc_memop_addr(fn, insn); ! target_in = pseudo_to_rvalue(fn, insn->type, insn->target); /* perform store */ ! LLVMBuildStore(fn->builder, target_in, addr); } static LLVMValueRef bool_value(struct function *fn, LLVMValueRef value) { if (LLVMTypeOf(value) != LLVMInt1Type()) ! value = LLVMBuildIsNotNull(fn->builder, value, LLVMGetValueName(value)); return value; } static void output_op_cbr(struct function *fn, struct instruction *br) { LLVMValueRef cond = bool_value(fn, ! pseudo_to_value(fn, NULL, br->cond)); LLVMBuildCondBr(fn->builder, cond, br->bb_true->priv, br->bb_false->priv); }
*** 663,680 **** } static void output_op_sel(struct function *fn, struct instruction *insn) { LLVMValueRef target, src1, src2, src3; ! src1 = bool_value(fn, pseudo_to_value(fn, insn, insn->src1)); ! src2 = pseudo_to_value(fn, insn, insn->src2); ! src3 = pseudo_to_value(fn, insn, insn->src3); ! target = LLVMBuildSelect(fn->builder, src1, src2, src3, "select"); ! insn->target->priv = target; } static void output_op_switch(struct function *fn, struct instruction *insn) { LLVMValueRef sw_val, target; --- 752,771 ---- } static void output_op_sel(struct function *fn, struct instruction *insn) { LLVMValueRef target, src1, src2, src3; + char name[MAX_PSEUDO_NAME]; ! src1 = bool_value(fn, pseudo_to_value(fn, NULL, insn->src1)); ! src2 = get_operand(fn, insn->type, insn->src2); ! src3 = get_operand(fn, insn->type, insn->src3); ! pseudo_name(insn->target, name); ! target = LLVMBuildSelect(fn->builder, src1, src2, src3, name); ! insn->target->priv = adjust_type(fn, insn->type, target); } static void output_op_switch(struct function *fn, struct instruction *insn) { LLVMValueRef sw_val, target;
*** 681,735 **** struct basic_block *def = NULL; struct multijmp *jmp; int n_jmp = 0; FOR_EACH_PTR(insn->multijmp_list, jmp) { ! if (jmp->begin == jmp->end) { /* case N */ ! n_jmp++; ! } else if (jmp->begin < jmp->end) { /* case M..N */ ! assert(0); } else /* default case */ def = jmp->target; } END_FOR_EACH_PTR(jmp); ! sw_val = pseudo_to_value(fn, insn, insn->target); target = LLVMBuildSwitch(fn->builder, sw_val, def ? def->priv : NULL, n_jmp); FOR_EACH_PTR(insn->multijmp_list, jmp) { ! if (jmp->begin == jmp->end) { /* case N */ ! LLVMAddCase(target, ! LLVMConstInt(LLVMInt32Type(), jmp->begin, 0), ! jmp->target->priv); ! } else if (jmp->begin < jmp->end) { /* case M..N */ ! assert(0); } } END_FOR_EACH_PTR(jmp); - - insn->target->priv = target; } static void output_op_call(struct function *fn, struct instruction *insn) { LLVMValueRef target, func; int n_arg = 0, i; struct pseudo *arg; LLVMValueRef *args; ! FOR_EACH_PTR(insn->arguments, arg) { ! n_arg++; ! } END_FOR_EACH_PTR(arg); ! args = calloc(n_arg, sizeof(LLVMValueRef)); i = 0; FOR_EACH_PTR(insn->arguments, arg) { ! args[i++] = pseudo_to_value(fn, insn, arg); } END_FOR_EACH_PTR(arg); ! func = pseudo_to_value(fn, insn, insn->func); ! target = LLVMBuildCall(fn->builder, func, args, n_arg, ""); insn->target->priv = target; } static void output_op_phisrc(struct function *fn, struct instruction *insn) --- 772,827 ---- struct basic_block *def = NULL; struct multijmp *jmp; int n_jmp = 0; FOR_EACH_PTR(insn->multijmp_list, jmp) { ! if (jmp->begin <= jmp->end) { ! n_jmp += (jmp->end - jmp->begin) + 1; } else /* default case */ def = jmp->target; } END_FOR_EACH_PTR(jmp); ! sw_val = get_ioperand(fn, insn->type, insn->cond); target = LLVMBuildSwitch(fn->builder, sw_val, def ? def->priv : NULL, n_jmp); FOR_EACH_PTR(insn->multijmp_list, jmp) { ! long long val; ! ! for (val = jmp->begin; val <= jmp->end; val++) { ! LLVMValueRef Val = val_to_value(val, insn->type); ! LLVMAddCase(target, Val, jmp->target->priv); } } END_FOR_EACH_PTR(jmp); } static void output_op_call(struct function *fn, struct instruction *insn) { LLVMValueRef target, func; + struct symbol *ctype; int n_arg = 0, i; struct pseudo *arg; LLVMValueRef *args; + char name[64]; ! n_arg = pseudo_list_size(insn->arguments); args = calloc(n_arg, sizeof(LLVMValueRef)); + PREPARE_PTR_LIST(insn->fntypes, ctype); + if (insn->func->type == PSEUDO_REG || insn->func->type == PSEUDO_PHI) + func = get_operand(fn, ctype, insn->func); + else + func = pseudo_to_value(fn, ctype, insn->func); i = 0; FOR_EACH_PTR(insn->arguments, arg) { ! NEXT_PTR_LIST(ctype); ! args[i++] = pseudo_to_rvalue(fn, ctype, arg); } END_FOR_EACH_PTR(arg); + FINISH_PTR_LIST(ctype); ! pseudo_name(insn->target, name); ! target = LLVMBuildCall(fn->builder, func, args, n_arg, name); insn->target->priv = target; } static void output_op_phisrc(struct function *fn, struct instruction *insn)
*** 738,748 **** struct instruction *phi; assert(insn->target->priv == NULL); /* target = src */ ! v = pseudo_to_value(fn, insn, insn->phi_src); FOR_EACH_PTR(insn->phi_users, phi) { LLVMValueRef load, ptr; assert(phi->opcode == OP_PHI); --- 830,840 ---- struct instruction *phi; assert(insn->target->priv == NULL); /* target = src */ ! v = get_operand(fn, insn->type, insn->phi_src); FOR_EACH_PTR(insn->phi_users, phi) { LLVMValueRef load, ptr; assert(phi->opcode == OP_PHI);
*** 768,813 **** } static void output_op_ptrcast(struct function *fn, struct instruction *insn) { LLVMValueRef src, target; char target_name[64]; ! src = insn->src->priv; ! if (!src) ! src = pseudo_to_value(fn, insn, insn->src); ! pseudo_name(insn->target, target_name); ! assert(!symbol_is_fp_type(insn->type)); ! target = LLVMBuildBitCast(fn->builder, src, insn_symbol_type(fn->module, insn), target_name); ! insn->target->priv = target; } static void output_op_cast(struct function *fn, struct instruction *insn, LLVMOpcode op) { LLVMValueRef src, target; char target_name[64]; ! src = insn->src->priv; ! if (!src) ! src = pseudo_to_value(fn, insn, insn->src); pseudo_name(insn->target, target_name); ! assert(!symbol_is_fp_type(insn->type)); ! if (insn->size < LLVMGetIntTypeWidth(LLVMTypeOf(src))) ! target = LLVMBuildTrunc(fn->builder, src, insn_symbol_type(fn->module, insn), target_name); ! else ! target = LLVMBuildCast(fn->builder, op, src, insn_symbol_type(fn->module, insn), target_name); insn->target->priv = target; } static void output_insn(struct function *fn, struct instruction *insn) { switch (insn->opcode) { case OP_RET: output_op_ret(fn, insn); --- 860,990 ---- } static void output_op_ptrcast(struct function *fn, struct instruction *insn) { LLVMValueRef src, target; + LLVMTypeRef dtype; + struct symbol *otype = insn->orig_type; + LLVMOpcode op; char target_name[64]; ! src = get_operand(fn, otype, insn->src); pseudo_name(insn->target, target_name); ! dtype = symbol_type(insn->type); ! switch (insn->opcode) { ! case OP_UTPTR: ! case OP_SEXT: // FIXME ! assert(is_int_type(otype)); ! assert(is_ptr_type(insn->type)); ! op = LLVMIntToPtr; ! break; ! case OP_PTRTU: ! assert(is_ptr_type(otype)); ! assert(is_int_type(insn->type)); ! op = LLVMPtrToInt; ! break; ! case OP_PTRCAST: ! case OP_ZEXT: // FIXME ! assert(is_ptr_type(otype)); ! assert(is_ptr_type(insn->type)); ! op = LLVMBitCast; ! break; ! default: ! assert(0); ! } ! target = LLVMBuildCast(fn->builder, op, src, dtype, target_name); insn->target->priv = target; } static void output_op_cast(struct function *fn, struct instruction *insn, LLVMOpcode op) { LLVMValueRef src, target; + LLVMTypeRef dtype; + struct symbol *otype = insn->orig_type; char target_name[64]; ! if (is_ptr_type(insn->type)) // cast to void* is OP_CAST ... ! return output_op_ptrcast(fn, insn); + assert(is_int_type(insn->type)); + + src = get_operand(fn, otype, insn->src); pseudo_name(insn->target, target_name); ! dtype = symbol_type(insn->type); ! if (is_ptr_type(otype)) { ! op = LLVMPtrToInt; ! } else if (is_float_type(otype)) { ! assert(op == LLVMFPToUI || op == LLVMFPToSI); ! } else if (is_int_type(otype)) { ! unsigned int width = otype->bit_size; ! if (insn->size < width) ! op = LLVMTrunc; ! else if (insn->size == width) ! op = LLVMBitCast; ! } else { ! assert(0); ! } ! target = LLVMBuildCast(fn->builder, op, src, dtype, target_name); ! insn->target->priv = target; ! } + static void output_op_fpcast(struct function *fn, struct instruction *insn) + { + LLVMTypeRef dtype = symbol_type(insn->type); + LLVMValueRef src, target; + struct symbol *otype = insn->orig_type; + char name[64]; + + assert(is_float_type(insn->type)); + + pseudo_name(insn->target, name); + src = get_operand(fn, otype, insn->src); + switch (insn->opcode) { + case OP_FCVTF: + target = LLVMBuildFPCast(fn->builder, src, dtype, name); + break; + case OP_SCVTF: + target = LLVMBuildSIToFP(fn->builder, src, dtype, name); + break; + case OP_UCVTF: + target = LLVMBuildUIToFP(fn->builder, src, dtype, name); + break; + default: + assert(0); + } insn->target->priv = target; } + static void output_op_setval(struct function *fn, struct instruction *insn) + { + struct expression *val = insn->val; + LLVMValueRef target; + + switch (val->type) { + case EXPR_LABEL: + target = LLVMBlockAddress(fn->fn, val->symbol->bb_target->priv); + break; + default: + assert(0); + } + + insn->target->priv = target; + } + + static void output_op_setfval(struct function *fn, struct instruction *insn) + { + LLVMTypeRef dtype = symbol_type(insn->type); + LLVMValueRef target; + + target = LLVMConstReal(dtype, insn->fvalue); + insn->target->priv = target; + } + static void output_insn(struct function *fn, struct instruction *insn) { switch (insn->opcode) { case OP_RET: output_op_ret(fn, insn);
*** 820,831 **** break; case OP_SYMADDR: assert(0); break; case OP_SETVAL: ! assert(0); break; case OP_SWITCH: output_op_switch(fn, insn); break; case OP_COMPUTEDGOTO: assert(0); --- 997,1011 ---- break; case OP_SYMADDR: assert(0); break; case OP_SETVAL: ! output_op_setval(fn, insn); break; + case OP_SETFVAL: + output_op_setfval(fn, insn); + break; case OP_SWITCH: output_op_switch(fn, insn); break; case OP_COMPUTEDGOTO: assert(0);
*** 837,877 **** output_op_phi(fn, insn); break; case OP_LOAD: output_op_load(fn, insn); break; - case OP_LNOP: - assert(0); - break; case OP_STORE: output_op_store(fn, insn); break; - case OP_SNOP: - assert(0); - break; case OP_INLINED_CALL: - assert(0); break; case OP_CALL: output_op_call(fn, insn); break; ! case OP_CAST: output_op_cast(fn, insn, LLVMZExt); break; ! case OP_SCAST: output_op_cast(fn, insn, LLVMSExt); break; ! case OP_FPCAST: ! assert(0); break; case OP_PTRCAST: output_op_ptrcast(fn, insn); break; case OP_BINARY ... OP_BINARY_END: output_op_binary(fn, insn); break; ! case OP_BINCMP ... OP_BINCMP_END: output_op_compare(fn, insn); break; case OP_SEL: output_op_sel(fn, insn); break; --- 1017,1062 ---- output_op_phi(fn, insn); break; case OP_LOAD: output_op_load(fn, insn); break; case OP_STORE: output_op_store(fn, insn); break; case OP_INLINED_CALL: break; case OP_CALL: output_op_call(fn, insn); break; ! case OP_ZEXT: output_op_cast(fn, insn, LLVMZExt); break; ! case OP_SEXT: output_op_cast(fn, insn, LLVMSExt); break; ! case OP_TRUNC: ! output_op_cast(fn, insn, LLVMTrunc); break; + case OP_FCVTU: + output_op_cast(fn, insn, LLVMFPToUI); + break; + case OP_FCVTS: + output_op_cast(fn, insn, LLVMFPToSI); + break; + case OP_UCVTF: case OP_SCVTF: + case OP_FCVTF: + output_op_fpcast(fn, insn); + break; + case OP_UTPTR: + case OP_PTRTU: case OP_PTRCAST: output_op_ptrcast(fn, insn); break; case OP_BINARY ... OP_BINARY_END: output_op_binary(fn, insn); break; ! case OP_FPCMP ... OP_BINCMP_END: output_op_compare(fn, insn); break; case OP_SEL: output_op_sel(fn, insn); break;
*** 880,901 **** break; case OP_NOT: { LLVMValueRef src, target; char target_name[64]; ! src = pseudo_to_value(fn, insn, insn->src); pseudo_name(insn->target, target_name); target = LLVMBuildNot(fn->builder, src, target_name); insn->target->priv = target; break; } ! case OP_NEG: ! assert(0); break; case OP_CONTEXT: assert(0); break; case OP_RANGE: assert(0); --- 1065,1100 ---- break; case OP_NOT: { LLVMValueRef src, target; char target_name[64]; ! src = pseudo_to_value(fn, insn->type, insn->src); pseudo_name(insn->target, target_name); target = LLVMBuildNot(fn->builder, src, target_name); insn->target->priv = target; break; } ! case OP_FNEG: ! case OP_NEG: { ! LLVMValueRef src, target; ! char target_name[64]; ! ! src = pseudo_to_value(fn, insn->type, insn->src); ! ! pseudo_name(insn->target, target_name); ! ! if (insn->opcode == OP_FNEG) ! target = LLVMBuildFNeg(fn->builder, src, target_name); ! else ! target = LLVMBuildNeg(fn->builder, src, target_name); ! ! insn->target->priv = target; break; + } case OP_CONTEXT: assert(0); break; case OP_RANGE: assert(0);
*** 914,929 **** default: break; } } ! static void output_bb(struct function *fn, struct basic_block *bb, unsigned long generation) { struct instruction *insn; - bb->generation = generation; - FOR_EACH_PTR(bb->insns, insn) { if (!insn->bb) continue; output_insn(fn, insn); --- 1113,1126 ---- default: break; } } ! static void output_bb(struct function *fn, struct basic_block *bb) { struct instruction *insn; FOR_EACH_PTR(bb->insns, insn) { if (!insn->bb) continue; output_insn(fn, insn);
*** 933,979 **** #define MAX_ARGS 64 static void output_fn(LLVMModuleRef module, struct entrypoint *ep) { - unsigned long generation = ++bb_generation; struct symbol *sym = ep->name; struct symbol *base_type = sym->ctype.base_type; - struct symbol *ret_type = sym->ctype.base_type->ctype.base_type; - LLVMTypeRef arg_types[MAX_ARGS]; - LLVMTypeRef return_type; struct function function = { .module = module }; struct basic_block *bb; - struct symbol *arg; - const char *name; int nr_args = 0; ! FOR_EACH_PTR(base_type->arguments, arg) { ! struct symbol *arg_base_type = arg->ctype.base_type; ! ! arg_types[nr_args++] = symbol_type(module, arg_base_type); ! } END_FOR_EACH_PTR(arg); ! ! name = show_ident(sym->ident); ! ! return_type = symbol_type(module, ret_type); ! ! function.type = LLVMFunctionType(return_type, arg_types, nr_args, 0); ! ! function.fn = LLVMAddFunction(module, name, function.type); LLVMSetFunctionCallConv(function.fn, LLVMCCallConv); - LLVMSetLinkage(function.fn, function_linkage(sym)); function.builder = LLVMCreateBuilder(); ! static int nr_bb; ! FOR_EACH_PTR(ep->bbs, bb) { ! if (bb->generation == generation) ! continue; LLVMBasicBlockRef bbr; char bbname[32]; struct instruction *insn; sprintf(bbname, "L%d", nr_bb++); --- 1130,1166 ---- #define MAX_ARGS 64 static void output_fn(LLVMModuleRef module, struct entrypoint *ep) { struct symbol *sym = ep->name; struct symbol *base_type = sym->ctype.base_type; struct function function = { .module = module }; struct basic_block *bb; int nr_args = 0; + int i; ! function.fn = get_sym_value(module, sym); LLVMSetFunctionCallConv(function.fn, LLVMCCallConv); LLVMSetLinkage(function.fn, function_linkage(sym)); function.builder = LLVMCreateBuilder(); ! /* give a name to each argument */ ! nr_args = symbol_list_size(base_type->arguments); ! for (i = 0; i < nr_args; i++) { ! char name[MAX_PSEUDO_NAME]; ! LLVMValueRef arg; ! arg = LLVMGetParam(function.fn, i); ! snprintf(name, sizeof(name), "ARG%d.", i+1); ! LLVMSetValueName(arg, name); ! } + /* create the BBs */ + FOR_EACH_PTR(ep->bbs, bb) { + static int nr_bb; LLVMBasicBlockRef bbr; char bbname[32]; struct instruction *insn; sprintf(bbname, "L%d", nr_bb++);
*** 990,1015 **** if (!insn->bb || insn->opcode != OP_PHI) continue; /* insert alloca into entry block */ entrybbr = LLVMGetEntryBasicBlock(function.fn); LLVMPositionBuilderAtEnd(function.builder, entrybbr); ! phi_type = insn_symbol_type(module, insn); ptr = LLVMBuildAlloca(function.builder, phi_type, ""); /* emit forward load for phi */ LLVMClearInsertionPosition(function.builder); insn->target->priv = LLVMBuildLoad(function.builder, ptr, "phi"); } END_FOR_EACH_PTR(insn); } END_FOR_EACH_PTR(bb); FOR_EACH_PTR(ep->bbs, bb) { - if (bb->generation == generation) - continue; - LLVMPositionBuilderAtEnd(function.builder, bb->priv); ! output_bb(&function, bb, generation); } END_FOR_EACH_PTR(bb); } static LLVMValueRef output_data(LLVMModuleRef module, struct symbol *sym) --- 1177,1199 ---- if (!insn->bb || insn->opcode != OP_PHI) continue; /* insert alloca into entry block */ entrybbr = LLVMGetEntryBasicBlock(function.fn); LLVMPositionBuilderAtEnd(function.builder, entrybbr); ! phi_type = insn_symbol_type(insn); ptr = LLVMBuildAlloca(function.builder, phi_type, ""); /* emit forward load for phi */ LLVMClearInsertionPosition(function.builder); insn->target->priv = LLVMBuildLoad(function.builder, ptr, "phi"); } END_FOR_EACH_PTR(insn); } END_FOR_EACH_PTR(bb); FOR_EACH_PTR(ep->bbs, bb) { LLVMPositionBuilderAtEnd(function.builder, bb->priv); ! output_bb(&function, bb); } END_FOR_EACH_PTR(bb); } static LLVMValueRef output_data(LLVMModuleRef module, struct symbol *sym)
*** 1020,1031 **** const char *name; if (initializer) { switch (initializer->type) { case EXPR_VALUE: ! initial_value = LLVMConstInt(symbol_type(module, sym), initializer->value, 1); break; case EXPR_SYMBOL: { struct symbol *sym = initializer->symbol; initial_value = LLVMGetNamedGlobal(module, show_ident(sym->ident)); if (!initial_value) --- 1204,1218 ---- const char *name; if (initializer) { switch (initializer->type) { case EXPR_VALUE: ! initial_value = LLVMConstInt(symbol_type(sym), initializer->value, 1); break; + case EXPR_FVALUE: + initial_value = LLVMConstReal(symbol_type(sym), initializer->fvalue); + break; case EXPR_SYMBOL: { struct symbol *sym = initializer->symbol; initial_value = LLVMGetNamedGlobal(module, show_ident(sym->ident)); if (!initial_value)
*** 1037,1056 **** initial_value = LLVMConstString(strdup(s), strlen(s) + 1, true); break; } default: ! assert(0); } } else { ! LLVMTypeRef type = symbol_type(module, sym); initial_value = LLVMConstNull(type); } ! name = show_ident(sym->ident); data = LLVMAddGlobal(module, LLVMTypeOf(initial_value), name); LLVMSetLinkage(data, data_linkage(sym)); if (sym->ctype.modifiers & MOD_CONST) LLVMSetGlobalConstant(data, 1); --- 1224,1248 ---- initial_value = LLVMConstString(strdup(s), strlen(s) + 1, true); break; } default: ! warning(initializer->pos, "can't initialize type: %s", show_typename(sym)); ! initial_value = NULL; ! break; } } else { ! LLVMTypeRef type = symbol_type(sym); initial_value = LLVMConstNull(type); } ! if (!initial_value) ! return NULL; + name = sym->ident ? show_ident(sym->ident) : "" ; + data = LLVMAddGlobal(module, LLVMTypeOf(initial_value), name); LLVMSetLinkage(data, data_linkage(sym)); if (sym->ctype.modifiers & MOD_CONST) LLVMSetGlobalConstant(data, 1);
*** 1078,1089 **** FOR_EACH_PTR(list, sym) { struct entrypoint *ep; expand_symbol(sym); ! if (is_prototype(sym)) continue; ep = linearize_symbol(sym); if (ep) output_fn(module, ep); else --- 1270,1284 ---- FOR_EACH_PTR(list, sym) { struct entrypoint *ep; expand_symbol(sym); ! if (is_prototype(sym)) { ! // this will do the LLVMAddFunction() we want ! get_sym_value(module, sym); continue; + } ep = linearize_symbol(sym); if (ep) output_fn(module, ep); else
*** 1156,1171 **** compile(module, symlist); /* need ->phi_users */ dbg_dead = 1; ! FOR_EACH_PTR_NOTAG(filelist, file) { symlist = sparse(file); if (die_if_error) return 1; compile(module, symlist); ! } END_FOR_EACH_PTR_NOTAG(file); LLVMVerifyModule(module, LLVMPrintMessageAction, NULL); LLVMWriteBitcodeToFD(module, STDOUT_FILENO, 0, 0); --- 1351,1366 ---- compile(module, symlist); /* need ->phi_users */ dbg_dead = 1; ! FOR_EACH_PTR(filelist, file) { symlist = sparse(file); if (die_if_error) return 1; compile(module, symlist); ! } END_FOR_EACH_PTR(file); LLVMVerifyModule(module, LLVMPrintMessageAction, NULL); LLVMWriteBitcodeToFD(module, STDOUT_FILENO, 0, 0);