diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-22 13:46:40 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-22 13:46:40 +0000 |
| commit | e3cc6c585a15fe4478dd2312bf5d390896729a31 (patch) | |
| tree | 1fbfbecd963d1d566c5d93d9c9cb3038b10fc89a /lib/CodeGen | |
| parent | 3a6eb921b50e191468d29c233718657f9f85d68e (diff) | |
feat(codegen): return C-struct records by value
EXTERN_FUNCTION may now return a C-struct record by value, either through
caller-supplied sret memory or as a coerced value stored back into the
record, as clang arranges it. This removes the last by-value rejection.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'lib/CodeGen')
| -rw-r--r-- | lib/CodeGen/FunctionGen.cc | 15 |
1 files changed, 5 insertions, 10 deletions
diff --git a/lib/CodeGen/FunctionGen.cc b/lib/CodeGen/FunctionGen.cc index 9cc1c08..b79698e 100644 --- a/lib/CodeGen/FunctionGen.cc +++ b/lib/CodeGen/FunctionGen.cc @@ -291,9 +291,9 @@ bool FunctionGen::emitExternPrototype(PrototypeAST *Proto) { return false; } - // Records cross the C boundary only as C structs, and are not yet - // returned by value. What names the parameter or return type in diagnostics. - auto CheckRecord = [&](const TypeInfo *Info, const std::string &What, bool IsResult) { + // Records cross the C boundary only as C structs, by value or through a + // pointer type. What names the parameter or return type in diagnostics. + auto CheckRecord = [&](const TypeInfo *Info, const std::string &What) { const TypeInfo *Record = Info->Kind == TypeKind::Pointer ? Types.resolve(Info->Pointer.PointeeTypeName) : Info; if (!Record || !Record->isRecord() || Record->IsClass) return true; @@ -303,11 +303,6 @@ bool FunctionGen::emitExternPrototype(PrototypeAST *Proto) { Record->Name.c_str(), Why.c_str()); return false; } - if (IsResult && Record == Info) { - reportError("%s cannot be record %s by value; use a pointer type to it", What.c_str(), - Record->Name.c_str()); - return false; - } return true; }; @@ -328,7 +323,7 @@ bool FunctionGen::emitExternPrototype(PrototypeAST *Proto) { reportError("Unknown type %s", P.TypeName.c_str()); return false; } - if (!CheckRecord(Info, "EXTERN parameter " + std::to_string(I + 1) + " of " + Name, false)) + if (!CheckRecord(Info, "EXTERN parameter " + std::to_string(I + 1) + " of " + Name)) return false; if (!Types.isExternType(Info)) { reportError("EXTERN parameter %zu of %s must be a non-void C type (got %s)", @@ -347,7 +342,7 @@ bool FunctionGen::emitExternPrototype(PrototypeAST *Proto) { reportError("Unknown type %s", Proto->getReturnType().c_str()); return false; } - if (!CheckRecord(Info, "The return type of EXTERN_FUNCTION " + Name, true)) return false; + if (!CheckRecord(Info, "The return type of EXTERN_FUNCTION " + Name)) return false; if (!Types.isExternType(Info)) { reportError("EXTERN_FUNCTION %s must return a non-void C type (got %s)", Name.c_str(), Proto->getReturnType().c_str()); |
