aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/ArrayHandler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/ArrayHandler.cc')
-rw-r--r--lib/CodeGen/ArrayHandler.cc326
1 files changed, 198 insertions, 128 deletions
diff --git a/lib/CodeGen/ArrayHandler.cc b/lib/CodeGen/ArrayHandler.cc
index 5842f77..fd55009 100644
--- a/lib/CodeGen/ArrayHandler.cc
+++ b/lib/CodeGen/ArrayHandler.cc
@@ -1,22 +1,35 @@
#include "cps/ArrayHandler.h"
#include "cps/CodeGen.h"
-#include "llvm/IR/Type.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;
-ArrayHandler::ArrayHandler(LLVMContext &C, IRBuilder<> &B, Module &M, std::map<std::string, Value*> &NV, RuntimeCheck &RC)
- : TheContext(&C), Builder(&B), TheModule(&M), NamedValues(&NV), RuntimeChecker(RC) {
+ArrayHandler::ArrayHandler(LLVMContext &C,
+ IRBuilder<> &B,
+ Module &M,
+ std::map<std::string, Value*> &NV,
+ std::map<std::string, SymbolInfo> &Sym,
+ TypeSystem &TS,
+ RuntimeCheck &RC)
+ : TheContext(&C),
+ Builder(&B),
+ TheModule(&M),
+ NamedValues(&NV),
+ Symbols(&Sym),
+ Types(TS),
+ RuntimeChecker(RC) {
setupExternalFunctions();
}
void ArrayHandler::setupExternalFunctions() {
std::vector<Type*> MallocArgs;
MallocArgs.push_back(Type::getInt64Ty(*TheContext));
-
+
FunctionType *MallocType = FunctionType::get(PointerType::getUnqual(*TheContext), MallocArgs, false);
MallocFunc = TheModule->getOrInsertFunction("malloc", MallocType);
@@ -26,89 +39,124 @@ void ArrayHandler::setupExternalFunctions() {
FreeFunc = TheModule->getOrInsertFunction("free", FreeType);
}
+const ArrayMetadata *ArrayHandler::getMetadata(const std::string &Name) const {
+ auto It = ArrayTable.find(Name);
+ if (It == ArrayTable.end()) {
+ return nullptr;
+ }
+ return &It->second;
+}
+
+Value *ArrayHandler::computeFlatIndex(const std::string &Name, const std::vector<Value*> &Indices) {
+ const ArrayMetadata *Meta = getMetadata(Name);
+ if (!Meta) return nullptr;
+
+ Value *Offset = ConstantInt::get(*TheContext, APInt(64, 0));
+ for (size_t i = 0; i < Indices.size(); ++i) {
+ Value *Idx = Indices[i];
+ Value *Lower = Meta->LowerBounds[i];
+ Value *Diff = Builder->CreateSub(Idx, Lower);
+ Value *Term = Builder->CreateMul(Diff, Meta->Multipliers[i]);
+ Offset = Builder->CreateAdd(Offset, Term);
+ }
+ return Offset;
+}
+
+Value *ArrayHandler::getArrayBasePointer(const std::string &Name) {
+ auto It = NamedValues->find(Name);
+ if (It == NamedValues->end() || !It->second) {
+ return nullptr;
+ }
+ return Builder->CreateLoad(PointerType::getUnqual(*TheContext), It->second, (Name + "_raw").c_str());
+}
+
+Value *ArrayHandler::getElementPointer(const std::string &Name, Value *Offset) {
+ const ArrayMetadata *Meta = getMetadata(Name);
+ if (!Meta || !Offset) return nullptr;
+
+ Value *RawPtr = getArrayBasePointer(Name);
+ if (!RawPtr) return nullptr;
+
+ PointerType *TypedPtrTy = PointerType::getUnqual(Meta->ElementType);
+ Value *TypedPtr = Builder->CreateBitCast(RawPtr, TypedPtrTy, Name + "_typed_ptr");
+ return Builder->CreateGEP(Meta->ElementType, TypedPtr, Offset, Name + "_elem_ptr");
+}
+
void ArrayHandler::emitArrayDeclare(ArrayDeclareStmtAST *Stmt, CodeGen &CG) {
std::string Name = Stmt->getName();
- int Rank = Stmt->getBounds().size();
-
- std::vector<Value*> Lows, Highs, Dims;
+ int Rank = static_cast<int>(Stmt->getBounds().size());
+
+ const TypeInfo *ElemInfo = Types.resolve(Stmt->getType());
+ if (!ElemInfo || !ElemInfo->LLVMType || ElemInfo->isVoid()) {
+ fprintf(stderr, "Error: Unknown array element type %s\n", Stmt->getType().c_str());
+ return;
+ }
+
+ std::vector<Value*> Lows;
+ std::vector<Value*> Highs;
+ std::vector<Value*> Dims;
Value *TotalElements = ConstantInt::get(*TheContext, APInt(64, 1));
-
+
for (const auto &Pair : Stmt->getBounds()) {
Value *L = CG.emitExpr(Pair.first.get());
Value *R = CG.emitExpr(Pair.second.get());
-
+ L = CG.coerceValueToType(L, CG.resolveType("INTEGER"));
+ R = CG.coerceValueToType(R, CG.resolveType("INTEGER"));
+
if (!L || !R) return;
-
- Value *L64 = Builder->CreateSExt(L, Type::getInt64Ty(*TheContext));
- Value *R64 = Builder->CreateSExt(R, Type::getInt64Ty(*TheContext));
-
+
Lows.push_back(L);
Highs.push_back(R);
-
- Value *Diff = Builder->CreateSub(R64, L64);
- Value *DimSize = Builder->CreateAdd(Diff, ConstantInt::get(*TheContext, APInt(64, 1)));
+
+ Value *Diff = Builder->CreateSub(R, L, Name + "_dim_diff");
+ Value *DimSize = Builder->CreateAdd(Diff, ConstantInt::get(*TheContext, APInt(64, 1)), Name + "_dim_size");
Dims.push_back(DimSize);
-
- TotalElements = Builder->CreateMul(TotalElements, DimSize);
+ TotalElements = Builder->CreateMul(TotalElements, DimSize, Name + "_total_elems");
}
-
+
std::vector<Value*> Multipliers(Rank);
Multipliers[Rank - 1] = ConstantInt::get(*TheContext, APInt(64, 1));
-
for (int i = Rank - 2; i >= 0; --i) {
- Value *NextMult = Multipliers[i+1];
- Value *NextDimSize = Dims[i+1];
- Multipliers[i] = Builder->CreateMul(NextMult, NextDimSize);
+ Multipliers[i] = Builder->CreateMul(Multipliers[i + 1], Dims[i + 1], Name + "_mult");
}
ArrayMetadata Meta;
Meta.Rank = Rank;
- Meta.ElementType = Type::getInt64Ty(*TheContext);
- Meta.LowerBounds = Lows;
- Meta.UpperBounds = Highs;
- Meta.Multipliers = Multipliers;
+ Meta.ElementTypeName = ElemInfo->Name;
+ Meta.ElementType = ElemInfo->LLVMType;
+ Meta.ElementSize = ElemInfo->ElementSize;
+ Meta.LowerBounds = std::move(Lows);
+ Meta.UpperBounds = std::move(Highs);
+ Meta.Multipliers = std::move(Multipliers);
ArrayTable[Name] = Meta;
-
- Value *ElemSize = ConstantInt::get(*TheContext, APInt(64, 8));
- Value *TotalBytes = Builder->CreateMul(TotalElements, ElemSize);
-
- CallInst *Ptr = Builder->CreateCall(MallocFunc, TotalBytes);
-
+ Value *ElemSize = ConstantInt::get(*TheContext, APInt(64, ElemInfo->ElementSize));
+ Value *TotalBytes = Builder->CreateMul(TotalElements, ElemSize, Name + "_total_bytes");
+ CallInst *Ptr = Builder->CreateCall(MallocFunc, TotalBytes, Name + "_malloc");
+
+ FunctionType *MemsetType = FunctionType::get(PointerType::getUnqual(*TheContext),
+ {PointerType::getUnqual(*TheContext), Type::getInt32Ty(*TheContext), Type::getInt64Ty(*TheContext)},
+ false);
+ FunctionCallee MemsetFunc = TheModule->getOrInsertFunction("memset", MemsetType);
+ Builder->CreateCall(MemsetFunc,
+ {Ptr, ConstantInt::get(Type::getInt32Ty(*TheContext), 0), TotalBytes});
+
Function *TheFunction = Builder->GetInsertBlock()->getParent();
- IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin());
-
- AllocaInst *Alloca = TmpB.CreateAlloca(PointerType::getUnqual(*TheContext), nullptr, Name);
-
+ AllocaInst *Alloca = CG.CreateEntryBlockAlloca(TheFunction, PointerType::getUnqual(*TheContext), Name);
Builder->CreateStore(Ptr, Alloca);
- (*NamedValues)[Name] = Alloca;
-}
-Value* ArrayHandler::computeFlatIndex(const std::string &Name, const std::vector<Value*> &Indices) {
- if (ArrayTable.find(Name) == ArrayTable.end()) return nullptr;
- const auto &Meta = ArrayTable[Name];
-
- Value *Offset = ConstantInt::get(*TheContext, APInt(64, 0));
-
- for (size_t i = 0; i < Indices.size(); ++i) {
- Value *Idx = Indices[i];
- Value *Lower = Meta.LowerBounds[i];
- Value *Diff = Builder->CreateSub(Idx, Lower);
- Value *Term = Builder->CreateMul(Diff, Meta.Multipliers[i]);
- Offset = Builder->CreateAdd(Offset, Term);
- }
- return Offset;
+ CG.registerSymbol(Name, Alloca, ElemInfo->Name, true);
}
-Value* ArrayHandler::emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG) {
+Value *ArrayHandler::emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG) {
std::string Name = Expr->getName();
- if (ArrayTable.find(Name) == ArrayTable.end()) {
+ const ArrayMetadata *Meta = getMetadata(Name);
+ if (!Meta) {
fprintf(stderr, "Error: Undeclared array %s\n", Name.c_str());
return nullptr;
}
-
- const auto &Meta = ArrayTable[Name];
- if (Expr->getIndices().size() != Meta.Rank) {
+
+ if (Expr->getIndices().size() != static_cast<size_t>(Meta->Rank)) {
fprintf(stderr, "Error: Incorrect number of indices for %s\n", Name.c_str());
return nullptr;
}
@@ -116,125 +164,147 @@ Value* ArrayHandler::emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG) {
std::vector<Value*> Indices;
for (size_t i = 0; i < Expr->getIndices().size(); ++i) {
Value *Idx = CG.emitExpr(Expr->getIndices()[i].get());
- Indices.push_back(Idx);
+ Idx = CG.coerceValueToType(Idx, CG.resolveType("INTEGER"));
+ if (!Idx) return nullptr;
- Value *Lower = Meta.LowerBounds[i];
- Value *Upper = Meta.UpperBounds[i];
- RuntimeChecker.emitIndexCheck(Idx, Lower, Upper, Expr->getLine());
+ Indices.push_back(Idx);
+ RuntimeChecker.emitIndexCheck(Idx, Meta->LowerBounds[i], Meta->UpperBounds[i], Expr->getLine());
}
-
+
Value *Offset = computeFlatIndex(Name, Indices);
-
- Value *Alloca = (*NamedValues)[Name];
- Value *RawPtr = Builder->CreateLoad(PointerType::getUnqual(*TheContext), Alloca);
- Value *IntPtr = Builder->CreateBitCast(RawPtr, PointerType::getUnqual(*TheContext));
- Value *ElemPtr = Builder->CreateGEP(Type::getInt64Ty(*TheContext), IntPtr, Offset);
-
- return Builder->CreateLoad(Type::getInt64Ty(*TheContext), ElemPtr);
+ Value *ElemPtr = getElementPointer(Name, Offset);
+ if (!ElemPtr) return nullptr;
+
+ Value *Val = Builder->CreateLoad(Meta->ElementType, ElemPtr, Name + "_elem");
+ if (Meta->ElementTypeName == "STRING") {
+ Value *IsNull = Builder->CreateICmpEQ(Val,
+ ConstantPointerNull::get(cast<PointerType>(Meta->ElementType)),
+ Name + "_str_is_null");
+ Val = Builder->CreateSelect(IsNull, CG.EmptyStringStr, Val, Name + "_safe_str");
+ }
+ return Val;
}
void ArrayHandler::emitArrayAssign(ArrayAssignStmtAST *Stmt, CodeGen &CG) {
std::string Name = Stmt->getName();
- if (ArrayTable.find(Name) == ArrayTable.end()) {
+ const ArrayMetadata *Meta = getMetadata(Name);
+ if (!Meta) {
fprintf(stderr, "Error: Undeclared array %s\n", Name.c_str());
return;
}
-
+
+ if (Stmt->getIndices().size() != static_cast<size_t>(Meta->Rank)) {
+ fprintf(stderr, "Error: Incorrect number of indices for %s\n", Name.c_str());
+ return;
+ }
+
std::vector<Value*> Indices;
for (size_t i = 0; i < Stmt->getIndices().size(); ++i) {
Value *Idx = CG.emitExpr(Stmt->getIndices()[i].get());
- Indices.push_back(Idx);
+ Idx = CG.coerceValueToType(Idx, CG.resolveType("INTEGER"));
+ if (!Idx) return;
- const auto &Meta = ArrayTable[Name];
- Value *Lower = Meta.LowerBounds[i];
- Value *Upper = Meta.UpperBounds[i];
- RuntimeChecker.emitIndexCheck(Idx, Lower, Upper, Stmt->getLine());
+ Indices.push_back(Idx);
+ RuntimeChecker.emitIndexCheck(Idx, Meta->LowerBounds[i], Meta->UpperBounds[i], Stmt->getLine());
}
-
+
+ const TypeInfo *ElemInfo = Types.resolve(Meta->ElementTypeName);
Value *Val = CG.emitExpr(Stmt->getExpr());
+ Val = CG.coerceValueToType(Val, ElemInfo);
+ if (!Val) return;
+
Value *Offset = computeFlatIndex(Name, Indices);
-
- Value *Alloca = (*NamedValues)[Name];
- Value *RawPtr = Builder->CreateLoad(PointerType::getUnqual(*TheContext), Alloca);
- Value *IntPtr = Builder->CreateBitCast(RawPtr, PointerType::getUnqual(*TheContext));
- Value *ElemPtr = Builder->CreateGEP(Type::getInt64Ty(*TheContext), IntPtr, Offset);
-
+ Value *ElemPtr = getElementPointer(Name, Offset);
+ if (!ElemPtr) return;
+
Builder->CreateStore(Val, ElemPtr);
}
-bool ArrayHandler::tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG, llvm::FunctionCallee PrintfFunc, llvm::Value* FmtStr) {
+bool ArrayHandler::tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG) {
std::string Name;
std::vector<Value*> Indices;
-
+
if (auto *Var = dynamic_cast<VariableExprAST*>(Expr)) {
Name = Var->getName();
- if (ArrayTable.find(Name) == ArrayTable.end()) return false;
- }
- else if (auto *Acc = dynamic_cast<ArrayAccessExprAST*>(Expr)) {
+ if (!getMetadata(Name)) return false;
+ } else if (auto *Acc = dynamic_cast<ArrayAccessExprAST*>(Expr)) {
Name = Acc->getName();
- if (ArrayTable.find(Name) == ArrayTable.end()) return false;
-
- for (const auto &Idx : Acc->getIndices()) {
- Indices.push_back(CG.emitExpr(Idx.get()));
+ const ArrayMetadata *Meta = getMetadata(Name);
+ if (!Meta) return false;
+
+ for (size_t i = 0; i < Acc->getIndices().size(); ++i) {
+ Value *Idx = CG.emitExpr(Acc->getIndices()[i].get());
+ Idx = CG.coerceValueToType(Idx, CG.resolveType("INTEGER"));
+ if (!Idx) return false;
+ Indices.push_back(Idx);
+ RuntimeChecker.emitIndexCheck(Idx, Meta->LowerBounds[i], Meta->UpperBounds[i], Acc->getLine());
+ }
+
+ if (Indices.size() > static_cast<size_t>(Meta->Rank)) {
+ fprintf(stderr, "Error: Incorrect number of indices for %s\n", Name.c_str());
+ return true;
}
} else {
return false;
}
-
- const auto &Meta = ArrayTable[Name];
-
- if (Indices.size() == Meta.Rank) {
+
+ const ArrayMetadata *Meta = getMetadata(Name);
+ if (!Meta) return false;
+ if (Indices.size() == static_cast<size_t>(Meta->Rank)) {
return false;
}
-
- emitPrintLoop(Name, Indices.size(), Indices, PrintfFunc, FmtStr);
+
+ emitPrintLoop(Name, static_cast<int>(Indices.size()), Indices, CG);
return true;
}
-void ArrayHandler::emitPrintLoop(const std::string &Name, int CurrentDim, std::vector<Value*> CurrentIndices, llvm::FunctionCallee PrintfFunc, llvm::Value* FmtStr) {
- const auto &Meta = ArrayTable[Name];
-
- if (CurrentDim == Meta.Rank) {
+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 *Alloca = (*NamedValues)[Name];
- Value *RawPtr = Builder->CreateLoad(PointerType::getUnqual(*TheContext), Alloca);
- Value *IntPtr = Builder->CreateBitCast(RawPtr, PointerType::getUnqual(*TheContext));
- Value *ElemPtr = Builder->CreateGEP(Type::getInt64Ty(*TheContext), IntPtr, Offset);
- Value *Val = Builder->CreateLoad(Type::getInt64Ty(*TheContext), ElemPtr);
-
- std::vector<Value*> Args;
- Args.push_back(FmtStr);
- Args.push_back(Val);
- Builder->CreateCall(PrintfFunc, Args);
+ Value *ElemPtr = getElementPointer(Name, Offset);
+ if (!ElemPtr) return;
+
+ Value *Val = Builder->CreateLoad(Meta->ElementType, ElemPtr, Name + "_print_val");
+ if (Meta->ElementTypeName == "STRING") {
+ Value *IsNull = Builder->CreateICmpEQ(Val,
+ ConstantPointerNull::get(cast<PointerType>(Meta->ElementType)),
+ Name + "_print_str_is_null");
+ Val = Builder->CreateSelect(IsNull, CG.EmptyStringStr, Val, Name + "_print_safe_str");
+ }
+
+ 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);
-
- IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin());
- AllocaInst *LoopVar = TmpB.CreateAlloca(Type::getInt64Ty(*TheContext), nullptr, "idx");
-
- Value *Start = Meta.LowerBounds[CurrentDim];
- Value *End = Meta.UpperBounds[CurrentDim];
-
+
+ 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, PrintfFunc, FmtStr);
-
+ 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);
}