{"action":"created","comment":{"url":"https://api.github.com/repos/halide/Halide/pulls/comments/28984999","id":28984999,"diff_hunk":"@@ -0,0 +1,552 @@\n+#include \"BitWriter_3_2/ReaderWriter_3_2.h\"\n+#include \"CodeGen_RS_Dev.h\"\n+#include \"CodeGen_Internal.h\"\n+#include \"IROperator.h\"\n+#include \"IRPrinter.h\"\n+#include \"Debug.h\"\n+#include \"Target.h\"\n+#include \"LLVM_Headers.h\"\n+#include \"LLVM_Runtime_Linker.h\"\n+\n+namespace Halide {\n+namespace Internal {\n+\n+using std::vector;\n+using std::string;\n+\n+using namespace llvm;\n+\n+// Sniff the contents of a kernel to extracts the bounds of all the\n+// thread indices (so we know how many threads to launch), and the\n+// amount of shared memory to allocate.\n+class ExtractBoundsNames : public IRVisitor {\n+public:\n+    string names[4];\n+\n+    ExtractBoundsNames() {\n+        for (int i = 0; i < 4; i++) {\n+            names[i] = \"\";\n+        }\n+    }\n+\n+private:\n+    using IRVisitor::visit;\n+\n+    void visit(const For *op) {\n+        if (CodeGen_GPU_Dev::is_gpu_var(op->name)) {\n+            internal_assert(is_zero(op->min));\n+        }\n+\n+        if (ends_with(op->name, \".__block_id_x\")) {\n+            names[0] = op->name;\n+        } else if (ends_with(op->name, \".__block_id_y\")) {\n+            names[1] = op->name;\n+        } else if (ends_with(op->name, \".__block_id_z\")) {\n+            names[2] = op->name;\n+        } else if (ends_with(op->name, \".__block_id_w\")) {\n+            names[3] = op->name;\n+        }\n+        op->body.accept(this);\n+    }\n+};\n+\n+CodeGen_RS_Dev::CodeGen_RS_Dev(Target host) : CodeGen_LLVM(host) {\n+    debug(2) << \"Created CodeGen_RS_Dev for target \" << host.to_string().c_str()\n+             << \"\\n\";\n+#if !(WITH_RS)\n+    user_error << \"rs not enabled for this build of Halide.\\n\";\n+#endif\n+    context = new llvm::LLVMContext();\n+}\n+\n+CodeGen_RS_Dev::~CodeGen_RS_Dev() { delete context; }\n+\n+void CodeGen_RS_Dev::add_kernel(Stmt stmt, const std::string &kernel_name,\n+                                const std::vector<GPU_Argument> &args) {\n+    internal_assert(module != NULL);\n+\n+    // Use [kernel_name] as the function name.\n+    debug(2) << \"In CodeGen_RS_Dev::add_kernel name=\" << kernel_name << \"\\n\";\n+\n+    ExtractBoundsNames bounds_names;\n+    stmt.accept(&bounds_names);\n+\n+    // Type Definitions\n+    StructType *StructTy_struct_rs_allocation =\n+        module->getTypeByName(\"struct.rs_allocation\");\n+\n+    // Put the arguments in the symbol table\n+    vector<std::tuple<string, Value *> > globals_sym_names;\n+\n+    // Constant Definitions\n+    ConstantAggregateZero *const_empty_allocation_struct =\n+        ConstantAggregateZero::get(StructTy_struct_rs_allocation);\n+    ConstantInt *const_0 =\n+        ConstantInt::get(*context, APInt(32, StringRef(\"0\"), 10));\n+\n+    NamedMDNode *rs_export_var =\n+        module->getOrInsertNamedMetadata(\"#rs_export_var\");\n+    NamedMDNode *rs_objects_slots =\n+        module->getOrInsertNamedMetadata(\"#rs_object_slots\");\n+\n+    // Now deduce the types of the arguments to our function\n+    vector<llvm::Type *> arg_types_1(args.size());\n+    llvm::Type *argument_type = NULL;\n+    for (size_t i = 0; i < args.size(); i++) {\n+        string arg_name = args[i].name;\n+        debug(1) << \"CodeGen_RS_Dev arg[\" << i << \"].name=\" << arg_name << \"\\n\";\n+        if (!args[i].is_buffer) {\n+            GlobalVariable *gvar =\n+                new GlobalVariable(*module, llvm::Type::getInt32Ty(*context),\n+                                   false,  // isConstant\n+                                   GlobalValue::CommonLinkage,\n+                                   0,  // has initializer, specified below\n+                                   arg_name);\n+            gvar->setAlignment(4);\n+            gvar->setInitializer(const_0);\n+            globals_sym_names.push_back(std::make_tuple(arg_name, gvar));\n+\n+            //\n+            //  \"6\" means \"integer\"-type for Renderscript.\n+            //\n+            rs_export_var->addOperand(MDNode::get(\n+                *context,\n+                vec<LLVMMDNodeArgumentType>(MDString::get(*context, arg_name),\n+                                            MDString::get(*context, \"6\"))));\n+        } else {\n+            argument_type =\n+                VectorType::get(llvm_type_of(UInt(8)), args[i].type.width);\n+\n+            GlobalVariable *gvar =\n+                new GlobalVariable(*module, StructTy_struct_rs_allocation,\n+                                   false,  // isConstant\n+                                   GlobalValue::CommonLinkage,\n+                                   0,  // has initializer, specified below\n+                                   arg_name);\n+            gvar->setAlignment(4);\n+            globals_sym_names.push_back(std::make_tuple(arg_name, gvar));\n+            gvar->setInitializer(const_empty_allocation_struct);\n+\n+            //\n+            //  \"20\" means \"buffer\"-type for Renderscript.\n+            //\n+            rs_export_var->addOperand(MDNode::get(\n+                *context,\n+                vec<LLVMMDNodeArgumentType>(MDString::get(*context, arg_name),\n+                                            MDString::get(*context, \"20\"))));\n+            rs_objects_slots->addOperand(\n+                MDNode::get(*context, vec<LLVMMDNodeArgumentType>(MDString::get(\n+                                          *context, std::to_string(i)))));\n+        }\n+        Halide::Type type = args[i].type;\n+\n+        debug(2) << \"args[\" << i << \"] = {\"\n+                 << \"name=\" << args[i].name\n+                 << \" is_buffer=\" << args[i].is_buffer\n+                 << \" dimensions=\" << args[i].dimensions << \" type.code=\"\n+                 << (type.code == Halide::Type::TypeCode::Int\n+                         ? \"Int\"\n+                         : type.code == Halide::Type::TypeCode::UInt\n+                               ? \"UInt\"\n+                               : type.code == Halide::Type::TypeCode::Float\n+                                     ? \"Float\"\n+                                     : type.code ==\n+                                               Halide::Type::TypeCode::Handle\n+                                           ? \"Handle\"\n+                                           : \"???\") << \";bits=\" << type.bits\n+                 << \";width=\" << type.width << \" llvm_type=\";\n+        debug(2) << \"\\n\";\n+    }\n+\n+    // Make our function with arguments for kernel defined per Renderscript\n+    // convention: (in_type in, i32 x, i32 y)\n+    vector<llvm::Type *> arg_types;\n+    arg_types.push_back(argument_type);  // \"in\"\n+    for (int i = 0; i < 4; i++) {\n+        debug(2) << \"  adding argument type at \" << i << \": \"\n+                 << bounds_names.names[i] << \"\\n\";\n+        if (!bounds_names.names[i].empty()) {\n+            arg_types.push_back(i32);\n+        }\n+    }\n+\n+    FunctionType *func_t = FunctionType::get(void_t, arg_types, false);\n+    function = llvm::Function::Create(func_t, llvm::Function::ExternalLinkage,\n+                                      kernel_name, module);\n+\n+    vector<string> arg_sym_names;\n+\n+    // Add kernel function's parameters to the scope.\n+    llvm::Function::arg_iterator input_arg = function->arg_begin();\n+    input_arg++;  // skip \"in\" buffer\n+    for (int i = 0; i < 4; i++, input_arg++) {\n+        string bounds_name = bounds_names.names[i];\n+        if (!bounds_name.empty()) {\n+            input_arg->setName(bounds_name);\n+            sym_push(bounds_name, input_arg);\n+            debug(2) << \"  adding kernel function parameter \" << bounds_name\n+                     << \" with type \";\n+            if (debug::debug_level >= 2) {\n+                input_arg->getType()->dump();\n+            }\n+            arg_sym_names.push_back(bounds_name);\n+        }\n+    }\n+\n+    // Mark the buffer args as no alias.\n+    for (size_t i = 0; i < args.size(); i++) {\n+        if (args[i].is_buffer) {\n+            function->setDoesNotAlias(i + 1);\n+        }\n+    }\n+\n+    // Make the initial basic block.\n+    entry_block = BasicBlock::Create(*context, \"entry\", function);\n+    builder->SetInsertPoint(entry_block);\n+\n+    // We won't end the entry block yet, because we'll want to add\n+    // some allocas to it later if there are local allocations. Start\n+    // a new block to put all the code.\n+    BasicBlock *body_block = BasicBlock::Create(*context, \"body\", function);\n+    builder->SetInsertPoint(body_block);\n+\n+    // Global symbols are pointers to the values, so\n+    // we need to dereference and load actual values.\n+    for (auto name_and_value : globals_sym_names) {\n+        string name = std::get<0>(name_and_value);\n+        debug(2) << \"Pushing global symbol \" << name << \" into sym table\\n\";\n+\n+        // Buffer symbols are bit-casted to rs_allocation*.\n+        Value *value = std::get<1>(name_and_value);\n+        llvm::PointerType *p = llvm::cast<llvm::PointerType>(value->getType());\n+        if (p != NULL) {\n+            if (p->getElementType() == StructTy_struct_rs_allocation) {\n+                value = builder->CreateBitCast(\n+                    value,\n+                    PointerType::get(\n+                        ArrayType::get(IntegerType::get(*context, 32), 1), 0));\n+            }\n+        }\n+\n+        value = builder->CreateAlignedLoad(value, 4 /*alignment*/);\n+        sym_push(name, value);\n+        arg_sym_names.push_back(name);\n+    }\n+\n+    debug(1) << \"Generating llvm bitcode for kernel...\\n\";\n+    // Ok, we have a module, function, context, and a builder\n+    // pointing at a brand new basic block. We're good to go.\n+    stmt.accept(this);\n+\n+    builder->CreateRetVoid();\n+    // Make the entry block point to the body block\n+    builder->SetInsertPoint(entry_block);\n+    builder->CreateBr(body_block);\n+\n+    // Add Renderscript standard set of metadata.\n+    NamedMDNode *rs_export_foreach_name =\n+        module->getOrInsertNamedMetadata(\"#rs_export_foreach_name\");\n+    rs_export_foreach_name->addOperand(MDNode::get(\n+        *context,\n+        vec<LLVMMDNodeArgumentType>(MDString::get(*context, \"root\"))));\n+    rs_export_foreach_name->addOperand(MDNode::get(\n+        *context,\n+        vec<LLVMMDNodeArgumentType>(MDString::get(*context, kernel_name))));\n+\n+    const char* kernel_signature = \"57\";\n+    NamedMDNode *rs_export_foreach =\n+        module->getOrInsertNamedMetadata(\"#rs_export_foreach\");\n+    rs_export_foreach->addOperand(MDNode::get(\n+        *context, vec<LLVMMDNodeArgumentType>(MDString::get(*context, \"0\"))));\n+    rs_export_foreach->addOperand(MDNode::get(\n+        *context, vec<LLVMMDNodeArgumentType>(MDString::get(\n+                      *context, kernel_signature))));\n+\n+    // Now verify the function is ok\n+    verifyFunction(*function);\n+\n+    // Finally, verify the module is ok\n+    verifyModule(*module);\n+\n+    debug(2) << \"Done generating llvm bitcode for RS\\n\";\n+\n+    // Clear the symbol table\n+    for (size_t i = 0; i < arg_sym_names.size(); i++) {\n+        sym_pop(arg_sym_names[i]);\n+    }\n+}\n+\n+void CodeGen_RS_Dev::init_module() {\n+    debug(2) << \"CodeGen_RS_Dev::init_module\\n\";\n+    init_context();\n+#ifdef WITH_RS\n+    delete module;\n+    module = get_initial_module_for_rs_device(target, context);\n+#endif\n+}\n+\n+llvm::Triple CodeGen_LLVM::get_target_triple() const {\n+    return Triple(Triple::normalize(\"armv7-none-linux-gnueabi\"));\n+}\n+\n+llvm::DataLayout CodeGen_RS_Dev::get_data_layout() const {\n+    return llvm::DataLayout(\"e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64\");\n+}\n+\n+//\n+// Loops become kernels. There should be no explicit loops in\n+// generated RenderScript code.\n+//\n+void CodeGen_RS_Dev::visit(const For *loop) {\n+    debug(2) << \"RS: Visiting for loop, loop->name is \" << loop->name\n+             << \" is_gpu_var? \" << is_gpu_var(loop->name) << \"\\n\";\n+    if (is_gpu_var(loop->name)) {\n+        // Whether it's thread-parallelization loop or loop over\n+        // coordinate variables, collapse them going straight to the body\n+        // because Renderscript takes care of setting up the loops.\n+        // We just need to produce a kernel code.\n+        loop->body.accept(this);\n+    } else {\n+        user_assert(loop->for_type != ForType::Parallel)\n+            << \"Cannot use loops inside RS kernel\\n\";\n+        CodeGen_LLVM::visit(loop);\n+    }\n+}\n+\n+void CodeGen_RS_Dev::visit(const Allocate *alloc) {\n+    debug(2) << \"RS: Allocate \" << alloc->name << \" on device\\n\";\n+    codegen(alloc->body);\n+}\n+\n+void CodeGen_RS_Dev::visit(const Free *f) {\n+    // TODO(aam): Implement this.\n+    debug(2) << \"RS: Free on device\\n\";\n+}\n+\n+llvm::Function *CodeGen_RS_Dev::fetch_GetElement_func(int width) {\n+    std::string func_name = width == 1\n+                                ? \"_Z20rsGetElementAt_uchar13rs_allocationjjj\"","path":"src/CodeGen_RS_Dev.cpp","position":360,"original_position":328,"commit_id":"298e0a44a023a72d3630c722785c3dd845754a78","original_commit_id":"ae283cf97060754f7368dd246551d5d04d78d8c7","user":{"login":"steven-johnson","id":328955,"avatar_url":"https://avatars.githubusercontent.com/u/328955?v=3","gravatar_id":"","url":"https://api.github.com/users/steven-johnson","html_url":"https://github.com/steven-johnson","followers_url":"https://api.github.com/users/steven-johnson/followers","following_url":"https://api.github.com/users/steven-johnson/following{/other_user}","gists_url":"https://api.github.com/users/steven-johnson/gists{/gist_id}","starred_url":"https://api.github.com/users/steven-johnson/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/steven-johnson/subscriptions","organizations_url":"https://api.github.com/users/steven-johnson/orgs","repos_url":"https://api.github.com/users/steven-johnson/repos","events_url":"https://api.github.com/users/steven-johnson/events{/privacy}","received_events_url":"https://api.github.com/users/steven-johnson/received_events","type":"User","site_admin":false},"body":"These are disturbingly-specific mangled names; they certainly deserve some commenting about where they are coming from. How likely is this to break in the future?","created_at":"2015-04-23T17:39:24Z","updated_at":"2015-04-23T17:39:24Z","html_url":"https://github.com/halide/Halide/pull/761#discussion_r28984999","pull_request_url":"https://api.github.com/repos/halide/Halide/pulls/761","_links":{"self":{"href":"https://api.github.com/repos/halide/Halide/pulls/comments/28984999"},"html":{"href":"https://github.com/halide/Halide/pull/761#discussion_r28984999"},"pull_request":{"href":"https://api.github.com/repos/halide/Halide/pulls/761"}}},"pull_request":{"url":"https://api.github.com/repos/halide/Halide/pulls/761","id":33908212,"html_url":"https://github.com/halide/Halide/pull/761","diff_url":"https://github.com/halide/Halide/pull/761.diff","patch_url":"https://github.com/halide/Halide/pull/761.patch","issue_url":"https://api.github.com/repos/halide/Halide/issues/761","number":761,"state":"open","locked":false,"title":"Renderscript Codegen and runtime.","user":{"login":"aam","id":381137,"avatar_url":"https://avatars.githubusercontent.com/u/381137?v=3","gravatar_id":"","url":"https://api.github.com/users/aam","html_url":"https://github.com/aam","followers_url":"https://api.github.com/users/aam/followers","following_url":"https://api.github.com/users/aam/following{/other_user}","gists_url":"https://api.github.com/users/aam/gists{/gist_id}","starred_url":"https://api.github.com/users/aam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aam/subscriptions","organizations_url":"https://api.github.com/users/aam/orgs","repos_url":"https://api.github.com/users/aam/repos","events_url":"https://api.github.com/users/aam/events{/privacy}","received_events_url":"https://api.github.com/users/aam/received_events","type":"User","site_admin":false},"body":"This PR adds Renderscript Codegen, RS-compatible BitWriter, runtime support, some simple IR-validation JIT tests and AOT tests that run on the device.\r\n\r\nApologize for the PR size, I initially thought about splitting this into two pull requests: one for Codegen, another for BitWriter, but that looked awkward as you won't be able to do much with just RS Codegen because you need BitWriter to actually run code on the device.\r\n\r\nRenderScript BitWriter source code was taken from Renderscript open-source code repository.\r\nRenderScript runtime API(src/runtime/mini_rs.h) corresponds to Lollipop release. Some 3-dimension API calls are only part of relatively modern RenderScript API(device_api=23).\r\n\r\nCurrently(and this is just the beginning) two image formats/schedule types are supported:\r\n* 4-channel 3-dimension interleaved image, which maps to 2-dimension 4-byte wide RGBA Renderscript image format. Schedule for Funcs operating on interleaved image have to be vectorized over c-coordinate, so that generated Renderscript API-calls GetElementAt_uchar4/SetElementAt_uchar4 are applicable.\r\n* 3-dimension planar image, which maps to 3-dimension 1-byte Renderscript image format. Schedule for Funcs operating on planar image should not be vectorized, so that 1-byte wide GetElementAt_uchar/SetElementAt_uchar are applicable.\r\n\r\nThank you.","created_at":"2015-04-22T22:32:42Z","updated_at":"2015-04-23T17:39:24Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a730d04b2ac743c0164d00a4249f61e869d0b66a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/halide/Halide/pulls/761/commits","review_comments_url":"https://api.github.com/repos/halide/Halide/pulls/761/comments","review_comment_url":"https://api.github.com/repos/halide/Halide/pulls/comments{/number}","comments_url":"https://api.github.com/repos/halide/Halide/issues/761/comments","statuses_url":"https://api.github.com/repos/halide/Halide/statuses/298e0a44a023a72d3630c722785c3dd845754a78","head":{"label":"halide:rs","ref":"rs","sha":"298e0a44a023a72d3630c722785c3dd845754a78","user":{"login":"halide","id":1548551,"avatar_url":"https://avatars.githubusercontent.com/u/1548551?v=3","gravatar_id":"","url":"https://api.github.com/users/halide","html_url":"https://github.com/halide","followers_url":"https://api.github.com/users/halide/followers","following_url":"https://api.github.com/users/halide/following{/other_user}","gists_url":"https://api.github.com/users/halide/gists{/gist_id}","starred_url":"https://api.github.com/users/halide/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/halide/subscriptions","organizations_url":"https://api.github.com/users/halide/orgs","repos_url":"https://api.github.com/users/halide/repos","events_url":"https://api.github.com/users/halide/events{/privacy}","received_events_url":"https://api.github.com/users/halide/received_events","type":"Organization","site_admin":false},"repo":{"id":5241312,"name":"Halide","full_name":"halide/Halide","owner":{"login":"halide","id":1548551,"avatar_url":"https://avatars.githubusercontent.com/u/1548551?v=3","gravatar_id":"","url":"https://api.github.com/users/halide","html_url":"https://github.com/halide","followers_url":"https://api.github.com/users/halide/followers","following_url":"https://api.github.com/users/halide/following{/other_user}","gists_url":"https://api.github.com/users/halide/gists{/gist_id}","starred_url":"https://api.github.com/users/halide/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/halide/subscriptions","organizations_url":"https://api.github.com/users/halide/orgs","repos_url":"https://api.github.com/users/halide/repos","events_url":"https://api.github.com/users/halide/events{/privacy}","received_events_url":"https://api.github.com/users/halide/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/halide/Halide","description":"a language for image processing and computational photography","fork":false,"url":"https://api.github.com/repos/halide/Halide","forks_url":"https://api.github.com/repos/halide/Halide/forks","keys_url":"https://api.github.com/repos/halide/Halide/keys{/key_id}","collaborators_url":"https://api.github.com/repos/halide/Halide/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/halide/Halide/teams","hooks_url":"https://api.github.com/repos/halide/Halide/hooks","issue_events_url":"https://api.github.com/repos/halide/Halide/issues/events{/number}","events_url":"https://api.github.com/repos/halide/Halide/events","assignees_url":"https://api.github.com/repos/halide/Halide/assignees{/user}","branches_url":"https://api.github.com/repos/halide/Halide/branches{/branch}","tags_url":"https://api.github.com/repos/halide/Halide/tags","blobs_url":"https://api.github.com/repos/halide/Halide/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/halide/Halide/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/halide/Halide/git/refs{/sha}","trees_url":"https://api.github.com/repos/halide/Halide/git/trees{/sha}","statuses_url":"https://api.github.com/repos/halide/Halide/statuses/{sha}","languages_url":"https://api.github.com/repos/halide/Halide/languages","stargazers_url":"https://api.github.com/repos/halide/Halide/stargazers","contributors_url":"https://api.github.com/repos/halide/Halide/contributors","subscribers_url":"https://api.github.com/repos/halide/Halide/subscribers","subscription_url":"https://api.github.com/repos/halide/Halide/subscription","commits_url":"https://api.github.com/repos/halide/Halide/commits{/sha}","git_commits_url":"https://api.github.com/repos/halide/Halide/git/commits{/sha}","comments_url":"https://api.github.com/repos/halide/Halide/comments{/number}","issue_comment_url":"https://api.github.com/repos/halide/Halide/issues/comments{/number}","contents_url":"https://api.github.com/repos/halide/Halide/contents/{+path}","compare_url":"https://api.github.com/repos/halide/Halide/compare/{base}...{head}","merges_url":"https://api.github.com/repos/halide/Halide/merges","archive_url":"https://api.github.com/repos/halide/Halide/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/halide/Halide/downloads","issues_url":"https://api.github.com/repos/halide/Halide/issues{/number}","pulls_url":"https://api.github.com/repos/halide/Halide/pulls{/number}","milestones_url":"https://api.github.com/repos/halide/Halide/milestones{/number}","notifications_url":"https://api.github.com/repos/halide/Halide/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/halide/Halide/labels{/name}","releases_url":"https://api.github.com/repos/halide/Halide/releases{/id}","created_at":"2012-07-31T04:05:25Z","updated_at":"2015-04-23T16:49:22Z","pushed_at":"2015-04-23T16:49:22Z","git_url":"git://github.com/halide/Halide.git","ssh_url":"git@github.com:halide/Halide.git","clone_url":"https://github.com/halide/Halide.git","svn_url":"https://github.com/halide/Halide","homepage":"http://halide-lang.org","size":126977,"stargazers_count":941,"watchers_count":941,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":170,"mirror_url":null,"open_issues_count":96,"forks":170,"open_issues":96,"watchers":941,"default_branch":"master"}},"base":{"label":"halide:master","ref":"master","sha":"f1011af2c73546ab966b680e88578addf1263e01","user":{"login":"halide","id":1548551,"avatar_url":"https://avatars.githubusercontent.com/u/1548551?v=3","gravatar_id":"","url":"https://api.github.com/users/halide","html_url":"https://github.com/halide","followers_url":"https://api.github.com/users/halide/followers","following_url":"https://api.github.com/users/halide/following{/other_user}","gists_url":"https://api.github.com/users/halide/gists{/gist_id}","starred_url":"https://api.github.com/users/halide/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/halide/subscriptions","organizations_url":"https://api.github.com/users/halide/orgs","repos_url":"https://api.github.com/users/halide/repos","events_url":"https://api.github.com/users/halide/events{/privacy}","received_events_url":"https://api.github.com/users/halide/received_events","type":"Organization","site_admin":false},"repo":{"id":5241312,"name":"Halide","full_name":"halide/Halide","owner":{"login":"halide","id":1548551,"avatar_url":"https://avatars.githubusercontent.com/u/1548551?v=3","gravatar_id":"","url":"https://api.github.com/users/halide","html_url":"https://github.com/halide","followers_url":"https://api.github.com/users/halide/followers","following_url":"https://api.github.com/users/halide/following{/other_user}","gists_url":"https://api.github.com/users/halide/gists{/gist_id}","starred_url":"https://api.github.com/users/halide/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/halide/subscriptions","organizations_url":"https://api.github.com/users/halide/orgs","repos_url":"https://api.github.com/users/halide/repos","events_url":"https://api.github.com/users/halide/events{/privacy}","received_events_url":"https://api.github.com/users/halide/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/halide/Halide","description":"a language for image processing and computational photography","fork":false,"url":"https://api.github.com/repos/halide/Halide","forks_url":"https://api.github.com/repos/halide/Halide/forks","keys_url":"https://api.github.com/repos/halide/Halide/keys{/key_id}","collaborators_url":"https://api.github.com/repos/halide/Halide/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/halide/Halide/teams","hooks_url":"https://api.github.com/repos/halide/Halide/hooks","issue_events_url":"https://api.github.com/repos/halide/Halide/issues/events{/number}","events_url":"https://api.github.com/repos/halide/Halide/events","assignees_url":"https://api.github.com/repos/halide/Halide/assignees{/user}","branches_url":"https://api.github.com/repos/halide/Halide/branches{/branch}","tags_url":"https://api.github.com/repos/halide/Halide/tags","blobs_url":"https://api.github.com/repos/halide/Halide/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/halide/Halide/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/halide/Halide/git/refs{/sha}","trees_url":"https://api.github.com/repos/halide/Halide/git/trees{/sha}","statuses_url":"https://api.github.com/repos/halide/Halide/statuses/{sha}","languages_url":"https://api.github.com/repos/halide/Halide/languages","stargazers_url":"https://api.github.com/repos/halide/Halide/stargazers","contributors_url":"https://api.github.com/repos/halide/Halide/contributors","subscribers_url":"https://api.github.com/repos/halide/Halide/subscribers","subscription_url":"https://api.github.com/repos/halide/Halide/subscription","commits_url":"https://api.github.com/repos/halide/Halide/commits{/sha}","git_commits_url":"https://api.github.com/repos/halide/Halide/git/commits{/sha}","comments_url":"https://api.github.com/repos/halide/Halide/comments{/number}","issue_comment_url":"https://api.github.com/repos/halide/Halide/issues/comments{/number}","contents_url":"https://api.github.com/repos/halide/Halide/contents/{+path}","compare_url":"https://api.github.com/repos/halide/Halide/compare/{base}...{head}","merges_url":"https://api.github.com/repos/halide/Halide/merges","archive_url":"https://api.github.com/repos/halide/Halide/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/halide/Halide/downloads","issues_url":"https://api.github.com/repos/halide/Halide/issues{/number}","pulls_url":"https://api.github.com/repos/halide/Halide/pulls{/number}","milestones_url":"https://api.github.com/repos/halide/Halide/milestones{/number}","notifications_url":"https://api.github.com/repos/halide/Halide/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/halide/Halide/labels{/name}","releases_url":"https://api.github.com/repos/halide/Halide/releases{/id}","created_at":"2012-07-31T04:05:25Z","updated_at":"2015-04-23T16:49:22Z","pushed_at":"2015-04-23T16:49:22Z","git_url":"git://github.com/halide/Halide.git","ssh_url":"git@github.com:halide/Halide.git","clone_url":"https://github.com/halide/Halide.git","svn_url":"https://github.com/halide/Halide","homepage":"http://halide-lang.org","size":126977,"stargazers_count":941,"watchers_count":941,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":170,"mirror_url":null,"open_issues_count":96,"forks":170,"open_issues":96,"watchers":941,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/halide/Halide/pulls/761"},"html":{"href":"https://github.com/halide/Halide/pull/761"},"issue":{"href":"https://api.github.com/repos/halide/Halide/issues/761"},"comments":{"href":"https://api.github.com/repos/halide/Halide/issues/761/comments"},"review_comments":{"href":"https://api.github.com/repos/halide/Halide/pulls/761/comments"},"review_comment":{"href":"https://api.github.com/repos/halide/Halide/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/halide/Halide/pulls/761/commits"},"statuses":{"href":"https://api.github.com/repos/halide/Halide/statuses/298e0a44a023a72d3630c722785c3dd845754a78"}}}}