aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-22 13:45:36 +0000
committer_ov4 <ov4@ov4.org>2026-10-22 13:45:36 +0000
commit3a6eb921b50e191468d29c233718657f9f85d68e (patch)
treeebf411667c1a4360f6e78e0ac971f9df924511d1 /lib
parent06538905915b15bde6364459929fe89cf0b8de5c (diff)
feat(codegen): pass C-struct records by value
EXTERN parameters may now be C-struct records by value. clang's arrangement decides the passing: coerced through memory, flattened into elements, or indirect as byval or a pointer to a copy. Returning a record by value stays rejected for now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/FunctionGen.cc12
1 files changed, 6 insertions, 6 deletions
diff --git a/lib/CodeGen/FunctionGen.cc b/lib/CodeGen/FunctionGen.cc
index 2cf6da3..9cc1c08 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, for now through a
- // pointer type. What names the parameter or return type in diagnostics.
- auto CheckRecord = [&](const TypeInfo *Info, const std::string &What) {
+ // 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) {
const TypeInfo *Record = Info->Kind == TypeKind::Pointer
? Types.resolve(Info->Pointer.PointeeTypeName) : Info;
if (!Record || !Record->isRecord() || Record->IsClass) return true;
@@ -303,7 +303,7 @@ bool FunctionGen::emitExternPrototype(PrototypeAST *Proto) {
Record->Name.c_str(), Why.c_str());
return false;
}
- if (Record == Info) {
+ 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;
@@ -328,7 +328,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))
+ if (!CheckRecord(Info, "EXTERN parameter " + std::to_string(I + 1) + " of " + Name, false))
return false;
if (!Types.isExternType(Info)) {
reportError("EXTERN parameter %zu of %s must be a non-void C type (got %s)",
@@ -347,7 +347,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)) return false;
+ if (!CheckRecord(Info, "The return type of EXTERN_FUNCTION " + Name, true)) 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());