void WinEHStatePass::linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler) { // Emit the .safeseh directive for this function. Handler->addFnAttr("safeseh"); Type *LinkTy = getEHLinkRegistrationType(); // Handler = Handler Value *HandlerI8 = Builder.CreateBitCast(Handler, Builder.getInt8PtrTy()); Builder.CreateStore(HandlerI8, Builder.CreateStructGEP(LinkTy, Link, 1)); // Next = [fs:00] Constant *FSZero = Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257)); Value *Next = Builder.CreateLoad(FSZero); Builder.CreateStore(Next, Builder.CreateStructGEP(LinkTy, Link, 0)); // [fs:00] = Link Builder.CreateStore(Link, FSZero); }
int main(int argc, char **argv) { InitializeNativeTarget(); LLVMContext &Context = getGlobalContext(); Module *m = new Module("test", Context); Type *intTy = Type::getInt64Ty(Context); StructType* structTy = StructType::create(Context, "struct.list"); std::vector<Type*> fields; fields.push_back(intTy); fields.push_back(PointerType::get(structTy, 0)); if (structTy->isOpaque()) { structTy->setBody(fields, false); } /* * int f1(struct x *p) { return p->next->l1; } */ std::vector<Type*> args_type; args_type.push_back(PointerType::get(structTy, 0)); FunctionType *fnTy = FunctionType::get(intTy, args_type, false); Function *func = Function::Create(fnTy, GlobalValue::ExternalLinkage, "f1", m); Value *v = func->arg_begin(); BasicBlock *bb = BasicBlock::Create(Context, "EntryBlock", func); IRBuilder<> *builder = new IRBuilder<>(bb); v = builder->CreateStructGEP(v, 1); v = builder->CreateLoad(v, "load0"); v = builder->CreateStructGEP(v, 0); v = builder->CreateLoad(v, "load1"); builder->CreateRet(v); (*m).dump(); { ExecutionEngine *ee = EngineBuilder(m). setEngineKind(EngineKind::JIT).create(); void *f = ee->getPointerToFunction(func); typedef int (*func_t) (struct x *); struct x o = {10, NULL}, v = {}; v.next = &o; std::cout << ((func_t)f)(&v) << std::endl; } return 0; }
void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) { // Clone Link into the current BB for better address mode folding. if (auto *GEP = dyn_cast<GetElementPtrInst>(Link)) { GEP = cast<GetElementPtrInst>(GEP->clone()); Builder.Insert(GEP); Link = GEP; } Type *LinkTy = getEHLinkRegistrationType(); // [fs:00] = Link->Next Value *Next = Builder.CreateLoad(Builder.CreateStructGEP(LinkTy, Link, 0)); Constant *FSZero = Constant::getNullValue(LinkTy->getPointerTo()->getPointerTo(257)); Builder.CreateStore(Next, FSZero); }
codegen_value ast::distribution::codegen(Module *module, IRBuilder<> &builder) { typecheck_vector param_types = get_parameter_types(); return errors::codegen_call<typecheck_vector, codegen_value>(param_types, [this, module, &builder] (vector<type_spec> ¶m_types) -> codegen_value { Type *param_struct_ty = getParameterType(param_types); boost::function<void (Value*, Module*, IRBuilder<>&)> loader = [this, ¶m_types] (Value *ctx, Module *module, IRBuilder<> &builder) -> void { //create variable names pointing to each member of the param struct for (unsigned int param_idx = 0; param_idx < params.size(); ++param_idx) { const distribution_parameter ¶m = params[param_idx]; Value *param_ptr = builder.CreateStructGEP(ctx, param_idx); variable_symbol_table::entry_type entry(param_ptr, param_types[param_idx], false); variables().set(param.name, entry); } }; //enter new scope push_distribution_context(name, param_struct_ty->getPointerTo(), loader); //evaluate all internal declarations codegen_vector content_eval; for (auto it = internal_decl.begin(); it != internal_decl.end(); it++) { codegen_value eval = (*it)->codegen(module, builder); content_eval = errors::codegen_vector_push_back(content_eval, eval); } //find the 'evaluate' function (error if not declared) codegen_value eval_func = check_for_evaluate(); //find the 'pdf' function codegen_value pdf_func = check_for_pdf(); //find the 'emission' function codegen_value emit_func = check_for_emission(); //find the 'sample' function codegen_value sample_func = check_for_sample(); //leave new scope pop_distribution_context(module, builder); vector<function_argument> ctor_arguments; for (unsigned int param_idx = 0; param_idx < params.size(); ++param_idx) { function_argument arg{params[param_idx].name, param_types[param_idx], false}; ctor_arguments.push_back(arg); } string ctor_name = function_generate_name(name, function_scope_name(), ctor_arguments); //define an externally visible function to evaluate this distribution (vectors must be passed by pointer, not value). //then define an externally visible function to instantiate this distribution boost::function<codegen_value (Value *&, Value *&, Value *&, Value *&)> check_funcs = [this, &ctor_name, ¶m_types, param_struct_ty, module, &builder] (Value *&eval_ptr, Value *&sample_ptr, Value *&pdf_ptr, Value *&emit_ptr) -> codegen_value { Value *eval_f = create_evaluator(cast_or_null<Function>(eval_ptr), param_struct_ty, module, builder); Value *sample_f = create_sampler(cast_or_null<Function>(sample_ptr), param_struct_ty, module, builder); Value *pdf_f = create_pdf(cast_or_null<Function>(pdf_ptr), param_struct_ty, module, builder); Value *emit_f = create_emission(cast_or_null<Function>(emit_ptr), param_struct_ty, module, builder); Function *dtor_f = createDestructor(module, builder, param_struct_ty, param_types); return createConstructor(module, builder, ctor_name, param_struct_ty, param_types, eval_f, sample_f, pdf_f, emit_f, dtor_f); }; codegen_value ctor_val = errors::codegen_apply(check_funcs, eval_func, sample_func, pdf_func, emit_func); //final error checking, add the constructor to the function symtab boost::function<codegen_value (vector<Value*> &, Value*&, Value*&)> op = [this, &ctor_arguments, ¶m_types, module, &builder] (vector<Value*> &, Value *&, Value *&ctor_ptr) -> codegen_value { Function *ctor = cast<Function>(ctor_ptr); function_entry entry = function_entry::make_entry(name, function_scope_name(), state->types["dfunc"], ctor_arguments); entry.func = ctor; function_table().set(entry.to_key(), entry); //also export the constructor exports::function_export exp; exp.name = entry.name; exp.full_name = entry.full_name; exp.return_type = entry.return_type; exp.arguments = entry.arguments; state->exports.add_function(exp); return ctor; }; return errors::codegen_apply(op, content_eval, eval_func, ctor_val); }); }
codegen_value ast::distribution::createConstructor(Module *module, IRBuilder<> &builder, const string &ctor_name, Type *parameter_type, const vector<type_spec> ¶m_type_list, Value *eval, Value *sample, Value *pdf, Value *emit, Function *dtor) { //create function accepting parameters as arguments vector<Type*> arg_types; for (auto it = param_type_list.begin(); it != param_type_list.end(); ++it) arg_types.push_back((*it)->llvm_type()); FunctionType *ft = FunctionType::get(state->types["dfunc"]->llvm_type(), arg_types, false); Function *f = Function::Create(ft, Function::ExternalLinkage, ctor_name, module); BasicBlock *bb = BasicBlock::Create(getGlobalContext(), "func_entry", f); builder.SetInsertPoint(bb); //setup arguments for the alloc call Value *gd_scene = module->getNamedGlobal(".__gd_scene"); assert(gd_scene != NULL); Value *scene_ptr = builder.CreateLoad(gd_scene); //compute the shader flags codegen_value flag_val = codegen_all_flags(module, builder); return errors::codegen_call(flag_val, [&] (Value *&flag_bitmask) -> codegen_value { //get memory for a new distribution object Value *dfunc_ptr = state->types["dfunc"]->allocate(module, builder); //initialize the object and dynamically allocate parameter memory (calling a builtin function) Type* int_ptr_ty = Type::getInt32Ty(getGlobalContext())->getPointerTo(); vector<Type*> alloc_arg_types({state->types["scene_ptr"]->llvm_type(), Type::getInt32Ty(getGlobalContext()), state->types["shader_flag"]->llvm_type(), int_ptr_ty, int_ptr_ty, int_ptr_ty, int_ptr_ty, dtor->getType(), dfunc_ptr->getType()}); FunctionType *alloc_type = FunctionType::get(Type::getInt32PtrTy(getGlobalContext()), alloc_arg_types, false); Function *alloc_func = GetExternalFunction(module, "gd_builtin_alloc_dfunc", alloc_type); int param_data_size = DataLayout(module).getTypeAllocSize(parameter_type); Constant *param_size_arg = ConstantInt::get(getGlobalContext(), APInt(8*sizeof(int), param_data_size)); vector<Value*> alloc_args({scene_ptr, param_size_arg, flag_bitmask, builder.CreatePointerCast(eval, int_ptr_ty), builder.CreatePointerCast(sample, int_ptr_ty), builder.CreatePointerCast(pdf, int_ptr_ty), builder.CreatePointerCast(emit, int_ptr_ty), dtor, dfunc_ptr}); Value *param_ptr = builder.CreatePointerCast(builder.CreateCall(alloc_func, alloc_args), parameter_type->getPointerTo(), "dfunc_param_ptr"); //set each parameter auto arg_it = f->arg_begin(); unsigned int field_idx = 0; for (auto it = param_type_list.begin(); it != param_type_list.end(); ++it, ++arg_it, ++field_idx) { Value *param_copy = (*it)->copy(arg_it, module, builder); (*it)->store(param_copy, builder.CreateStructGEP(param_ptr, field_idx), module, builder); } //return the object Value *rt_val = builder.CreateLoad(dfunc_ptr, "dist_ref"); builder.CreateRet(rt_val); return f; }); }