aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/FunctionGen.cc
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-07-26 17:42:08 +0000
committer_ov4 <ov4@ov4.org>2026-07-26 17:42:08 +0000
commita44f1246dbe24fc813a212a5ef3f5811b1d6402a (patch)
treef0894af7daa0bac56471c4dae684ec87588c055d /lib/CodeGen/FunctionGen.cc
parentd65c296a0ad8d335aa076aab48a8b198fa934a2d (diff)
feat: whole arrays (and records) as FUNCTION/PROCEDURE parameters
- Parameter syntax lands end-to-end: ARRAY OF T (rank 1, bounds travel with the argument) and ARRAY[l:u,...] OF T (any rank, literal bounds as a checked contract). Element type and rank must match exactly. - Flattened ABI: each rank-R array parameter becomes a data pointer plus kBoundArgsPerDim i64 bounds per dimension. The callee rebuilds ArrayMetadata from those bounds (ArrayHandler::bindArrayParameter via a binder callback injected by CodeGen, so FunctionGen stays ignorant of the array subsystem); the checked-indexing pipeline is reused unchanged. - BYVAL (the CIE default) copies the whole buffer at callee entry (malloc+memcpy, never freed — consistent with the string policy) so callee writes stay invisible; BYREF binds the caller's buffer. - Bounded-parameter contract: compile-time comparison when the caller's bounds are constants, else a runtime [Fatal] check (RuntimeCheck::emitArrayArgBoundsCheck). - marshalCallArgs gains the array branch and a call-site line number (CallStmtAST now carries one); whole-array-to-scalar keeps a clear error, FUNCTION RETURNS ARRAY is a dedicated parse error. - Verified: BYREF fill/sort-style mutation, BYVAL copy invisibility, 2-D bounded params, ARRAY OF <record> with field writes through the parameter, bounds-contract mismatches at compile time and run time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Diffstat (limited to 'lib/CodeGen/FunctionGen.cc')
-rw-r--r--lib/CodeGen/FunctionGen.cc59
1 files changed, 45 insertions, 14 deletions
diff --git a/lib/CodeGen/FunctionGen.cc b/lib/CodeGen/FunctionGen.cc
index cbaee75..77a37ec 100644
--- a/lib/CodeGen/FunctionGen.cc
+++ b/lib/CodeGen/FunctionGen.cc
@@ -42,6 +42,24 @@ void FunctionGen::createArgumentAllocas(Function *F, const std::vector<ParamDecl
++AI;
ArgVal->setName(P.Name);
+ if (P.IsArray) {
+ // Data pointer + kBoundArgsPerDim bounds per dimension; binding
+ // into the array subsystem is delegated to the injected binder.
+ std::vector<Value*> LBs, UBs;
+ for (int D = 1; D <= P.Rank; ++D) {
+ Value *LB = &(*AI);
+ ++AI;
+ LB->setName(P.Name + kLowerBoundSuffix + std::to_string(D));
+ Value *UB = &(*AI);
+ ++AI;
+ UB->setName(P.Name + kUpperBoundSuffix + std::to_string(D));
+ LBs.push_back(LB);
+ UBs.push_back(UB);
+ }
+ if (BindArrayParam) BindArrayParam(P, ArgVal, LBs, UBs);
+ continue;
+ }
+
if (P.Mode == PassMode::ByRef) {
Symbols[P.Name] = {ArgVal, P.TypeName, false};
continue;
@@ -86,18 +104,27 @@ Function *FunctionGen::emitPrototype(PrototypeAST *Proto) {
std::vector<Type*> ArgTypes;
for (const ParamDecl &P : Proto->getParams()) {
+ ParamSig PS;
+ PS.TypeName = P.TypeName;
+ PS.IsByRef = P.Mode == PassMode::ByRef;
+ PS.IsArray = P.IsArray;
+ PS.Rank = P.Rank;
+ PS.DeclaredBounds = P.DeclaredBounds;
+
if (P.IsArray) {
- fprintf(stderr, "Error: Array parameters are not implemented yet (parameter '%s' of %s)\n",
- P.Name.c_str(), Proto->getName().c_str());
- HadError = true;
- return nullptr;
- }
- Type *T = getLLVMType(P.TypeName);
- if (P.Mode == PassMode::ByRef) {
- T = T->getPointerTo();
+ getLLVMType(P.TypeName); // diagnose an unknown element type
+ ArgTypes.push_back(PointerType::getUnqual(Context)); // data pointer
+ for (unsigned D = 0; D < static_cast<unsigned>(P.Rank) * kBoundArgsPerDim; ++D) {
+ ArgTypes.push_back(Type::getInt64Ty(Context));
+ }
+ } else {
+ Type *T = getLLVMType(P.TypeName);
+ if (PS.IsByRef) {
+ T = T->getPointerTo();
+ }
+ ArgTypes.push_back(T);
}
- ArgTypes.push_back(T);
- Sig.Params.emplace_back(P.TypeName, P.Mode == PassMode::ByRef);
+ Sig.Params.push_back(std::move(PS));
}
Type *RetType = getLLVMType(Proto->getReturnType());
@@ -117,10 +144,14 @@ Function *FunctionGen::emitPrototype(PrototypeAST *Proto) {
// wins and the second is rejected by emitFunctionDef.
Signatures.emplace(Proto->getName(), std::move(Sig));
- unsigned Idx = 0;
- for (auto &Arg : F->args()) {
- if (Idx < Proto->getParams().size()) {
- Arg.setName(Proto->getParams()[Idx++].Name);
+ Function::arg_iterator AI = F->arg_begin();
+ for (const ParamDecl &P : Proto->getParams()) {
+ if (AI == F->arg_end()) break;
+ (AI++)->setName(P.Name);
+ for (int D = 1; P.IsArray && D <= P.Rank && AI != F->arg_end(); ++D) {
+ (AI++)->setName(P.Name + kLowerBoundSuffix + std::to_string(D));
+ if (AI != F->arg_end())
+ (AI++)->setName(P.Name + kUpperBoundSuffix + std::to_string(D));
}
}
return F;