diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-16 09:44:47 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-16 09:44:47 +0000 |
| commit | 533d95d4b54ff2139468d38a7162e5ca3a40a7f6 (patch) | |
| tree | e79b5ccb1fafca7ccf5e7198309289f3b07a42b1 /lib/CodeGen/ArrayOutput.cc | |
| parent | 2d84c01c1ccbb0a746f103d167ed7f3448b4a349 (diff) | |
refactor(arrays): separate parameter and output emission
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'lib/CodeGen/ArrayOutput.cc')
| -rw-r--r-- | lib/CodeGen/ArrayOutput.cc | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/lib/CodeGen/ArrayOutput.cc b/lib/CodeGen/ArrayOutput.cc new file mode 100644 index 0000000..91e9f49 --- /dev/null +++ b/lib/CodeGen/ArrayOutput.cc @@ -0,0 +1,90 @@ +#include "cps/ArrayHandler.h" +#include "cps/CodeGen.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Type.h" +#include <cstdio> + +using namespace llvm; +using namespace cps; + +bool ArrayHandler::tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG) { + std::string Name; + const std::vector<std::unique_ptr<ExprAST>> *IndexExprs = nullptr; + int Line = 0; + + if (auto *Var = dynamic_cast<VariableExprAST*>(Expr)) { + Name = Var->getName(); + if (!getMetadata(Name)) return false; + } else if (auto *Acc = dynamic_cast<ArrayAccessExprAST*>(Expr)) { + Name = Acc->getName(); + const ArrayMetadata *Meta = getMetadata(Name); + if (!Meta) return false; + if (Acc->getIndices().size() == static_cast<size_t>(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<Value*> Indices; + if (IndexExprs && !emitCheckedIndices(Name, *IndexExprs, Line, false, CG, Indices)) { + return true; // diagnosed + } + + emitPrintLoop(Name, static_cast<int>(Indices.size()), Indices, CG); + return true; +} + +void ArrayHandler::emitPrintLoop(const std::string &Name, + int CurrentDim, + std::vector<Value*> 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<Value*> 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); +} |
