aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cps/ArrayHandler.h18
-rw-r--r--include/cps/CodeGen.h3
-rw-r--r--include/cps/TypeSystem.h5
-rw-r--r--lib/CodeGen/ArrayHandler.cc51
-rw-r--r--lib/CodeGen/CodeGen.cc25
-rw-r--r--lib/CodeGen/TypeSystem.cc4
6 files changed, 78 insertions, 28 deletions
diff --git a/include/cps/ArrayHandler.h b/include/cps/ArrayHandler.h
index 6e2c015..e4ccc51 100644
--- a/include/cps/ArrayHandler.h
+++ b/include/cps/ArrayHandler.h
@@ -16,7 +16,7 @@ struct ArrayMetadata {
int Rank = 0;
std::string ElementTypeName;
llvm::Type *ElementType = nullptr;
- uint64_t ElementSize = 0;
+ llvm::Constant *ElementSizeC = nullptr; // i64 sizeof constant (target-folded)
std::vector<llvm::Value*> LowerBounds;
std::vector<llvm::Value*> UpperBounds;
std::vector<llvm::Value*> Multipliers;
@@ -67,6 +67,22 @@ public:
llvm::Value *emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG);
bool tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG);
+
+ // Full-rank checked element address (bounds checks included); reports the
+ // element type name through ElemTypeNameOut. The lvalue layer builds
+ // field/deref accesses on top of this.
+ llvm::Value *emitElementAddress(const std::string &Name,
+ const std::vector<std::unique_ptr<ExprAST>> &IndexExprs,
+ int Line,
+ CodeGen &CG,
+ std::string &ElemTypeNameOut);
+ llvm::Value *emitElementAddress(ArrayAccessExprAST *Expr,
+ CodeGen &CG,
+ std::string &ElemTypeNameOut);
+
+ // Swap in a fresh table (function bodies get their own scope, mirroring
+ // the Symbols save/clear/restore discipline); returns the previous table.
+ std::map<std::string, ArrayMetadata> exchangeTable(std::map<std::string, ArrayMetadata> NewTable);
};
} // namespace cps
diff --git a/include/cps/CodeGen.h b/include/cps/CodeGen.h
index 43d3a32..2451cbd 100644
--- a/include/cps/CodeGen.h
+++ b/include/cps/CodeGen.h
@@ -87,6 +87,9 @@ public:
llvm::Value *emitExpr(ExprAST *Expr);
void emitStmt(StmtAST *Stmt);
+ // STRING slots zero-init to null; normalize null to "" at load/print sites.
+ llvm::Value *emitStringNullGuard(llvm::Value *StrVal);
+
const TypeInfo *resolveType(const std::string &TypeName) const;
llvm::Type *getLLVMType(const std::string &TypeName) const;
llvm::Value *getNamedValue(const std::string &Name) const;
diff --git a/include/cps/TypeSystem.h b/include/cps/TypeSystem.h
index 32c348f..14a21bd 100644
--- a/include/cps/TypeSystem.h
+++ b/include/cps/TypeSystem.h
@@ -66,6 +66,11 @@ public:
llvm::Type *getLLVMType(const std::string &TypeName) const;
uint64_t getElementSize(const std::string &TypeName) const;
llvm::Constant *getZeroValue(const std::string &TypeName) const;
+
+ // Target-independent sizeof: a null-GEP+ptrtoint i64 constant the backend
+ // folds with the *real* target's DataLayout. The module carries no
+ // DataLayout string, so sizes must never be computed host-side.
+ llvm::Constant *getSizeOfConstant(llvm::Type *Ty) const;
};
} // namespace cps
diff --git a/lib/CodeGen/ArrayHandler.cc b/lib/CodeGen/ArrayHandler.cc
index 83204a7..7977563 100644
--- a/lib/CodeGen/ArrayHandler.cc
+++ b/lib/CodeGen/ArrayHandler.cc
@@ -117,14 +117,13 @@ void ArrayHandler::emitArrayDeclare(ArrayDeclareStmtAST *Stmt, CodeGen &CG) {
Meta.Rank = Rank;
Meta.ElementTypeName = ElemInfo->Name;
Meta.ElementType = ElemInfo->LLVMType;
- Meta.ElementSize = ElemInfo->ElementSize;
+ Meta.ElementSizeC = Types.getSizeOfConstant(ElemInfo->LLVMType);
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, ElemInfo->ElementSize));
- Value *TotalBytes = Builder->CreateMul(TotalElements, ElemSize, Name + "_total_bytes");
+ Value *TotalBytes = Builder->CreateMul(TotalElements, Meta.ElementSizeC, Name + "_total_bytes");
CallInst *Ptr = Builder->CreateCall(MallocFunc, TotalBytes, Name + "_malloc");
FunctionType *MemsetType = FunctionType::get(PointerType::getUnqual(*TheContext),
@@ -179,10 +178,7 @@ Value *ArrayHandler::loadElement(const std::string &Name, Value *Offset, CodeGen
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");
+ Val = CG.emitStringNullGuard(Val);
}
return Val;
}
@@ -198,22 +194,45 @@ Value *ArrayHandler::emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG) {
}
void ArrayHandler::emitArrayAssign(ArrayAssignStmtAST *Stmt, CodeGen &CG) {
- std::string Name = Stmt->getName();
- std::vector<Value*> Indices;
- if (!emitCheckedIndices(Name, Stmt->getIndices(), Stmt->getLine(), true, CG, Indices))
- return;
+ std::string ElemTypeName;
+ Value *ElemPtr = emitElementAddress(Stmt->getName(), Stmt->getIndices(),
+ Stmt->getLine(), CG, ElemTypeName);
+ if (!ElemPtr) return;
- const ArrayMetadata *Meta = getMetadata(Name);
- const TypeInfo *ElemInfo = Types.resolve(Meta->ElementTypeName);
Value *Val = CG.emitExpr(Stmt->getExpr());
- Val = CG.coerceValueToType(Val, ElemInfo);
+ Val = CG.coerceValueToType(Val, Types.resolve(ElemTypeName));
if (!Val) return;
+ Builder->CreateStore(Val, ElemPtr);
+}
+
+Value *ArrayHandler::emitElementAddress(const std::string &Name,
+ const std::vector<std::unique_ptr<ExprAST>> &IndexExprs,
+ int Line,
+ CodeGen &CG,
+ std::string &ElemTypeNameOut) {
+ std::vector<Value*> Indices;
+ if (!emitCheckedIndices(Name, IndexExprs, Line, true, CG, Indices))
+ return nullptr;
+
Value *Offset = computeFlatIndex(Name, Indices);
Value *ElemPtr = getElementPointer(Name, Offset);
- if (!ElemPtr) return;
+ if (!ElemPtr) return nullptr;
- Builder->CreateStore(Val, ElemPtr);
+ ElemTypeNameOut = getMetadata(Name)->ElementTypeName;
+ return ElemPtr;
+}
+
+Value *ArrayHandler::emitElementAddress(ArrayAccessExprAST *Expr,
+ CodeGen &CG,
+ std::string &ElemTypeNameOut) {
+ return emitElementAddress(Expr->getName(), Expr->getIndices(), Expr->getLine(),
+ CG, ElemTypeNameOut);
+}
+
+std::map<std::string, ArrayMetadata> ArrayHandler::exchangeTable(std::map<std::string, ArrayMetadata> NewTable) {
+ std::swap(ArrayTable, NewTable);
+ return NewTable;
}
bool ArrayHandler::tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG) {
diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc
index ae82914..4b9ebfb 100644
--- a/lib/CodeGen/CodeGen.cc
+++ b/lib/CodeGen/CodeGen.cc
@@ -363,6 +363,14 @@ void CodeGen::emitDeclareStmt(DeclareStmtAST *Stmt) {
registerSymbol(Stmt->getName(), Alloca, Info->Name, false);
}
+Value *CodeGen::emitStringNullGuard(Value *StrVal) {
+ if (!StrVal || !StrVal->getType()->isPointerTy()) return StrVal;
+ Value *IsNull = Builder->CreateICmpEQ(StrVal,
+ ConstantPointerNull::get(cast<PointerType>(StrVal->getType())),
+ "str_is_null");
+ return Builder->CreateSelect(IsNull, EmptyStringStr, StrVal, "safe_str");
+}
+
void CodeGen::emitOutputValue(Value *Val, const TypeInfo *Info, bool AppendNewline) {
if (!Val || !Info) return;
if (!Info->Printable && Info->Kind == TypeKind::Custom) {
@@ -387,13 +395,7 @@ void CodeGen::emitOutputValue(Value *Val, const TypeInfo *Info, bool AppendNewli
Args.push_back(Fmt);
Args.push_back(Builder->CreateSelect(BoolVal, TrueStr, FalseStr));
} else if (Info->isString()) {
- Value *StrVal = Val;
- if (StrVal->getType()->isPointerTy()) {
- Value *IsNull = Builder->CreateICmpEQ(StrVal,
- ConstantPointerNull::get(cast<PointerType>(StrVal->getType())),
- "str_is_null");
- StrVal = Builder->CreateSelect(IsNull, EmptyStringStr, StrVal, "safe_str");
- }
+ Value *StrVal = emitStringNullGuard(Val);
Fmt = AppendNewline
? PrintfStringFormatStr
: Builder->CreateGlobalStringPtr("%s", "fmt_str_inline", 0, TheModule.get());
@@ -491,10 +493,7 @@ Value *CodeGen::emitExpr(ExprAST *Expr) {
Value *Loaded = Builder->CreateLoad(TypeInfo->LLVMType, Info->Storage, Var->getName().c_str());
if (TypeInfo->isString()) {
- Value *IsNull = Builder->CreateICmpEQ(Loaded,
- ConstantPointerNull::get(cast<PointerType>(Loaded->getType())),
- "str_is_null");
- Loaded = Builder->CreateSelect(IsNull, EmptyStringStr, Loaded, "safe_var_str");
+ Loaded = emitStringNullGuard(Loaded);
}
return Loaded;
}
@@ -836,11 +835,15 @@ void CodeGen::emitStmt(StmtAST *Stmt) {
if (auto *FuncDef = dynamic_cast<FunctionDefAST*>(Stmt)) {
BasicBlock *SavedBlock = Builder->GetInsertBlock();
+ // Function bodies get a fresh array scope (metadata SSA values belong
+ // to the emitting function), mirroring FunctionGen's Symbols handling.
+ auto SavedArrays = Arrays->exchangeTable({});
FuncGen->emitFunctionDef(FuncDef, [this](StmtAST *S) {
this->emitStmt(S);
});
+ Arrays->exchangeTable(std::move(SavedArrays));
if (SavedBlock) Builder->SetInsertPoint(SavedBlock);
return;
}
diff --git a/lib/CodeGen/TypeSystem.cc b/lib/CodeGen/TypeSystem.cc
index 59dcc18..830ce25 100644
--- a/lib/CodeGen/TypeSystem.cc
+++ b/lib/CodeGen/TypeSystem.cc
@@ -129,6 +129,10 @@ uint64_t TypeSystem::getElementSize(const std::string &TypeName) const {
return Info ? Info->ElementSize : 0;
}
+Constant *TypeSystem::getSizeOfConstant(Type *Ty) const {
+ return ConstantExpr::getSizeOf(Ty);
+}
+
Constant *TypeSystem::getZeroValue(const std::string &TypeName) const {
const TypeInfo *Info = resolve(TypeName);
if (!Info || !Info->LLVMType || Info->LLVMType->isVoidTy()) {