aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CallGen.cc
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-22 13:59:48 +0000
committer_ov4 <ov4@ov4.org>2026-10-22 13:59:48 +0000
commitf694cc443ccc17a494cd195151882ab5e491bbb2 (patch)
tree4a74ec68a1406073c5d70d8a0a71b5d839e0c3ef /lib/CodeGen/CallGen.cc
parent312a19c781da1c31ff1e3dc71c319663a8be9148 (diff)
feat(codegen): accept ^x of C values as variadic arguments
In a variadic EXTERN position, ^x now passes the address of x as a plain pointer when x has a C type or is a C struct, like C's f(n, &x). The address of a pseudocode-typed value keeps the "must be a C value" error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'lib/CodeGen/CallGen.cc')
-rw-r--r--lib/CodeGen/CallGen.cc12
1 files changed, 11 insertions, 1 deletions
diff --git a/lib/CodeGen/CallGen.cc b/lib/CodeGen/CallGen.cc
index 576520d..4631332 100644
--- a/lib/CodeGen/CallGen.cc
+++ b/lib/CodeGen/CallGen.cc
@@ -133,7 +133,10 @@ bool CodeGen::marshalCallArgs(const FuncSig &Signature,
// C structs and pointers to them pass unchanged (C11 6.5.2.2p6-7, 7.16.1.1p2).
Value *CodeGen::emitVariadicArgument(ExprAST *Expr, const std::string &Callee, size_t Position,
const TypeInfo *&Promoted) {
- const TypeInfo *Info = isWholeArrayVar(Expr) ? nullptr : getExprTypeInfo(Expr);
+ ExprAST *Target = Expr;
+ auto *Addr = dynamic_cast<AddrOfExprAST *>(Expr);
+ if (Addr) Target = Addr->getTarget();
+ const TypeInfo *Info = isWholeArrayVar(Target) ? nullptr : getExprTypeInfo(Target);
const TypeInfo *Record = Types->pointerBase(Info);
std::string Why;
if (Record && Record->isRecord() && !Record->IsClass && !Types->isCStruct(Record, &Why)) {
@@ -145,6 +148,13 @@ Value *CodeGen::emitVariadicArgument(ExprAST *Expr, const std::string &Callee, s
reportError("Variadic argument %zu to %s must be a C value; cast it to a C type", Position, Callee.c_str());
return nullptr;
}
+ // ^x of a C value or C struct is a plain pointer, like C's f(n, &x).
+ if (Addr) {
+ LValueInfo LV;
+ if (!emitLValue(Target, LV)) return nullptr;
+ Promoted = Types->resolve("C_TYPE(\"void*\")");
+ return LV.Addr;
+ }
Promoted = Info;
Value *V = emitExpr(Expr);
if (!V || Info->Kind != TypeKind::CScalar) return V;