aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/ArrayHandler.cc193
-rw-r--r--lib/CodeGen/ArrayOutput.cc90
-rw-r--r--lib/CodeGen/ArrayParameters.cc123
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;
+}