diff options
Diffstat (limited to 'lib/CodeGen')
| -rw-r--r-- | lib/CodeGen/ArrayHandler.cc | 4 | ||||
| -rw-r--r-- | lib/CodeGen/Builtins.h | 3 | ||||
| -rw-r--r-- | lib/CodeGen/CTypeGen.cc | 6 | ||||
| -rw-r--r-- | lib/CodeGen/CodeGen.cc | 6 | ||||
| -rw-r--r-- | lib/CodeGen/ConstantGen.cc | 2 | ||||
| -rw-r--r-- | lib/CodeGen/ControlFlowGen.cc | 3 | ||||
| -rw-r--r-- | lib/CodeGen/Designator.cc | 3 | ||||
| -rw-r--r-- | lib/CodeGen/ExpressionGen.cc | 5 | ||||
| -rw-r--r-- | lib/CodeGen/FunctionGen.cc | 58 | ||||
| -rw-r--r-- | lib/CodeGen/StatementGen.cc | 1 | ||||
| -rw-r--r-- | lib/CodeGen/TypeCheckGen.cc | 7 | ||||
| -rw-r--r-- | lib/CodeGen/TypeSystem.cc | 6 |
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; } |
