From 533d95d4b54ff2139468d38a7162e5ca3a40a7f6 Mon Sep 17 00:00:00 2001 From: _ov4 Date: Fri, 16 Oct 2026 09:44:47 +0000 Subject: refactor(arrays): separate parameter and output emission Co-Authored-By: Claude Fable 5.1 --- lib/CodeGen/ArrayHandler.cc | 193 -------------------------------------------- 1 file changed, 193 deletions(-) (limited to 'lib/CodeGen/ArrayHandler.cc') diff --git a/lib/CodeGen/ArrayHandler.cc b/lib/CodeGen/ArrayHandler.cc index bd68473..6a89781 100644 --- a/lib/CodeGen/ArrayHandler.cc +++ b/lib/CodeGen/ArrayHandler.cc @@ -253,196 +253,3 @@ std::map ArrayHandler::exchangeTable(std::map &LBs, - const std::vector &UBs, - bool MakeCopy, - CodeGen &CG) { - const TypeInfo *ElemInfo = Types.resolve(ElemTypeName); - if (!ElemInfo || !ElemInfo->LLVMType || ElemInfo->isVoid()) { - CG.reportError("Unknown array element type %s", ElemTypeName.c_str()); - return; - } - - std::vector Multipliers; - Value *TotalElements = nullptr; - computeDimsAndMultipliers(Name, LBs, UBs, Multipliers, TotalElements); - - ArrayMetadata Meta; - Meta.Rank = static_cast(LBs.size()); - Meta.ElementTypeName = ElemInfo->Name; - Meta.ElementType = ElemInfo->LLVMType; - Meta.ElementSizeC = Types.getSizeOfConstant(ElemInfo->LLVMType); - Meta.LowerBounds = LBs; - Meta.UpperBounds = UBs; - Meta.Multipliers = std::move(Multipliers); - ArrayTable[Name] = Meta; - - Value *Ptr = DataPtr; - if (MakeCopy) { - // BYVAL: whole-buffer copy so callee writes stay invisible to the - // caller. The copy is malloc'd and never freed, consistent with the - // project-wide string policy. - Value *TotalBytes = Builder->CreateMul(TotalElements, Meta.ElementSizeC, - Name + "_copy_bytes"); - Value *Copy = Builder->CreateCall(MallocFunc, TotalBytes, Name + "_copy"); - FunctionType *MemcpyType = FunctionType::get( - PointerType::getUnqual(*TheContext), - {PointerType::getUnqual(*TheContext), PointerType::getUnqual(*TheContext), - Type::getInt64Ty(*TheContext)}, - false); - FunctionCallee MemcpyFunc = TheModule->getOrInsertFunction("memcpy", MemcpyType); - Builder->CreateCall(MemcpyFunc, {Copy, DataPtr, TotalBytes}); - Ptr = Copy; - } - - Function *TheFunction = Builder->GetInsertBlock()->getParent(); - AllocaInst *Alloca = CG.CreateEntryBlockAlloca(TheFunction, PointerType::getUnqual(*TheContext), Name); - Builder->CreateStore(Ptr, Alloca); - - CG.registerSymbol(Name, Alloca, ElemInfo->Name, true); -} - -bool ArrayHandler::emitArrayArgument(ExprAST *ArgExpr, - const std::string &ElemTypeName, - int Rank, - const std::vector> &DeclaredBounds, - const std::string &Callee, - int Line, - CodeGen &CG, - std::vector &Out) { - auto *Var = dynamic_cast(ArgExpr); - const ArrayMetadata *Meta = Var ? getMetadata(Var->getName()) : nullptr; - if (!Meta) { - CG.reportError("Argument to %s must be a whole array variable (ARRAY OF %s)", - Callee.c_str(), ElemTypeName.c_str()); - return false; - } - if (!CG.resolveType(Meta->ElementTypeName)->sameType(CG.resolveType(ElemTypeName))) { - CG.reportError("Array argument %s to %s must have element type %s (got %s)", - Var->getName().c_str(), Callee.c_str(), - ElemTypeName.c_str(), Meta->ElementTypeName.c_str()); - return false; - } - if (Meta->Rank != Rank) { - CG.reportError("Array argument %s to %s must have %d dimension%s (got %d)", - Var->getName().c_str(), Callee.c_str(), - Rank, Rank == 1 ? "" : "s", Meta->Rank); - return false; - } - - // Bounded parameters are a contract: verified at compile time when the - // caller's bounds are constants (the common case), at run time otherwise. - for (size_t D = 0; D < DeclaredBounds.size(); ++D) { - int64_t DeclLo = DeclaredBounds[D].first; - int64_t DeclHi = DeclaredBounds[D].second; - auto *ActLo = dyn_cast(Meta->LowerBounds[D]); - auto *ActHi = dyn_cast(Meta->UpperBounds[D]); - if (ActLo && ActHi) { - if (ActLo->getSExtValue() != DeclLo || ActHi->getSExtValue() != DeclHi) { - CG.reportError("Array argument %s to %s has bounds [%lld:%lld] but the parameter declares [%lld:%lld]", - Var->getName().c_str(), Callee.c_str(), - static_cast(ActLo->getSExtValue()), - static_cast(ActHi->getSExtValue()), - static_cast(DeclLo), - static_cast(DeclHi)); - return false; - } - } else { - RuntimeChecker.emitArrayArgBoundsCheck(Meta->LowerBounds[D], Meta->UpperBounds[D], - DeclLo, DeclHi, Line); - } - } - - Value *DataPtr = getArrayBasePointer(Var->getName()); - if (!DataPtr) return false; - Out.push_back(DataPtr); - for (int D = 0; D < Rank; ++D) { - Out.push_back(Meta->LowerBounds[D]); - Out.push_back(Meta->UpperBounds[D]); - } - return true; -} - -bool ArrayHandler::tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG) { - std::string Name; - const std::vector> *IndexExprs = nullptr; - int Line = 0; - - if (auto *Var = dynamic_cast(Expr)) { - Name = Var->getName(); - if (!getMetadata(Name)) return false; - } else if (auto *Acc = dynamic_cast(Expr)) { - Name = Acc->getName(); - const ArrayMetadata *Meta = getMetadata(Name); - if (!Meta) return false; - if (Acc->getIndices().size() == static_cast(Meta->Rank)) { - return false; // full element access: handled by the normal expression path - } - IndexExprs = &Acc->getIndices(); - Line = Acc->getLine(); - } else { - return false; - } - - const TypeInfo *ElemInfo = Types.resolve(getMetadata(Name)->ElementTypeName); - if (ElemInfo && !ElemInfo->isOutputtable()) { - CG.reportError("Cannot OUTPUT array %s of type %s; output individual fields", - Name.c_str(), ElemInfo->Name.c_str()); - return true; // diagnosed - } - - std::vector Indices; - if (IndexExprs && !emitCheckedIndices(Name, *IndexExprs, Line, false, CG, Indices)) { - return true; // diagnosed - } - - emitPrintLoop(Name, static_cast(Indices.size()), Indices, CG); - return true; -} - -void ArrayHandler::emitPrintLoop(const std::string &Name, - int CurrentDim, - std::vector CurrentIndices, - CodeGen &CG) { - const ArrayMetadata *Meta = getMetadata(Name); - if (!Meta) return; - - if (CurrentDim == Meta->Rank) { - Value *Offset = computeFlatIndex(Name, CurrentIndices); - Value *Val = loadElement(Name, Offset, CG); - if (!Val) return; - - CG.emitOutputValue(Val, Types.resolve(Meta->ElementTypeName), true); - return; - } - - Function *TheFunction = Builder->GetInsertBlock()->getParent(); - BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "arr_loop", TheFunction); - BasicBlock *AfterBB = BasicBlock::Create(*TheContext, "arr_after", TheFunction); - - AllocaInst *LoopVar = CG.CreateEntryBlockAlloca(TheFunction, Type::getInt64Ty(*TheContext), "idx"); - Value *Start = Meta->LowerBounds[CurrentDim]; - Value *End = Meta->UpperBounds[CurrentDim]; - - Builder->CreateStore(Start, LoopVar); - Builder->CreateBr(LoopBB); - - Builder->SetInsertPoint(LoopBB); - Value *CurVal = Builder->CreateLoad(Type::getInt64Ty(*TheContext), LoopVar); - - std::vector NextIndices = CurrentIndices; - NextIndices.push_back(CurVal); - emitPrintLoop(Name, CurrentDim + 1, NextIndices, CG); - - Value *NextVal = Builder->CreateAdd(CurVal, ConstantInt::get(*TheContext, APInt(64, 1))); - Builder->CreateStore(NextVal, LoopVar); - - Value *Cond = Builder->CreateICmpSLE(NextVal, End); - Builder->CreateCondBr(Cond, LoopBB, AfterBB); - - Builder->SetInsertPoint(AfterBB); -} -- cgit v1.3.1-4-g156e