diff options
Diffstat (limited to 'lib/CodeGen')
| -rw-r--r-- | lib/CodeGen/ArrayHandler.cc | 193 | ||||
| -rw-r--r-- | lib/CodeGen/ArrayOutput.cc | 90 | ||||
| -rw-r--r-- | lib/CodeGen/ArrayParameters.cc | 123 |
3 files changed, 213 insertions, 193 deletions
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<std::string, ArrayMetadata> ArrayHandler::exchangeTable(std::map<std::s std::swap(ArrayTable, NewTable); return NewTable; } - -void ArrayHandler::bindArrayParameter(const std::string &Name, - const std::string &ElemTypeName, - Value *DataPtr, - const std::vector<Value*> &LBs, - const std::vector<Value*> &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<Value*> Multipliers; - Value *TotalElements = nullptr; - computeDimsAndMultipliers(Name, LBs, UBs, Multipliers, TotalElements); - - ArrayMetadata Meta; - Meta.Rank = static_cast<int>(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<std::pair<int64_t, int64_t>> &DeclaredBounds, - const std::string &Callee, - int Line, - CodeGen &CG, - std::vector<Value*> &Out) { - auto *Var = dynamic_cast<VariableExprAST*>(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<ConstantInt>(Meta->LowerBounds[D]); - auto *ActHi = dyn_cast<ConstantInt>(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<long long>(ActLo->getSExtValue()), - static_cast<long long>(ActHi->getSExtValue()), - static_cast<long long>(DeclLo), - static_cast<long long>(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<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); -} 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); +} diff --git a/lib/CodeGen/ArrayParameters.cc b/lib/CodeGen/ArrayParameters.cc new file mode 100644 index 0000000..09017c9 --- /dev/null +++ b/lib/CodeGen/ArrayParameters.cc @@ -0,0 +1,123 @@ +#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; + +void ArrayHandler::bindArrayParameter(const std::string &Name, + const std::string &ElemTypeName, + Value *DataPtr, + const std::vector<Value*> &LBs, + const std::vector<Value*> &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<Value*> Multipliers; + Value *TotalElements = nullptr; + computeDimsAndMultipliers(Name, LBs, UBs, Multipliers, TotalElements); + + ArrayMetadata Meta; + Meta.Rank = static_cast<int>(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<std::pair<int64_t, int64_t>> &DeclaredBounds, + const std::string &Callee, + int Line, + CodeGen &CG, + std::vector<Value*> &Out) { + auto *Var = dynamic_cast<VariableExprAST*>(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<ConstantInt>(Meta->LowerBounds[D]); + auto *ActHi = dyn_cast<ConstantInt>(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<long long>(ActLo->getSExtValue()), + static_cast<long long>(ActHi->getSExtValue()), + static_cast<long long>(DeclLo), + static_cast<long long>(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; +} |
