/* Find the last bit set. */ static void emit_umsb(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMBuilderRef builder = gallivm->builder; LLVMValueRef args[2] = { emit_data->args[0], /* Don't generate code for handling zero: */ LLVMConstInt(LLVMInt1TypeInContext(gallivm->context), 1, 0) }; LLVMValueRef msb = lp_build_intrinsic(builder, "llvm.ctlz.i32", emit_data->dst_type, args, ARRAY_SIZE(args), LLVMReadNoneAttribute); /* The HW returns the last bit index from MSB, but TGSI wants * the index from LSB. Invert it by doing "31 - msb". */ msb = LLVMBuildSub(builder, lp_build_const_int32(gallivm, 31), msb, ""); /* Check for zero: */ emit_data->output[emit_data->chan] = LLVMBuildSelect(builder, LLVMBuildICmp(builder, LLVMIntEQ, args[0], bld_base->uint_bld.zero, ""), lp_build_const_int32(gallivm, -1), msb, ""); }
/* this is ffs in C */ static void emit_lsb(const struct lp_build_tgsi_action *action, struct lp_build_tgsi_context *bld_base, struct lp_build_emit_data *emit_data) { struct gallivm_state *gallivm = bld_base->base.gallivm; LLVMBuilderRef builder = gallivm->builder; LLVMValueRef args[2] = { emit_data->args[0], /* The value of 1 means that ffs(x=0) = undef, so LLVM won't * add special code to check for x=0. The reason is that * the LLVM behavior for x=0 is different from what we * need here. However, LLVM also assumes that ffs(x) is * in [0, 31], but GLSL expects that ffs(0) = -1, so * a conditional assignment to handle 0 is still required. */ LLVMConstInt(LLVMInt1TypeInContext(gallivm->context), 1, 0) }; LLVMValueRef lsb = lp_build_intrinsic(gallivm->builder, "llvm.cttz.i32", emit_data->dst_type, args, ARRAY_SIZE(args), LLVMReadNoneAttribute); /* TODO: We need an intrinsic to skip this conditional. */ /* Check for zero: */ emit_data->output[emit_data->chan] = LLVMBuildSelect(builder, LLVMBuildICmp(builder, LLVMIntEQ, args[0], bld_base->uint_bld.zero, ""), lp_build_const_int32(gallivm, -1), lsb, ""); }
/* Initialize module-independent parts of the context. * * The caller is responsible for initializing ctx::module and ctx::builder. */ void ac_llvm_context_init(struct ac_llvm_context *ctx, LLVMContextRef context) { LLVMValueRef args[1]; ctx->context = context; ctx->module = NULL; ctx->builder = NULL; ctx->voidt = LLVMVoidTypeInContext(ctx->context); ctx->i1 = LLVMInt1TypeInContext(ctx->context); ctx->i8 = LLVMInt8TypeInContext(ctx->context); ctx->i16 = LLVMIntTypeInContext(ctx->context, 16); ctx->i32 = LLVMIntTypeInContext(ctx->context, 32); ctx->i64 = LLVMIntTypeInContext(ctx->context, 64); ctx->f16 = LLVMHalfTypeInContext(ctx->context); ctx->f32 = LLVMFloatTypeInContext(ctx->context); ctx->f64 = LLVMDoubleTypeInContext(ctx->context); ctx->v4i32 = LLVMVectorType(ctx->i32, 4); ctx->v4f32 = LLVMVectorType(ctx->f32, 4); ctx->v8i32 = LLVMVectorType(ctx->i32, 8); ctx->i32_0 = LLVMConstInt(ctx->i32, 0, false); ctx->i32_1 = LLVMConstInt(ctx->i32, 1, false); ctx->f32_0 = LLVMConstReal(ctx->f32, 0.0); ctx->f32_1 = LLVMConstReal(ctx->f32, 1.0); ctx->range_md_kind = LLVMGetMDKindIDInContext(ctx->context, "range", 5); ctx->invariant_load_md_kind = LLVMGetMDKindIDInContext(ctx->context, "invariant.load", 14); ctx->fpmath_md_kind = LLVMGetMDKindIDInContext(ctx->context, "fpmath", 6); args[0] = LLVMConstReal(ctx->f32, 2.5); ctx->fpmath_md_2p5_ulp = LLVMMDNodeInContext(ctx->context, args, 1); ctx->uniform_md_kind = LLVMGetMDKindIDInContext(ctx->context, "amdgpu.uniform", 14); ctx->empty_md = LLVMMDNodeInContext(ctx->context, NULL, 0); }
// Generates the allocas for the function arguments. This has to be called // from the block since that is where the entry block is created. // // node - The function node. // module - The compilation unit this node is a part of. // // Returns 0 if successful, otherwise returns -1. int qip_ast_function_codegen_args(qip_ast_node *node, qip_module *module) { int rc; unsigned int i; check(node != NULL, "Node required"); check(node->type == QIP_AST_TYPE_FUNCTION, "Node type expected to be 'function'"); check(module != NULL, "Module required"); LLVMBuilderRef builder = module->compiler->llvm_builder; LLVMContextRef context = LLVMGetModuleContext(module->llvm_module); // Retrieve current function scope. qip_scope *scope = NULL; rc = qip_module_get_current_function_scope(module, &scope); check(rc == 0 && scope != NULL, "Unable to retrieve current function scope"); // Codegen allocas. LLVMValueRef *values = malloc(sizeof(LLVMValueRef) * node->function.arg_count); check_mem(values); for(i=0; i<node->function.arg_count; i++) { rc = qip_ast_node_codegen(node->function.args[i], module, &values[i]); check(rc == 0, "Unable to determine function argument type"); } scope->llvm_last_alloca = LLVMBuildAlloca(builder, LLVMInt1TypeInContext(context), "nop"); // Codegen store instructions. for(i=0; i<node->function.arg_count; i++) { LLVMValueRef param = LLVMGetParam(scope->llvm_function, i); LLVMValueRef build_value = LLVMBuildStore(builder, param, values[i]); check(build_value != NULL, "Unable to create store instruction"); } free(values); return 0; error: if(values) free(values); return -1; }
LLVMTypeRef ett_llvm_type(EagleComplexType *type) { switch(type->type) { case ETVoid: return LLVMVoidTypeInContext(utl_get_current_context()); case ETFloat: return LLVMFloatTypeInContext(utl_get_current_context()); case ETDouble: return LLVMDoubleTypeInContext(utl_get_current_context()); case ETInt1: return LLVMInt1TypeInContext(utl_get_current_context()); case ETGeneric: // In practice this doesn't matter case ETAny: case ETInt8: case ETUInt8: return LLVMInt8TypeInContext(utl_get_current_context()); case ETInt16: case ETUInt16: return LLVMInt16TypeInContext(utl_get_current_context()); case ETInt32: case ETUInt32: return LLVMInt32TypeInContext(utl_get_current_context()); case ETInt64: case ETUInt64: return LLVMInt64TypeInContext(utl_get_current_context()); case ETCString: return LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); case ETEnum: return LLVMInt64TypeInContext(utl_get_current_context()); case ETGenerator: { if(generator_type) return generator_type; LLVMTypeRef ptmp[2]; ptmp[0] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); ptmp[1] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); generator_type = LLVMStructCreateNamed(utl_get_current_context(), "__egl_gen_strct"); LLVMStructSetBody(generator_type, ptmp, 2, 0); return generator_type; } case ETClass: case ETStruct: { EagleStructType *st = (EagleStructType *)type; LLVMTypeRef loaded = LLVMGetTypeByName(the_module, st->name); if(loaded) return loaded; return NULL; // LLVMTypeRef ty = LLVMStructTypeInContext(utl_get_current_context(), } case ETInterface: { return LLVMInt8TypeInContext(utl_get_current_context()); } case ETPointer: { EaglePointerType *pt = (EaglePointerType *)type; if(pt->counted || pt->weak) { LLVMTypeRef ptmp[2]; ptmp[0] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); ptmp[1] = LLVMInt1TypeInContext(utl_get_current_context()); LLVMTypeRef tys[6]; tys[0] = LLVMInt64TypeInContext(utl_get_current_context()); tys[1] = LLVMInt16TypeInContext(utl_get_current_context()); tys[2] = LLVMInt16TypeInContext(utl_get_current_context()); tys[3] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); tys[4] = LLVMPointerType(LLVMFunctionType(LLVMVoidTypeInContext(utl_get_current_context()), ptmp, 2, 0), 0); tys[5] = ett_llvm_type(pt->to); return LLVMPointerType(ty_get_counted(LLVMStructTypeInContext(utl_get_current_context(), tys, 6, 0)), 0); } return LLVMPointerType(ett_llvm_type(((EaglePointerType *)type)->to), 0); } case ETArray: { EagleArrayType *at = (EagleArrayType *)type; if(at->ct < 0) return LLVMPointerType(ett_llvm_type(at->of), 0); else return LLVMArrayType(ett_llvm_type(at->of), at->ct); } case ETFunction: { EagleFunctionType *ft = (EagleFunctionType *)type; if(ET_IS_CLOSURE(type)) { LLVMTypeRef tys[2]; tys[0] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); tys[1] = LLVMPointerType(LLVMInt8TypeInContext(utl_get_current_context()), 0); return LLVMStructTypeInContext(utl_get_current_context(), tys, 2, 0); } LLVMTypeRef *tys = malloc(sizeof(LLVMTypeRef) * ft->pct); int i; for(i = 0; i < ft->pct; i++) tys[i] = ett_llvm_type(ft->params[i]); LLVMTypeRef out = LLVMFunctionType(ett_llvm_type(ft->retType), tys, ft->pct, 0); free(tys); return out; } default: return NULL; } }
static void init_runtime(compile_t* c) { c->str_builtin = stringtab("$0"); c->str_Bool = stringtab("Bool"); c->str_I8 = stringtab("I8"); c->str_I16 = stringtab("I16"); c->str_I32 = stringtab("I32"); c->str_I64 = stringtab("I64"); c->str_I128 = stringtab("I128"); c->str_ILong = stringtab("ILong"); c->str_ISize = stringtab("ISize"); c->str_U8 = stringtab("U8"); c->str_U16 = stringtab("U16"); c->str_U32 = stringtab("U32"); c->str_U64 = stringtab("U64"); c->str_U128 = stringtab("U128"); c->str_ULong = stringtab("ULong"); c->str_USize = stringtab("USize"); c->str_F32 = stringtab("F32"); c->str_F64 = stringtab("F64"); c->str_Pointer = stringtab("Pointer"); c->str_Maybe = stringtab("MaybePointer"); c->str_DoNotOptimise = stringtab("DoNotOptimise"); c->str_Array = stringtab("Array"); c->str_String = stringtab("String"); c->str_Platform = stringtab("Platform"); c->str_Main = stringtab("Main"); c->str_Env = stringtab("Env"); c->str_add = stringtab("add"); c->str_sub = stringtab("sub"); c->str_mul = stringtab("mul"); c->str_div = stringtab("div"); c->str_mod = stringtab("mod"); c->str_neg = stringtab("neg"); c->str_add_unsafe = stringtab("add_unsafe"); c->str_sub_unsafe = stringtab("sub_unsafe"); c->str_mul_unsafe = stringtab("mul_unsafe"); c->str_div_unsafe = stringtab("div_unsafe"); c->str_mod_unsafe = stringtab("mod_unsafe"); c->str_neg_unsafe = stringtab("neg_unsafe"); c->str_and = stringtab("op_and"); c->str_or = stringtab("op_or"); c->str_xor = stringtab("op_xor"); c->str_not = stringtab("op_not"); c->str_shl = stringtab("shl"); c->str_shr = stringtab("shr"); c->str_shl_unsafe = stringtab("shl_unsafe"); c->str_shr_unsafe = stringtab("shr_unsafe"); c->str_eq = stringtab("eq"); c->str_ne = stringtab("ne"); c->str_lt = stringtab("lt"); c->str_le = stringtab("le"); c->str_ge = stringtab("ge"); c->str_gt = stringtab("gt"); c->str_eq_unsafe = stringtab("eq_unsafe"); c->str_ne_unsafe = stringtab("ne_unsafe"); c->str_lt_unsafe = stringtab("lt_unsafe"); c->str_le_unsafe = stringtab("le_unsafe"); c->str_ge_unsafe = stringtab("ge_unsafe"); c->str_gt_unsafe = stringtab("gt_unsafe"); c->str_this = stringtab("this"); c->str_create = stringtab("create"); c->str__create = stringtab("_create"); c->str__init = stringtab("_init"); c->str__final = stringtab("_final"); c->str__event_notify = stringtab("_event_notify"); c->str__serialise_space = stringtab("_serialise_space"); c->str__serialise = stringtab("_serialise"); c->str__deserialise = stringtab("_deserialise"); LLVMTypeRef type; LLVMTypeRef params[5]; LLVMValueRef value; c->void_type = LLVMVoidTypeInContext(c->context); c->i1 = LLVMInt1TypeInContext(c->context); c->i8 = LLVMInt8TypeInContext(c->context); c->i16 = LLVMInt16TypeInContext(c->context); c->i32 = LLVMInt32TypeInContext(c->context); c->i64 = LLVMInt64TypeInContext(c->context); c->i128 = LLVMIntTypeInContext(c->context, 128); c->f32 = LLVMFloatTypeInContext(c->context); c->f64 = LLVMDoubleTypeInContext(c->context); c->intptr = LLVMIntPtrTypeInContext(c->context, c->target_data); // i8* c->void_ptr = LLVMPointerType(c->i8, 0); // forward declare object c->object_type = LLVMStructCreateNamed(c->context, "__object"); c->object_ptr = LLVMPointerType(c->object_type, 0); // padding required in an actor between the descriptor and fields c->actor_pad = LLVMArrayType(c->i8, PONY_ACTOR_PAD_SIZE); // message params[0] = c->i32; // size params[1] = c->i32; // id c->msg_type = LLVMStructCreateNamed(c->context, "__message"); c->msg_ptr = LLVMPointerType(c->msg_type, 0); LLVMStructSetBody(c->msg_type, params, 2, false); // trace // void (*)(i8*, __object*) params[0] = c->void_ptr; params[1] = c->object_ptr; c->trace_type = LLVMFunctionType(c->void_type, params, 2, false); c->trace_fn = LLVMPointerType(c->trace_type, 0); // serialise // void (*)(i8*, __object*, i8*, intptr, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->void_ptr; params[3] = c->intptr; params[4] = c->i32; c->serialise_type = LLVMFunctionType(c->void_type, params, 5, false); c->serialise_fn = LLVMPointerType(c->serialise_type, 0); // serialise_space // i64 (__object*) params[0] = c->object_ptr; c->custom_serialise_space_fn = LLVMPointerType( LLVMFunctionType(c->i64, params, 1, false), 0); // custom_deserialise // void (*)(__object*, void*) params[0] = c->object_ptr; params[1] = c->void_ptr; c->custom_deserialise_fn = LLVMPointerType( LLVMFunctionType(c->void_type, params, 2, false), 0); // dispatch // void (*)(i8*, __object*, $message*) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->msg_ptr; c->dispatch_type = LLVMFunctionType(c->void_type, params, 3, false); c->dispatch_fn = LLVMPointerType(c->dispatch_type, 0); // void (*)(__object*) params[0] = c->object_ptr; c->final_fn = LLVMPointerType( LLVMFunctionType(c->void_type, params, 1, false), 0); // descriptor, opaque version // We need this in order to build our own structure. const char* desc_name = genname_descriptor(NULL); c->descriptor_type = LLVMStructCreateNamed(c->context, desc_name); c->descriptor_ptr = LLVMPointerType(c->descriptor_type, 0); // field descriptor // Also needed to build a descriptor structure. params[0] = c->i32; params[1] = c->descriptor_ptr; c->field_descriptor = LLVMStructTypeInContext(c->context, params, 2, false); // descriptor, filled in gendesc_basetype(c, c->descriptor_type); // define object params[0] = c->descriptor_ptr; LLVMStructSetBody(c->object_type, params, 1, false); #if PONY_LLVM >= 309 LLVM_DECLARE_ATTRIBUTEREF(nounwind_attr, nounwind, 0); LLVM_DECLARE_ATTRIBUTEREF(readnone_attr, readnone, 0); LLVM_DECLARE_ATTRIBUTEREF(readonly_attr, readonly, 0); LLVM_DECLARE_ATTRIBUTEREF(inacc_or_arg_mem_attr, inaccessiblemem_or_argmemonly, 0); LLVM_DECLARE_ATTRIBUTEREF(noalias_attr, noalias, 0); LLVM_DECLARE_ATTRIBUTEREF(noreturn_attr, noreturn, 0); LLVM_DECLARE_ATTRIBUTEREF(deref_actor_attr, dereferenceable, PONY_ACTOR_PAD_SIZE + (target_is_ilp32(c->opt->triple) ? 4 : 8)); LLVM_DECLARE_ATTRIBUTEREF(align_pool_attr, align, ponyint_pool_size(0)); LLVM_DECLARE_ATTRIBUTEREF(align_heap_attr, align, HEAP_MIN); LLVM_DECLARE_ATTRIBUTEREF(deref_or_null_alloc_attr, dereferenceable_or_null, HEAP_MIN); LLVM_DECLARE_ATTRIBUTEREF(deref_alloc_small_attr, dereferenceable, HEAP_MIN); LLVM_DECLARE_ATTRIBUTEREF(deref_alloc_large_attr, dereferenceable, HEAP_MAX << 1); #endif // i8* pony_ctx() type = LLVMFunctionType(c->void_ptr, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_ctx", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, readnone_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMAddFunctionAttr(value, LLVMReadNoneAttribute); #endif // __object* pony_create(i8*, __Desc*) params[0] = c->void_ptr; params[1] = c->descriptor_ptr; type = LLVMFunctionType(c->object_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_create", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_actor_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_pool_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, PONY_ACTOR_PAD_SIZE + (target_is_ilp32(c->opt->triple) ? 4 : 8)); #endif // void ponyint_destroy(__object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "ponyint_destroy", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // void pony_sendv(i8*, __object*, $message*, $message*) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->msg_ptr; params[3] = c->msg_ptr; type = LLVMFunctionType(c->void_type, params, 4, false); value = LLVMAddFunction(c->module, "pony_sendv", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // void pony_sendv_single(i8*, __object*, $message*, $message*) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->msg_ptr; params[3] = c->msg_ptr; type = LLVMFunctionType(c->void_type, params, 4, false); value = LLVMAddFunction(c->module, "pony_sendv_single", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // i8* pony_alloc(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_or_null_alloc_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // i8* pony_alloc_small(i8*, i32) params[0] = c->void_ptr; params[1] = c->i32; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_small", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_alloc_small_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MIN); #endif // i8* pony_alloc_large(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_large", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_alloc_large_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MAX << 1); #endif // i8* pony_realloc(i8*, i8*, intptr) params[0] = c->void_ptr; params[1] = c->void_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_realloc", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_or_null_alloc_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // i8* pony_alloc_final(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_final", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_or_null_alloc_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // i8* pony_alloc_small_final(i8*, i32) params[0] = c->void_ptr; params[1] = c->i32; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_small_final", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_alloc_small_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MIN); #endif // i8* pony_alloc_large_final(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_large_final", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, deref_alloc_large_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_heap_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MAX << 1); #endif // $message* pony_alloc_msg(i32, i32) params[0] = c->i32; params[1] = c->i32; type = LLVMFunctionType(c->msg_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_msg", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, align_pool_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); #endif // void pony_trace(i8*, i8*) params[0] = c->void_ptr; params[1] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_trace", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, 2, readnone_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif value = LLVMGetParam(value, 1); LLVMAddAttribute(value, LLVMReadNoneAttribute); #endif // void pony_traceknown(i8*, __object*, __Desc*, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->descriptor_ptr; params[3] = c->i32; type = LLVMFunctionType(c->void_type, params, 4, false); value = LLVMAddFunction(c->module, "pony_traceknown", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, 2, readonly_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif value = LLVMGetParam(value, 1); LLVMAddAttribute(value, LLVMReadOnlyAttribute); #endif // void pony_traceunknown(i8*, __object*, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->i32; type = LLVMFunctionType(c->void_type, params, 3, false); value = LLVMAddFunction(c->module, "pony_traceunknown", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, 2, readonly_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif value = LLVMGetParam(value, 1); LLVMAddAttribute(value, LLVMReadOnlyAttribute); #endif // void pony_gc_send(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_gc_send", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // void pony_gc_recv(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_gc_recv", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // void pony_send_done(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_send_done", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); #endif // void pony_recv_done(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_recv_done", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); #endif // void pony_serialise_reserve(i8*, i8*, intptr) params[0] = c->void_ptr; params[1] = c->void_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_type, params, 3, false); value = LLVMAddFunction(c->module, "pony_serialise_reserve", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, 2, readnone_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif value = LLVMGetParam(value, 1); LLVMAddAttribute(value, LLVMReadNoneAttribute); #endif // intptr pony_serialise_offset(i8*, i8*) params[0] = c->void_ptr; params[1] = c->void_ptr; type = LLVMFunctionType(c->intptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_serialise_offset", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, 2, readonly_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif value = LLVMGetParam(value, 1); LLVMAddAttribute(value, LLVMReadOnlyAttribute); #endif // i8* pony_deserialise_offset(i8*, __desc*, intptr) params[0] = c->void_ptr; params[1] = c->descriptor_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_deserialise_offset", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #elif PONY_LLVM == 308 LLVMSetInaccessibleMemOrArgMemOnly(value); #endif // i8* pony_deserialise_block(i8*, intptr, intptr) params[0] = c->void_ptr; params[1] = c->intptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_deserialise_block", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeReturnIndex, noalias_attr); #else # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif LLVMSetReturnNoAlias(value); #endif // i32 pony_init(i32, i8**) params[0] = c->i32; params[1] = LLVMPointerType(c->void_ptr, 0); type = LLVMFunctionType(c->i32, params, 2, false); value = LLVMAddFunction(c->module, "pony_init", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // void pony_become(i8*, __object*) params[0] = c->void_ptr; params[1] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_become", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // i32 pony_start(i32, i32) params[0] = c->i32; params[1] = c->i32; type = LLVMFunctionType(c->i32, params, 2, false); value = LLVMAddFunction(c->module, "pony_start", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, inacc_or_arg_mem_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); # if PONY_LLVM >= 308 LLVMSetInaccessibleMemOrArgMemOnly(value); # endif #endif // i32 pony_get_exitcode() type = LLVMFunctionType(c->i32, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_get_exitcode", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, readonly_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMAddFunctionAttr(value, LLVMReadOnlyAttribute); #endif // void pony_throw() type = LLVMFunctionType(c->void_type, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_throw", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, noreturn_attr); #else LLVMAddFunctionAttr(value, LLVMNoReturnAttribute); #endif // i32 pony_personality_v0(...) type = LLVMFunctionType(c->i32, NULL, 0, true); c->personality = LLVMAddFunction(c->module, "pony_personality_v0", type); // i32 memcmp(i8*, i8*, intptr) params[0] = c->void_ptr; params[1] = c->void_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->i32, params, 3, false); value = LLVMAddFunction(c->module, "memcmp", type); #if PONY_LLVM >= 309 LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr); LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, readonly_attr); LLVMAddAttributeAtIndex(value, 1, readonly_attr); LLVMAddAttributeAtIndex(value, 2, readonly_attr); #else LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMAddFunctionAttr(value, LLVMReadOnlyAttribute); LLVMValueRef param = LLVMGetParam(value, 0); LLVMAddAttribute(param, LLVMReadOnlyAttribute); param = LLVMGetParam(value, 1); LLVMAddAttribute(param, LLVMReadOnlyAttribute); #endif }
static void init_runtime(compile_t* c) { c->str_1 = stringtab("$1"); c->str_Bool = stringtab("Bool"); c->str_I8 = stringtab("I8"); c->str_I16 = stringtab("I16"); c->str_I32 = stringtab("I32"); c->str_I64 = stringtab("I64"); c->str_I128 = stringtab("I128"); c->str_U8 = stringtab("U8"); c->str_U16 = stringtab("U16"); c->str_U32 = stringtab("U32"); c->str_U64 = stringtab("U64"); c->str_U128 = stringtab("U128"); c->str_F32 = stringtab("F32"); c->str_F64 = stringtab("F64"); c->str_Pointer = stringtab("Pointer"); c->str_Array = stringtab("Array"); c->str_Platform = stringtab("Platform"); c->str_add = stringtab("add"); c->str_sub = stringtab("sub"); c->str_mul = stringtab("mul"); c->str_div = stringtab("div"); c->str_mod = stringtab("mod"); c->str_neg = stringtab("neg"); c->str_and = stringtab("op_and"); c->str_or = stringtab("op_or"); c->str_xor = stringtab("op_xor"); c->str_not = stringtab("op_not"); c->str_shl = stringtab("shl"); c->str_shr = stringtab("shr"); c->str_eq = stringtab("eq"); c->str_ne = stringtab("ne"); c->str_lt = stringtab("lt"); c->str_le = stringtab("le"); c->str_ge = stringtab("ge"); c->str_gt = stringtab("gt"); LLVMTypeRef type; LLVMTypeRef params[4]; LLVMValueRef value; c->void_type = LLVMVoidTypeInContext(c->context); c->i1 = LLVMInt1TypeInContext(c->context); c->i8 = LLVMInt8TypeInContext(c->context); c->i16 = LLVMInt16TypeInContext(c->context); c->i32 = LLVMInt32TypeInContext(c->context); c->i64 = LLVMInt64TypeInContext(c->context); c->i128 = LLVMIntTypeInContext(c->context, 128); c->f32 = LLVMFloatTypeInContext(c->context); c->f64 = LLVMDoubleTypeInContext(c->context); c->intptr = LLVMIntPtrTypeInContext(c->context, c->target_data); // i8* c->void_ptr = LLVMPointerType(c->i8, 0); // forward declare object c->object_type = LLVMStructCreateNamed(c->context, "$object"); c->object_ptr = LLVMPointerType(c->object_type, 0); // padding required in an actor between the descriptor and fields c->actor_pad = LLVMArrayType(c->i8, PONY_ACTOR_PAD_SIZE); // message params[0] = c->i32; // size params[1] = c->i32; // id c->msg_type = LLVMStructCreateNamed(c->context, "$message"); c->msg_ptr = LLVMPointerType(c->msg_type, 0); LLVMStructSetBody(c->msg_type, params, 2, false); // trace // void (*)($object*) params[0] = c->object_ptr; c->trace_type = LLVMFunctionType(c->void_type, params, 1, false); c->trace_fn = LLVMPointerType(c->trace_type, 0); // dispatch // void (*)($object*, $message*) params[0] = c->object_ptr; params[1] = c->msg_ptr; c->dispatch_type = LLVMFunctionType(c->void_type, params, 2, false); c->dispatch_fn = LLVMPointerType(c->dispatch_type, 0); // void (*)($object*) params[0] = c->object_ptr; c->final_fn = LLVMPointerType( LLVMFunctionType(c->void_type, params, 1, false), 0); // descriptor, opaque version // We need this in order to build our own structure. const char* desc_name = genname_descriptor(NULL); c->descriptor_type = LLVMStructCreateNamed(c->context, desc_name); c->descriptor_ptr = LLVMPointerType(c->descriptor_type, 0); // field descriptor // Also needed to build a descriptor structure. params[0] = c->i32; params[1] = c->descriptor_ptr; c->field_descriptor = LLVMStructTypeInContext(c->context, params, 2, false); // descriptor, filled in c->descriptor_type = gendesc_type(c, NULL); // define object params[0] = c->descriptor_ptr; LLVMStructSetBody(c->object_type, params, 1, false); // $object* pony_create($desc*) params[0] = c->descriptor_ptr; type = LLVMFunctionType(c->object_ptr, params, 1, false); value = LLVMAddFunction(c->module, "pony_create", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // void pony_destroy($object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_destroy", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); //LLVMSetReturnNoAlias(value); // void pony_sendv($object*, $message*); params[0] = c->object_ptr; params[1] = c->msg_ptr; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_sendv", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* pony_alloc(i64) params[0] = c->i64; type = LLVMFunctionType(c->void_ptr, params, 1, false); value = LLVMAddFunction(c->module, "pony_alloc", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // i8* pony_realloc(i8*, i64) params[0] = c->void_ptr; params[1] = c->i64; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_realloc", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // i8* pony_alloc_final(i64, c->final_fn) params[0] = c->i64; params[1] = c->final_fn; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_final", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // $message* pony_alloc_msg(i32, i32) params[0] = c->i32; params[1] = c->i32; type = LLVMFunctionType(c->msg_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_msg", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // void pony_trace(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_trace", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_traceactor($object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_traceactor", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_traceobject($object*, trace_fn) params[0] = c->object_ptr; params[1] = c->trace_fn; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_traceobject", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_traceunknown($object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_traceunknown", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_trace_tag_or_actor($object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_trace_tag_or_actor", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_gc_send() type = LLVMFunctionType(c->void_type, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_gc_send", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_gc_recv() type = LLVMFunctionType(c->void_type, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_gc_recv", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_send_done() type = LLVMFunctionType(c->void_type, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_send_done", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_recv_done() type = LLVMFunctionType(c->void_type, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_recv_done", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i32 pony_init(i32, i8**) params[0] = c->i32; params[1] = LLVMPointerType(c->void_ptr, 0); type = LLVMFunctionType(c->i32, params, 2, false); value = LLVMAddFunction(c->module, "pony_init", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_become($object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_become", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i32 pony_start(i32) params[0] = c->i32; type = LLVMFunctionType(c->i32, params, 1, false); value = LLVMAddFunction(c->module, "pony_start", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_throw() type = LLVMFunctionType(c->void_type, NULL, 0, false); LLVMAddFunction(c->module, "pony_throw", type); // i32 pony_personality_v0(...) type = LLVMFunctionType(c->i32, NULL, 0, true); c->personality = LLVMAddFunction(c->module, "pony_personality_v0", type); // i8* memcpy(...) type = LLVMFunctionType(c->void_ptr, NULL, 0, true); value = LLVMAddFunction(c->module, "memcpy", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* memmove(...) type = LLVMFunctionType(c->void_ptr, NULL, 0, true); value = LLVMAddFunction(c->module, "memmove", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); }
/** * Return mask ? a : b; * * mask is a bitwise mask, composed of 0 or ~0 for each element. Any other value * will yield unpredictable results. */ LLVMValueRef lp_build_select(struct lp_build_context *bld, LLVMValueRef mask, LLVMValueRef a, LLVMValueRef b) { LLVMBuilderRef builder = bld->gallivm->builder; LLVMContextRef lc = bld->gallivm->context; struct lp_type type = bld->type; LLVMValueRef res; assert(lp_check_value(type, a)); assert(lp_check_value(type, b)); if(a == b) return a; if (type.length == 1) { mask = LLVMBuildTrunc(builder, mask, LLVMInt1TypeInContext(lc), ""); res = LLVMBuildSelect(builder, mask, a, b, ""); } else if (0) { /* Generate a vector select. * * XXX: Using vector selects would avoid emitting intrinsics, but they aren't * properly supported yet. * * LLVM 3.0 includes experimental support provided the -promote-elements * options is passed to LLVM's command line (e.g., via * llvm::cl::ParseCommandLineOptions), but resulting code quality is much * worse, probably because some optimization passes don't know how to * handle vector selects. * * See also: * - http://lists.cs.uiuc.edu/pipermail/llvmdev/2011-October/043659.html */ /* Convert the mask to a vector of booleans. * XXX: There are two ways to do this. Decide what's best. */ if (1) { LLVMTypeRef bool_vec_type = LLVMVectorType(LLVMInt1TypeInContext(lc), type.length); mask = LLVMBuildTrunc(builder, mask, bool_vec_type, ""); } else { mask = LLVMBuildICmp(builder, LLVMIntNE, mask, LLVMConstNull(bld->int_vec_type), ""); } res = LLVMBuildSelect(builder, mask, a, b, ""); } else if (((util_cpu_caps.has_sse4_1 && type.width * type.length == 128) || (util_cpu_caps.has_avx && type.width * type.length == 256 && type.width >= 32)) && !LLVMIsConstant(a) && !LLVMIsConstant(b) && !LLVMIsConstant(mask)) { const char *intrinsic; LLVMTypeRef arg_type; LLVMValueRef args[3]; /* * There's only float blend in AVX but can just cast i32/i64 * to float. */ if (type.width * type.length == 256) { if (type.width == 64) { intrinsic = "llvm.x86.avx.blendv.pd.256"; arg_type = LLVMVectorType(LLVMDoubleTypeInContext(lc), 4); } else { intrinsic = "llvm.x86.avx.blendv.ps.256"; arg_type = LLVMVectorType(LLVMFloatTypeInContext(lc), 8); } } else if (type.floating && type.width == 64) { intrinsic = "llvm.x86.sse41.blendvpd"; arg_type = LLVMVectorType(LLVMDoubleTypeInContext(lc), 2); } else if (type.floating && type.width == 32) { intrinsic = "llvm.x86.sse41.blendvps"; arg_type = LLVMVectorType(LLVMFloatTypeInContext(lc), 4); } else { intrinsic = "llvm.x86.sse41.pblendvb"; arg_type = LLVMVectorType(LLVMInt8TypeInContext(lc), 16); } if (arg_type != bld->int_vec_type) { mask = LLVMBuildBitCast(builder, mask, arg_type, ""); } if (arg_type != bld->vec_type) { a = LLVMBuildBitCast(builder, a, arg_type, ""); b = LLVMBuildBitCast(builder, b, arg_type, ""); } args[0] = b; args[1] = a; args[2] = mask; res = lp_build_intrinsic(builder, intrinsic, arg_type, args, Elements(args)); if (arg_type != bld->vec_type) { res = LLVMBuildBitCast(builder, res, bld->vec_type, ""); } } else { res = lp_build_select_bitwise(bld, mask, a, b); } return res; }
static void init_runtime(compile_t* c) { c->str_builtin = stringtab("$0"); c->str_Bool = stringtab("Bool"); c->str_I8 = stringtab("I8"); c->str_I16 = stringtab("I16"); c->str_I32 = stringtab("I32"); c->str_I64 = stringtab("I64"); c->str_I128 = stringtab("I128"); c->str_ILong = stringtab("ILong"); c->str_ISize = stringtab("ISize"); c->str_U8 = stringtab("U8"); c->str_U16 = stringtab("U16"); c->str_U32 = stringtab("U32"); c->str_U64 = stringtab("U64"); c->str_U128 = stringtab("U128"); c->str_ULong = stringtab("ULong"); c->str_USize = stringtab("USize"); c->str_F32 = stringtab("F32"); c->str_F64 = stringtab("F64"); c->str_Pointer = stringtab("Pointer"); c->str_Maybe = stringtab("MaybePointer"); c->str_DoNotOptimise = stringtab("DoNotOptimise"); c->str_Array = stringtab("Array"); c->str_String = stringtab("String"); c->str_Platform = stringtab("Platform"); c->str_Main = stringtab("Main"); c->str_Env = stringtab("Env"); c->str_add = stringtab("add"); c->str_sub = stringtab("sub"); c->str_mul = stringtab("mul"); c->str_div = stringtab("div"); c->str_mod = stringtab("mod"); c->str_neg = stringtab("neg"); c->str_and = stringtab("op_and"); c->str_or = stringtab("op_or"); c->str_xor = stringtab("op_xor"); c->str_not = stringtab("op_not"); c->str_shl = stringtab("shl"); c->str_shr = stringtab("shr"); c->str_eq = stringtab("eq"); c->str_ne = stringtab("ne"); c->str_lt = stringtab("lt"); c->str_le = stringtab("le"); c->str_ge = stringtab("ge"); c->str_gt = stringtab("gt"); c->str_this = stringtab("this"); c->str_create = stringtab("create"); c->str__create = stringtab("_create"); c->str__init = stringtab("_init"); c->str__final = stringtab("_final"); c->str__event_notify = stringtab("_event_notify"); LLVMTypeRef type; LLVMTypeRef params[5]; LLVMValueRef value; c->void_type = LLVMVoidTypeInContext(c->context); c->ibool = LLVMInt8TypeInContext(c->context); c->i1 = LLVMInt1TypeInContext(c->context); c->i8 = LLVMInt8TypeInContext(c->context); c->i16 = LLVMInt16TypeInContext(c->context); c->i32 = LLVMInt32TypeInContext(c->context); c->i64 = LLVMInt64TypeInContext(c->context); c->i128 = LLVMIntTypeInContext(c->context, 128); c->f32 = LLVMFloatTypeInContext(c->context); c->f64 = LLVMDoubleTypeInContext(c->context); c->intptr = LLVMIntPtrTypeInContext(c->context, c->target_data); // i8* c->void_ptr = LLVMPointerType(c->i8, 0); // forward declare object c->object_type = LLVMStructCreateNamed(c->context, "__object"); c->object_ptr = LLVMPointerType(c->object_type, 0); // padding required in an actor between the descriptor and fields c->actor_pad = LLVMArrayType(c->i8, PONY_ACTOR_PAD_SIZE); // message params[0] = c->i32; // size params[1] = c->i32; // id c->msg_type = LLVMStructCreateNamed(c->context, "__message"); c->msg_ptr = LLVMPointerType(c->msg_type, 0); LLVMStructSetBody(c->msg_type, params, 2, false); // trace // void (*)(i8*, __object*) params[0] = c->void_ptr; params[1] = c->object_ptr; c->trace_type = LLVMFunctionType(c->void_type, params, 2, false); c->trace_fn = LLVMPointerType(c->trace_type, 0); // serialise // void (*)(i8*, __object*, i8*, intptr, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->void_ptr; params[3] = c->intptr; params[4] = c->i32; c->serialise_type = LLVMFunctionType(c->void_type, params, 5, false); c->serialise_fn = LLVMPointerType(c->serialise_type, 0); // dispatch // void (*)(i8*, __object*, $message*) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->msg_ptr; c->dispatch_type = LLVMFunctionType(c->void_type, params, 3, false); c->dispatch_fn = LLVMPointerType(c->dispatch_type, 0); // void (*)(__object*) params[0] = c->object_ptr; c->final_fn = LLVMPointerType( LLVMFunctionType(c->void_type, params, 1, false), 0); // descriptor, opaque version // We need this in order to build our own structure. const char* desc_name = genname_descriptor(NULL); c->descriptor_type = LLVMStructCreateNamed(c->context, desc_name); c->descriptor_ptr = LLVMPointerType(c->descriptor_type, 0); // field descriptor // Also needed to build a descriptor structure. params[0] = c->i32; params[1] = c->descriptor_ptr; c->field_descriptor = LLVMStructTypeInContext(c->context, params, 2, false); // descriptor, filled in gendesc_basetype(c, c->descriptor_type); // define object params[0] = c->descriptor_ptr; LLVMStructSetBody(c->object_type, params, 1, false); // $i8* pony_ctx() type = LLVMFunctionType(c->void_ptr, NULL, 0, false); value = LLVMAddFunction(c->module, "pony_ctx", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMAddFunctionAttr(value, LLVMReadNoneAttribute); // __object* pony_create(i8*, __Desc*) params[0] = c->void_ptr; params[1] = c->descriptor_ptr; type = LLVMFunctionType(c->object_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_create", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, PONY_ACTOR_PAD_SIZE); // void ponyint_destroy(__object*) params[0] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "ponyint_destroy", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_sendv(i8*, __object*, $message*); params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->msg_ptr; type = LLVMFunctionType(c->void_type, params, 3, false); value = LLVMAddFunction(c->module, "pony_sendv", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* pony_alloc(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); #if PONY_LLVM >= 307 LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // i8* pony_alloc_small(i8*, i32) params[0] = c->void_ptr; params[1] = c->i32; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_small", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MIN); // i8* pony_alloc_large(i8*, intptr) params[0] = c->void_ptr; params[1] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_large", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); LLVMSetDereferenceable(value, 0, HEAP_MAX + 1); // i8* pony_realloc(i8*, i8*, intptr) params[0] = c->void_ptr; params[1] = c->void_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_realloc", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); #if PONY_LLVM >= 307 LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // i8* pony_alloc_final(i8*, intptr, c->final_fn) params[0] = c->void_ptr; params[1] = c->intptr; params[2] = c->final_fn; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_alloc_final", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); #if PONY_LLVM >= 307 LLVMSetDereferenceableOrNull(value, 0, HEAP_MIN); #endif // $message* pony_alloc_msg(i32, i32) params[0] = c->i32; params[1] = c->i32; type = LLVMFunctionType(c->msg_ptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_alloc_msg", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); LLVMSetReturnNoAlias(value); // void pony_trace(i8*, i8*) params[0] = c->void_ptr; params[1] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_trace", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* pony_traceobject(i8*, __object*, __Desc*, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->descriptor_ptr; params[3] = c->i32; type = LLVMFunctionType(c->void_ptr, params, 4, false); value = LLVMAddFunction(c->module, "pony_traceknown", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* pony_traceunknown(i8*, __object*, i32) params[0] = c->void_ptr; params[1] = c->object_ptr; params[2] = c->i32; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_traceunknown", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_gc_send(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_gc_send", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_gc_recv(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_gc_recv", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_send_done(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_send_done", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_recv_done(i8*) params[0] = c->void_ptr; type = LLVMFunctionType(c->void_type, params, 1, false); value = LLVMAddFunction(c->module, "pony_recv_done", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_serialise_reserve(i8*, i8*, intptr) params[0] = c->void_ptr; params[1] = c->void_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_type, params, 3, false); value = LLVMAddFunction(c->module, "pony_serialise_reserve", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // intptr pony_serialise_offset(i8*, i8*) params[0] = c->void_ptr; params[1] = c->void_ptr; type = LLVMFunctionType(c->intptr, params, 2, false); value = LLVMAddFunction(c->module, "pony_serialise_offset", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i8* pony_deserialise_offset(i8*, __desc*, intptr) params[0] = c->void_ptr; params[1] = c->descriptor_ptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_deserialise_offset", type); // i8* pony_deserialise_block(i8*, intptr, intptr) params[0] = c->void_ptr; params[1] = c->intptr; params[2] = c->intptr; type = LLVMFunctionType(c->void_ptr, params, 3, false); value = LLVMAddFunction(c->module, "pony_deserialise_block", type); // i32 pony_init(i32, i8**) params[0] = c->i32; params[1] = LLVMPointerType(c->void_ptr, 0); type = LLVMFunctionType(c->i32, params, 2, false); value = LLVMAddFunction(c->module, "pony_init", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_become(i8*, __object*) params[0] = c->void_ptr; params[1] = c->object_ptr; type = LLVMFunctionType(c->void_type, params, 2, false); value = LLVMAddFunction(c->module, "pony_become", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // i32 pony_start(i32) params[0] = c->i32; type = LLVMFunctionType(c->i32, params, 1, false); value = LLVMAddFunction(c->module, "pony_start", type); LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void pony_throw() type = LLVMFunctionType(c->void_type, NULL, 0, false); LLVMAddFunction(c->module, "pony_throw", type); // i32 pony_personality_v0(...) type = LLVMFunctionType(c->i32, NULL, 0, true); c->personality = LLVMAddFunction(c->module, "pony_personality_v0", type); // void llvm.memcpy.*(i8*, i8*, i32/64, i32, i1) params[0] = c->void_ptr; params[1] = c->void_ptr; params[3] = c->i32; params[4] = c->i1; if(target_is_ilp32(c->opt->triple)) { params[2] = c->i32; type = LLVMFunctionType(c->void_type, params, 5, false); value = LLVMAddFunction(c->module, "llvm.memcpy.p0i8.p0i8.i32", type); } else { params[2] = c->i64; type = LLVMFunctionType(c->void_type, params, 5, false); value = LLVMAddFunction(c->module, "llvm.memcpy.p0i8.p0i8.i64", type); } LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); // void llvm.memmove.*(i8*, i8*, i32/64, i32, i1) params[0] = c->void_ptr; params[1] = c->void_ptr; params[3] = c->i32; params[4] = c->i1; if(target_is_ilp32(c->opt->triple)) { params[2] = c->i32; type = LLVMFunctionType(c->void_type, params, 5, false); value = LLVMAddFunction(c->module, "llvm.memmove.p0i8.p0i8.i32", type); } else { params[2] = c->i64; type = LLVMFunctionType(c->void_type, params, 5, false); value = LLVMAddFunction(c->module, "llvm.memmove.p0i8.p0i8.i64", type); } LLVMAddFunctionAttr(value, LLVMNoUnwindAttribute); }