From 9654d79ecedbce3013a95e5d99e16a2376a09813 Mon Sep 17 00:00:00 2001 From: Cedric Mercier Date: Mon, 19 Oct 2026 14:07:36 +0200 Subject: [PATCH] bintools: classify every eightbyte of small objects on System V x86_64 ClassifyObject() only looked at fields two by two and never classified an eightbyte holding a single field, so Vector { x, y, z } was SSE + None: the z returned in xmm1 was never stored (SDKCall returning a Vector by value got z = 0). Merge the class of every field into the eightbyte it is laid out in instead. --- extensions/bintools/jit_call_x64.cpp | 35 +++++++++++----------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/extensions/bintools/jit_call_x64.cpp b/extensions/bintools/jit_call_x64.cpp index d404498015..c796305129 100644 --- a/extensions/bintools/jit_call_x64.cpp +++ b/extensions/bintools/jit_call_x64.cpp @@ -685,31 +685,22 @@ inline int ClassifyObject(const PassInfo *info, ObjectClass *classes) { numWords = int((info->size + 7) / 8); - unsigned int j = 0; + // Each eightbyte gets the merged class of every field laid out in it (fields are + // naturally aligned, in declaration order). E.g. Vector { float x, y, z; } is + // SSE (x, y) + SSE (z), returned in xmm0 + xmm1. for (int i = 0; i < numWords; i++) - { classes[i] = ObjectClass::None; - size_t sizeSoFar = 0; - for (int k = 0; j < numFields; j++, k++) - { - size_t sz = TypeSize(fields[j]); - if (sizeSoFar + sz > 8) - break; - else - sizeSoFar += sz; - if (k == 0 && sizeSoFar == 8) { - classes[i] = ClassifyType(fields[j++]); - break; - } else if (j + 1 >= numFields) { - break; - } - - const ObjectField &field1 = fields[j]; - const ObjectField &field2 = fields[j + 1]; - - classes[i] = MergeClasses(ClassifyType(field1), ClassifyType(field2)); - } + size_t fieldOffset = 0; + for (unsigned int j = 0; j < numFields; j++) + { + size_t sz = TypeSize(fields[j]); + fieldOffset = (fieldOffset + sz - 1) & ~(sz - 1); + size_t word = fieldOffset / 8; + if (word >= (size_t)numWords) + break; + classes[word] = MergeClasses(classes[word], ClassifyType(fields[j])); + fieldOffset += sz; } }