)]}'
{
  "commit": "421d296893ed173846c0aceaee67cdafa67da07b",
  "tree": "fe485cc5189d60687fc4bacd4bf05aa75e8fe42e",
  "parents": [
    "112fb2f79d7983be203957cad6b148865182ed47"
  ],
  "author": {
    "name": "adams381",
    "email": "adams@nvidia.com",
    "time": "Thu Jun 11 17:39:53 2026 -0500"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Thu Jun 11 22:39:53 2026 +0000"
  },
  "message": "[CIR] Lower sret returns in CallConvLowering (#201716)\n\nFunctions that return an aggregate by value classify their return as\nArgKind::Indirect, but CallConvLowering reached an errorNYI for that\ncase, so the whole CallConv pass refused to lower any struct-returning\nfunction.\n\nrewriteFunctionDefinition now recognizes an Indirect return: the wire\nreturn type becomes void, a hidden sret pointer is prepended as block\nargument 0, and every cir.return is routed through that pointer.  Rather\nthan storing the loaded return value through the sret pointer (a\nbyte-copy that breaks non-trivially-copyable types -- libstdc++\u0027s SSO\nstd::string keeps a _M_p pointer into its own _M_local_buf, so a\nbyte-copy leaves the destination aliasing the source\u0027s dying stack\nstorage), insertSRetStores rewires the __retval alloca to the sret\npointer so construction flows directly into the caller\u0027s slot, matching\nclassic CodeGen\u0027s \"construct into %agg.result\" pattern. CIRGen emits one\ncir.load __retval / cir.return pair per return statement, all reading\nthe\nsingle __retval alloca, so the alloca is rewired once and every return\nis\ncollapsed to a bare return. That cir.return (cir.load \u003calloca\u003e) shape is\ntreated as an invariant and asserted with cast\u003c\u003e rather than guarded by\na\nfallback.  The sret parameter carries sret(T) align A writable\ndead_on_unwind, plus noalias on definitions.\n\nrewriteCallSite prepends the return slot, makes the call return void,\nand reads the result back.  When the result has a single store-into-dest\nuse whose destination dominates the call, it reuses that destination as\nthe sret slot and drops the redundant store, so the callee writes\nstraight into the local with no copy; otherwise it allocates a fresh\nslot\nand loads the value out.  The slot\u0027s\nper-argument attributes go through the same updateArgAttrs path as the\nnon-sret case, so sret composes with Extend (signext/zeroext) and Ignore\narguments.\n\nbyval indirect arguments and Expand are still errorNYI.\n\nCo-authored-by: Cursor \u003ccursoragent@cursor.com\u003e\n\n---------\n\nCo-authored-by: Cursor \u003ccursoragent@cursor.com\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "a2615394f223a1e614091b74c9aab75f15dcccb1",
      "old_mode": 33188,
      "old_path": "clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp",
      "new_id": "b252ed188c40839e55b06164c9be7bcf53aa6133",
      "new_mode": 33188,
      "new_path": "clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.cpp"
    },
    {
      "type": "modify",
      "old_id": "038e81026784c9248a1a477295b44e140c727ee2",
      "old_mode": 33188,
      "old_path": "clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.h",
      "new_id": "3977628b56516b3e951bcdb343ea50099c5beef8",
      "new_mode": 33188,
      "new_path": "clang/lib/CIR/Dialect/Transforms/TargetLowering/CIRABIRewriteContext.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "98b77e51ba3da65fe66dfa52f7141733bc377346",
      "new_mode": 33188,
      "new_path": "clang/test/CIR/Transforms/abi-lowering/indirect-return-sret.cir"
    }
  ]
}
