aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/ArrayHandler.cc4
-rw-r--r--lib/CodeGen/Builtins.h3
-rw-r--r--lib/CodeGen/CTypeGen.cc6
-rw-r--r--lib/CodeGen/CodeGen.cc6
-rw-r--r--lib/CodeGen/ConstantGen.cc2
-rw-r--r--lib/CodeGen/ControlFlowGen.cc3
-rw-r--r--lib/CodeGen/Designator.cc3
-rw-r--r--lib/CodeGen/ExpressionGen.cc5
-rw-r--r--lib/CodeGen/FunctionGen.cc58
-rw-r--r--lib/CodeGen/StatementGen.cc1
-rw-r--r--lib/CodeGen/TypeCheckGen.cc7
-rw-r--r--lib/CodeGen/TypeSystem.cc6
12 files changed, 62 insertions, 42 deletions
diff --git a/lib/CodeGen/ArrayHandler.cc b/lib/CodeGen/ArrayHandler.cc
index 40a330f..5eb8a52 100644
--- a/lib/CodeGen/ArrayHandler.cc
+++ b/lib/CodeGen/ArrayHandler.cc
@@ -12,7 +12,7 @@ using namespace cps;
ArrayHandler::ArrayHandler(LLVMContext &C,
IRBuilder<> &B,
Module &M,
- std::map<std::string, SymbolInfo> &Sym,
+ IdentifierMap<SymbolInfo> &Sym,
TypeSystem &TS,
RuntimeCheck &RC)
: TheContext(&C),
@@ -253,7 +253,7 @@ Value *ArrayHandler::emitElementAddress(ArrayAccessExprAST *Expr,
CG, ElemTypeNameOut);
}
-std::map<std::string, ArrayMetadata> ArrayHandler::exchangeTable(std::map<std::string, ArrayMetadata> NewTable) {
+IdentifierMap<ArrayMetadata> ArrayHandler::exchangeTable(IdentifierMap<ArrayMetadata> NewTable) {
std::swap(ArrayTable, NewTable);
return NewTable;
}
diff --git a/lib/CodeGen/Builtins.h b/lib/CodeGen/Builtins.h
index 34e36a9..e7f60e4 100644
--- a/lib/CodeGen/Builtins.h
+++ b/lib/CodeGen/Builtins.h
@@ -1,4 +1,5 @@
#pragma once
+#include "cps/Identifier.h"
#include <string>
namespace cps::detail {
@@ -29,7 +30,7 @@ inline constexpr BuiltinInfo Builtins[] = {
inline const BuiltinInfo *findBuiltin(const std::string &Name) {
for (const auto &B : Builtins) {
- if (Name == B.Name) return &B;
+ if (sameIdentifier(Name, B.Name)) return &B;
}
return nullptr;
}
diff --git a/lib/CodeGen/CTypeGen.cc b/lib/CodeGen/CTypeGen.cc
index a20306e..80a7d3b 100644
--- a/lib/CodeGen/CTypeGen.cc
+++ b/lib/CodeGen/CTypeGen.cc
@@ -81,7 +81,7 @@ Value *CodeGen::emitCast(CastExprAST *Cast) {
Value *CodeGen::emitCBinaryOp(int Op, Value *L, const TypeInfo *Left,
Value *R, const TypeInfo *Right, int Line) {
if (!Left || !Right || !Left->isC() || !Right->isC()) {
- reportError("C and pseudocode operands require an explicit cast (line %d)", Line);
+ reportError("C and pseudocode operands require an explicit cast");
return nullptr;
}
if (Left->isPointer() || Right->isPointer()) {
@@ -99,7 +99,7 @@ Value *CodeGen::emitCBinaryOp(int Op, Value *L, const TypeInfo *Left,
return nullptr;
}
if (Op == '&' || ((Op == tok_div || Op == tok_mod) && !Common->isIntegral())) {
- reportError("Operator is not supported for these C operand types (line %d)", Line);
+ reportError("Operator is not supported for these C operand types");
return nullptr;
}
if (Op == tok_and || Op == tok_or) {
@@ -154,7 +154,7 @@ Value *CodeGen::emitCBinaryOp(int Op, Value *L, const TypeInfo *Left,
: Builder->CreateICmpUGE(L, R, "c_ge");
}
}
- reportError("Unsupported operator for C operands (line %d)", Line);
+ reportError("Unsupported operator for C operands");
return nullptr;
}
diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc
index b793657..dff4009 100644
--- a/lib/CodeGen/CodeGen.cc
+++ b/lib/CodeGen/CodeGen.cc
@@ -24,6 +24,7 @@ void CodeGen::reportError(const char *Fmt, ...) {
va_start(Args, Fmt);
fprintf(stderr, "error: ");
vfprintf(stderr, Fmt, Args);
+ if (DiagnosticLine) fprintf(stderr, " at line %d", DiagnosticLine);
fprintf(stderr, "\n");
va_end(Args);
HadError = true;
@@ -51,7 +52,7 @@ CodeGen::CodeGen() {
*Types,
*Exceptions,
Symbols,
- HadError);
+ HadError, DiagnosticLine);
ArithHandler = std::make_unique<ArithmeticHandler>(*TheContext, *Builder, HadError,
*RuntimeChecker);
@@ -158,12 +159,14 @@ void CodeGen::compile(const std::vector<std::unique_ptr<StmtAST>> &Statements) {
// Pre-register every top-level FUNCTION/PROCEDURE prototype so calls may
// precede definitions.
for (const auto &Stmt : Statements) {
+ SaveAndRestore<int> Location(DiagnosticLine, Stmt->getLine());
if (auto *FuncDef = dynamic_cast<FunctionDefAST*>(Stmt.get())) {
FuncGen->emitPrototype(FuncDef->getProto());
}
}
for (const auto &Stmt : Statements) {
+ SaveAndRestore<int> Location(DiagnosticLine, Stmt->getLine());
emitStmt(Stmt.get());
}
@@ -197,6 +200,7 @@ bool CodeGen::marshalCallArgs(const std::string &Callee,
const std::vector<std::unique_ptr<ExprAST>> &ArgExprs,
int Line,
std::vector<Value*> &Out) {
+ SaveAndRestore<int> Location(DiagnosticLine, Line ? Line : DiagnosticLine);
const FuncSig *Sig = FuncGen->getSignature(Callee);
if (!Sig) {
reportError("Call to undefined function %s", Callee.c_str());
diff --git a/lib/CodeGen/ConstantGen.cc b/lib/CodeGen/ConstantGen.cc
index e9f81ae..e14e22f 100644
--- a/lib/CodeGen/ConstantGen.cc
+++ b/lib/CodeGen/ConstantGen.cc
@@ -19,7 +19,7 @@ bool CodeGen::prepareSymbolDeclaration(const std::string &Name, bool IsConstant)
auto &Scope = ConstantScopes.back();
auto It = Symbols.find(Name);
if (It != Symbols.end()) {
- if ((IsConstant || It->second.ConstantValue) && It->second.ScopeID == Scope.ID) {
+ if (It->second.ScopeID == Scope.ID) {
reportError("Declaration of %s conflicts with an existing declaration in this scope", Name.c_str());
return false;
}
diff --git a/lib/CodeGen/ControlFlowGen.cc b/lib/CodeGen/ControlFlowGen.cc
index d34f640..17f43f2 100644
--- a/lib/CodeGen/ControlFlowGen.cc
+++ b/lib/CodeGen/ControlFlowGen.cc
@@ -190,6 +190,7 @@ void CodeGen::emitCaseStmt(CaseStmtAST *Stmt) {
auto *After = BasicBlock::Create(*TheContext, "case_cont", F);
auto SavedArrays = Arrays->snapshotTable();
for (const auto &Branch : Stmt->getBranches()) {
+ SaveAndRestore<int> Location(DiagnosticLine, Branch.Line);
auto *Body = BasicBlock::Create(*TheContext, "case_body", F);
auto *Next = BasicBlock::Create(*TheContext, "case_next", F);
auto Compare = [&](int Op, ExprAST *Label) -> Value * {
@@ -199,7 +200,7 @@ void CodeGen::emitCaseStmt(CaseStmtAST *Stmt) {
}
const TypeInfo *LabelType = getExprTypeInfo(Label);
if (!LabelType) {
- reportError("Cannot determine CASE label type at line %d", Branch.Line);
+ reportError("Cannot determine CASE label type");
return nullptr;
}
Value *LabelValue = emitExpr(Label);
diff --git a/lib/CodeGen/Designator.cc b/lib/CodeGen/Designator.cc
index afaf0a4..fcc6919 100644
--- a/lib/CodeGen/Designator.cc
+++ b/lib/CodeGen/Designator.cc
@@ -15,6 +15,7 @@ void CodeGen::runTypePrePass(const std::vector<std::unique_ptr<StmtAST>> &Statem
std::string Err;
for (const auto &S : Statements) {
+ SaveAndRestore<int> Location(DiagnosticLine, S->getLine());
bool Ok = true;
if (auto *C = dynamic_cast<CTypeDeclAST*>(S.get()))
Ok = Types->defineCAlias(C->getName(), C->getExpression(), Err);
@@ -28,6 +29,7 @@ void CodeGen::runTypePrePass(const std::vector<std::unique_ptr<StmtAST>> &Statem
}
for (const auto &S : Statements) {
+ SaveAndRestore<int> Location(DiagnosticLine, S->getLine());
bool Ok = true;
if (auto *E = dynamic_cast<EnumTypeDeclAST*>(S.get())) {
Ok = Types->defineEnum(E->getName(), E->getValueNames(), Err);
@@ -44,6 +46,7 @@ void CodeGen::runTypePrePass(const std::vector<std::unique_ptr<StmtAST>> &Statem
// of its storage plus the type name stored there. Array indexing goes through
// ArrayHandler's checked pipeline; dereferences emit the null-pointer check.
bool CodeGen::emitLValue(ExprAST *E, LValueInfo &Out) {
+ SaveAndRestore<int> Location(DiagnosticLine, E && E->getLine() ? E->getLine() : DiagnosticLine);
if (auto *Var = dynamic_cast<VariableExprAST*>(E)) {
const SymbolInfo *Info = getSymbolInfo(Var->getName());
if (!Info) {
diff --git a/lib/CodeGen/ExpressionGen.cc b/lib/CodeGen/ExpressionGen.cc
index f3dadb7..b3655fd 100644
--- a/lib/CodeGen/ExpressionGen.cc
+++ b/lib/CodeGen/ExpressionGen.cc
@@ -11,6 +11,7 @@ using namespace cps;
using namespace cps::detail;
Value *CodeGen::emitExpr(ExprAST *Expr) {
+ SaveAndRestore<int> Location(DiagnosticLine, Expr && Expr->getLine() ? Expr->getLine() : DiagnosticLine);
if (auto *Cast = dynamic_cast<CastExprAST*>(Expr)) return emitCast(Cast);
if (!Expr) return nullptr;
@@ -126,6 +127,7 @@ Value *CodeGen::emitExpr(ExprAST *Expr) {
if (auto *Call = dynamic_cast<CallExprAST*>(Expr)) {
std::string Name = Call->getCallee();
if (const BuiltinInfo *B = findBuiltin(Name)) {
+ Name = B->Name;
if (Call->getArgs().size() != B->Arity) {
reportError("%s expects %u arg%s", B->Name, B->Arity, B->Arity == 1 ? "" : "s");
return nullptr;
@@ -247,6 +249,7 @@ Value *CodeGen::emitExpr(ExprAST *Expr) {
// Ordinary binary expressions and CASE use the same typed operations.
Value *CodeGen::emitBinaryOp(int Op, Value *L, const TypeInfo *LT,
Value *R, const TypeInfo *RT, int Line) {
+ SaveAndRestore<int> Location(DiagnosticLine, Line ? Line : DiagnosticLine);
if (!L || !R) return nullptr;
if ((LT && LT->isC()) || (RT && RT->isC()))
return emitCBinaryOp(Op, L, LT, R, RT, Line);
@@ -261,7 +264,7 @@ Value *CodeGen::emitBinaryOp(int Op, Value *L, const TypeInfo *LT,
case tok_eq: case tok_ne: case '<': case '>': case tok_le: case tok_ge:
if ((LT && LT->isString()) || (RT && RT->isString())) {
if (!(LT && LT->isString() && RT && RT->isString())) {
- reportError("STRING comparison requires two STRING operands (line %d)", Line);
+ reportError("STRING comparison requires two STRING operands");
return nullptr;
}
return StrHandler->emitCompare(Op, L, R);
diff --git a/lib/CodeGen/FunctionGen.cc b/lib/CodeGen/FunctionGen.cc
index 957a1f5..a155f60 100644
--- a/lib/CodeGen/FunctionGen.cc
+++ b/lib/CodeGen/FunctionGen.cc
@@ -2,6 +2,7 @@
#include "cps/CodeGen.h"
#include "cps/ExceptionHandler.h"
#include <cstdio>
+#include <cstdarg>
using namespace llvm;
using namespace cps;
@@ -19,16 +20,26 @@ static bool isReservedRuntimeName(const std::string &Name) {
"__gxx_personality_seh0", "__gxx_personality_sj0", "_Unwind_Resume", "_ZTIi",
};
for (const char *R : Reserved) {
- if (Name == R) return true;
+ if (sameIdentifier(Name, R)) return true;
}
return false;
}
+void FunctionGen::reportError(const char *Fmt, ...) {
+ va_list Args;
+ va_start(Args, Fmt);
+ fprintf(stderr, "error: ");
+ vfprintf(stderr, Fmt, Args);
+ if (DiagnosticLine) fprintf(stderr, " at line %d", DiagnosticLine);
+ fprintf(stderr, "\n");
+ va_end(Args);
+ HadError = true;
+}
+
Type *FunctionGen::getLLVMType(const std::string &TypeName) {
Type *Resolved = Types.getLLVMType(TypeName);
if (!Resolved) {
- fprintf(stderr, "error: Unknown type %s\n", TypeName.c_str());
- HadError = true;
+ reportError("Unknown type %s", TypeName.c_str());
return Type::getInt64Ty(Context);
}
return Resolved;
@@ -38,12 +49,10 @@ void FunctionGen::createArgumentAllocas(Function *F, const std::vector<ParamDecl
Function::arg_iterator AI = F->arg_begin();
for (const ParamDecl &P : Params) {
if (Types.lookupEnumConstant(P.Name)) {
- fprintf(stderr, "error: parameter '%s' collides with an enum value\n", P.Name.c_str());
- HadError = true;
+ reportError("parameter '%s' collides with an enum value", P.Name.c_str());
}
if (Types.resolve(P.Name)) {
- fprintf(stderr, "error: parameter '%s' collides with a type name\n", P.Name.c_str());
- HadError = true;
+ reportError("parameter '%s' collides with a type name", P.Name.c_str());
}
Value *ArgVal = &(*AI);
++AI;
@@ -88,39 +97,35 @@ const FuncSig *FunctionGen::getSignature(const std::string &Name) const {
Function *FunctionGen::emitPrototype(PrototypeAST *Proto) {
if (isReservedRuntimeName(Proto->getName())) {
- fprintf(stderr, "error: '%s' is a reserved runtime symbol and cannot be a FUNCTION/PROCEDURE name\n",
+ reportError("'%s' is a reserved runtime symbol and cannot be a FUNCTION/PROCEDURE name",
Proto->getName().c_str());
- HadError = true;
return nullptr;
}
if (CodeGen::isBuiltinName(Proto->getName())) {
- fprintf(stderr, "error: '%s' is a built-in function and cannot be redefined\n",
+ reportError("'%s' is a built-in function and cannot be redefined",
Proto->getName().c_str());
- HadError = true;
return nullptr;
}
if (Types.lookupEnumConstant(Proto->getName())) {
- fprintf(stderr, "error: '%s' is an enum value and cannot be a FUNCTION/PROCEDURE name\n",
+ reportError("'%s' is an enum value and cannot be a FUNCTION/PROCEDURE name",
Proto->getName().c_str());
- HadError = true;
return nullptr;
}
if (Types.resolve(Proto->getName())) {
- fprintf(stderr, "error: '%s' is a type name and cannot be a FUNCTION/PROCEDURE name\n",
+ reportError("'%s' is a type name and cannot be a FUNCTION/PROCEDURE name",
Proto->getName().c_str());
- HadError = true;
return nullptr;
}
FuncSig Sig;
+ Sig.Name = Proto->getName();
Sig.ReturnTypeName = Proto->getReturnType();
std::vector<Type*> ArgTypes;
for (const ParamDecl &P : Proto->getParams()) {
const TypeInfo *Info = Types.resolve(P.TypeName);
if (Info && Info->isVoid()) {
- fprintf(stderr, "error: parameter %s cannot have void type\n", P.Name.c_str());
- HadError = true;
+ reportError("parameter %s cannot have void type", P.Name.c_str());
return nullptr;
}
ParamSig PS;
@@ -148,11 +153,11 @@ Function *FunctionGen::emitPrototype(PrototypeAST *Proto) {
Type *RetType = getLLVMType(Proto->getReturnType());
FunctionType *FT = FunctionType::get(RetType, ArgTypes, false);
- Function *F = Module.getFunction(Proto->getName());
+ const FuncSig *Existing = getSignature(Proto->getName());
+ Function *F = Module.getFunction(Existing ? Existing->Name : Proto->getName());
if (F && F->getFunctionType() != FT) {
- fprintf(stderr, "error: Function %s conflicts with an existing declaration of a different type\n",
+ reportError("Function %s conflicts with an existing declaration of a different type",
Proto->getName().c_str());
- HadError = true;
return nullptr;
}
if (!F) {
@@ -184,15 +189,14 @@ Function *FunctionGen::emitFunctionDef(FunctionDefAST *FuncAST,
if (!TheFunction) return nullptr;
if (!TheFunction->empty()) {
- fprintf(stderr, "error: Function %s cannot be redefined.\n", Proto->getName().c_str());
- HadError = true;
+ reportError("Function %s cannot be redefined.", Proto->getName().c_str());
return nullptr;
}
BasicBlock *BB = BasicBlock::Create(Context, "entry", TheFunction);
Builder.SetInsertPoint(BB);
- std::map<std::string, SymbolInfo> OldSymbols = Symbols;
+ IdentifierMap<SymbolInfo> OldSymbols = Symbols;
Symbols.clear();
for (const auto &[Name, Info] : OldSymbols) {
if (Info.ConstantValue && Info.ScopeID == 0) Symbols.emplace(Name, Info);
@@ -209,7 +213,7 @@ Function *FunctionGen::emitFunctionDef(FunctionDefAST *FuncAST,
}
if (!Builder.GetInsertBlock()->hasTerminator()) {
- if (Proto->getReturnType() == "VOID") {
+ if (sameIdentifier(Proto->getReturnType(), "VOID")) {
Builder.CreateRetVoid();
} else {
Builder.CreateRet(Constant::getNullValue(TheFunction->getReturnType()));
@@ -240,11 +244,13 @@ static Value *GenerateCall(llvm::Module &Module,
}
llvm::Value *FunctionGen::emitCallExpr(CallExprAST *Call, const std::vector<llvm::Value*> &Args) {
- return GenerateCall(Module, Exceptions, Call->getCallee(), Args, HadError);
+ const FuncSig *Sig = getSignature(Call->getCallee());
+ return GenerateCall(Module, Exceptions, Sig ? Sig->Name : Call->getCallee(), Args, HadError);
}
void FunctionGen::emitCallStmt(CallStmtAST *Call, const std::vector<llvm::Value*> &Args) {
- GenerateCall(Module, Exceptions, Call->getCallee(), Args, HadError);
+ const FuncSig *Sig = getSignature(Call->getCallee());
+ GenerateCall(Module, Exceptions, Sig ? Sig->Name : Call->getCallee(), Args, HadError);
}
void FunctionGen::emitReturn(ReturnStmtAST *Ret, llvm::Value *RetVal) {
diff --git a/lib/CodeGen/StatementGen.cc b/lib/CodeGen/StatementGen.cc
index 8907cfa..3ea0670 100644
--- a/lib/CodeGen/StatementGen.cc
+++ b/lib/CodeGen/StatementGen.cc
@@ -9,6 +9,7 @@ using namespace llvm;
using namespace cps;
void CodeGen::emitStmt(StmtAST *Stmt) {
+ SaveAndRestore<int> Location(DiagnosticLine, Stmt && Stmt->getLine() ? Stmt->getLine() : DiagnosticLine);
if (!Stmt) return;
if (auto *FuncDef = dynamic_cast<FunctionDefAST*>(Stmt)) {
diff --git a/lib/CodeGen/TypeCheckGen.cc b/lib/CodeGen/TypeCheckGen.cc
index 654afc8..690d005 100644
--- a/lib/CodeGen/TypeCheckGen.cc
+++ b/lib/CodeGen/TypeCheckGen.cc
@@ -33,6 +33,7 @@ std::string opToText(int Op) {
// LLVM level); builtin targets additionally reject user-kind sources, then
// keep the existing representation coercions unchanged.
Value *CodeGen::emitCoercedExpr(ExprAST *E, const TypeInfo *Target) {
+ SaveAndRestore<int> Location(DiagnosticLine, E && E->getLine() ? E->getLine() : DiagnosticLine);
if (!E || !Target) return nullptr;
// A whole-array reference evaluates to its raw data pointer, and
@@ -94,7 +95,7 @@ Value *CodeGen::emitCoercedExpr(ExprAST *E, const TypeInfo *Target) {
}
return nullptr;
}
- if (Src->Name != Target->Name) {
+ if (!Src->sameType(Target)) {
reportError("Cannot use a value of type %s where %s is expected",
Src->Name.c_str(), Target->Name.c_str());
return nullptr;
@@ -133,7 +134,7 @@ Value *CodeGen::emitUserKindBinaryOp(int Op, Value *L, const TypeInfo *LT,
}
if ((LT && LT->isPointer()) || (RT && RT->isPointer())) {
- bool SameName = LT && RT && LT->isPointer() && RT->isPointer() && LT->Name == RT->Name;
+ bool SameName = LT && RT && LT->isPointer() && RT->isPointer() && LT->sameType(RT);
if (SameName && (Op == tok_eq || Op == tok_ne)) {
return Op == tok_eq ? Builder->CreateICmpEQ(L, R, "ptr_eq")
: Builder->CreateICmpNE(L, R, "ptr_ne");
@@ -144,7 +145,7 @@ Value *CodeGen::emitUserKindBinaryOp(int Op, Value *L, const TypeInfo *LT,
}
// At least one enum operand from here on.
- bool BothSameEnum = LT && RT && LT->isEnum() && RT->isEnum() && LT->Name == RT->Name;
+ bool BothSameEnum = LT && RT && LT->isEnum() && RT->isEnum() && LT->sameType(RT);
switch (Op) {
case tok_eq: case tok_ne: case '<': case '>': case tok_le: case tok_ge: {
diff --git a/lib/CodeGen/TypeSystem.cc b/lib/CodeGen/TypeSystem.cc
index a837c9a..f4620dc 100644
--- a/lib/CodeGen/TypeSystem.cc
+++ b/lib/CodeGen/TypeSystem.cc
@@ -12,12 +12,12 @@ bool TypeInfo::sameType(const TypeInfo *Other) const {
if (!Other) return false;
if (isC() || Other->isC())
return isC() && Other->isC() && CIdentity == Other->CIdentity;
- return Name == Other->Name;
+ return sameIdentifier(Name, Other->Name);
}
const RecordFieldInfo *RecordPayload::findField(const std::string &Name) const {
for (const auto &F : Fields) {
- if (F.first == Name) return &F.second;
+ if (sameIdentifier(F.first, Name)) return &F.second;
}
return nullptr;
}
@@ -172,7 +172,7 @@ bool TypeSystem::defineEnum(const std::string &Name,
for (size_t I = 0; I < Values.size(); ++I) {
const std::string &V = Values[I];
for (size_t J = 0; J < I; ++J) {
- if (Values[J] == V) {
+ if (sameIdentifier(Values[J], V)) {
Err = "Duplicate value '" + V + "' in enum " + Name;
return false;
}