void Resolve::runOnFunction(Function *F) { for (auto &Arg : F->args()) if (!K->Map.add(Arg, F->getEntryBlock())) { DiagnosticPrinter(Arg->getSourceLocation()) << "argument " + Arg->getName() + " attempting to overshadow " "previously bound symbol with " "same name"; } /// For all statements of the form: /// %V = 7; /// ^ /// BindInst /// /// Insert into K->Map for (auto &BB : *F) for (auto &V : *BB) { if (auto B = dyn_cast<BindInst>(V)) if (!K->Map.add(B, BB)) { DiagnosticPrinter(B->getSourceLocation()) << "symbol " + B->getName() + " attempting to overshadow " "previously bound symbol with same " "name"; exit(1); } } /// Resolve operands of all Users: /// %V(...); /// ^ ^---- Operands /// User for (auto &BB : *F) for (auto &V : *BB) resolveOperandsOfUser(cast<User>(V), BB); }
bool ToolInvocation::run() { std::vector<const char*> Argv; for (const std::string &Str : CommandLine) Argv.push_back(Str.c_str()); const char *const BinaryName = Argv[0]; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false); const std::unique_ptr<clang::driver::Driver> Driver( newDriver(&Diagnostics, BinaryName)); // Since the input might only be virtual, don't check whether it exists. Driver->setCheckInputsExist(false); const std::unique_ptr<clang::driver::Compilation> Compilation( Driver->BuildCompilation(llvm::makeArrayRef(Argv))); const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments( &Diagnostics, Compilation.get()); if (CC1Args == NULL) { return false; } std::unique_ptr<clang::CompilerInvocation> Invocation( newInvocation(&Diagnostics, *CC1Args)); for (const auto &It : MappedFileContents) { // Inject the code as the given file name into the preprocessor options. auto *Input = llvm::MemoryBuffer::getMemBuffer(It.getValue()); Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(), Input); } return runInvocation(BinaryName, Compilation.get(), Invocation.release()); }
llvm::Constant *Function::toLL(llvm::Module *M) { auto K = getContext(); auto CurrentFunction = getOrInsert(M); /// Bind argument symbols to function argument values in symbol table auto ArgList = getArguments(); auto S = ArgList.begin(); for (auto &Arg : CurrentFunction->args()) { auto SourceLoc = (*S)->getSourceLocation(); if (!K->Map.add(*S, &Arg)) DiagnosticPrinter(SourceLoc) << "argument " + (*S)->getName() + " conflicts with existing symbol name"; ++S; } // Add function symbol to symbol table, global scope K->Map.add(this, CurrentFunction); /// Codegens all blocks getEntryBlock()->toLL(M); auto ExitBlock = getExitBlock(); if (!ExitBlock->size() || !isa<ReturnInst>(ExitBlock->back())) K->Builder->CreateRet(nullptr); return CurrentFunction; }
Type *TypeInfer::visit(Argument *V) { if (!V->isUnTyped()) return V->getType(); DiagnosticPrinter(V->getSourceLocation()) << "untyped argument " + V->getName(); exit(1); }
bool ToolInvocation::run() { std::vector<const char*> Argv; for (int I = 0, E = CommandLine.size(); I != E; ++I) Argv.push_back(CommandLine[I].c_str()); const char *const BinaryName = Argv[0]; DiagnosticOptions DefaultDiagnosticOptions; TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), DefaultDiagnosticOptions); DiagnosticsEngine Diagnostics(llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs>( new DiagnosticIDs()), &DiagnosticPrinter, false); const llvm::OwningPtr<clang::driver::Driver> Driver( newDriver(&Diagnostics, BinaryName)); // Since the input might only be virtual, don't check whether it exists. Driver->setCheckInputsExist(false); const llvm::OwningPtr<clang::driver::Compilation> Compilation( Driver->BuildCompilation(llvm::makeArrayRef(Argv))); const clang::driver::ArgStringList *const CC1Args = getCC1Arguments( &Diagnostics, Compilation.get()); if (CC1Args == NULL) { return false; } llvm::OwningPtr<clang::CompilerInvocation> Invocation( newInvocation(&Diagnostics, *CC1Args)); return runInvocation(BinaryName, Compilation.get(), Invocation.take(), *CC1Args, ToolAction.take()); }
Type *TypeInfer::visit(LoadInst *V) { V->setType(V->getVal()->getType()); if (!V->isUnTyped()) return V->getType(); auto Name = V->getVal()->getName(); DiagnosticPrinter(V->getSourceLocation()) << "untyped symbol " + Name; exit(1); }
void Resolve::lookupReplaceUse(UnresolvedValue *V, Use &U, BasicBlock *Block) { auto Name = V->getName(); auto K = V->getContext(); if (auto S = K->Map.get(V, Block)) { /// %S = 2; /// ^ /// Came from here (MallocInst, Argument, or Prototype) /// /// Foo(%S); /// ^ /// UnresolvedValue; replace with %Replacement if (auto M = dyn_cast<MallocInst>(S)) { if (dyn_cast<StoreInst>(U->getUser())) U.set(M); else { auto Replacement = LoadInst::get(M); Replacement->setSourceLocation(V->getSourceLocation()); U.set(Replacement); } } else if (isa<BindInst>(S) || isa<Argument>(S)) { U.set(S); } else if (isa<Prototype>(S)) { auto Replacement = Pointer::get(S); Replacement->setSourceLocation(S->getSourceLocation()); U.set(Replacement); } } else { /// %V was not seen earlier (%S not initialized) /// Only one possibility: %V(...) /// ^ /// Callee of CallInst auto SourceLoc = U->getSourceLocation(); if (auto Inst = dyn_cast<CallInst>(U->getUser())) if (Inst->getCallee() == V) { DiagnosticPrinter(SourceLoc) << "unbound function " + Name; exit(1); } DiagnosticPrinter(SourceLoc) << "unbound symbol " + Name; exit(1); } }
FunctionType *TypeInfer::followFcnPointers(Value *Callee, Location Loc) { if (auto FcnTy = followFcnPointer(Callee->getType())) { while (auto DeeperFcn = followFcnPointer(FcnTy->getRTy())) FcnTy = DeeperFcn; return FcnTy; } std::ostringstream ErrMsg; ErrMsg << Callee->getName() << " was expected to be a pointer to a function" << " but was instead found to be of type " << *Callee->getType(); DiagnosticPrinter(Loc) << ErrMsg.str(); exit(1); }
void Resolve::runOnModule(Module *M) { K = M->getContext(); for (auto P : Externals::get(K)->getProtos()) if (!K->Map.add(P)) { auto ErrMsg = "prototype " + P->getName() + " attempting to overshadow previously bound symbol with same name"; DiagnosticPrinter(P->getSourceLocation()) << ErrMsg; exit(1); } for (auto &F : *M) if (!K->Map.add(F)) { DiagnosticPrinter(F->getSourceLocation()) << "function " + F->getName() + " attempting to overshadow " "previously bound symbol with same " "name"; exit(1); } for (auto &F : *M) runOnFunction(F); }
Type *TypeInfer::visit(ReturnInst *V) { if (!V->getVal()) return VoidType::get(K); auto Val = V->getVal(); auto Ty = visit(Val); if (isa<VoidType>(Ty)) { auto CannotReturnVoid = "cannot return expression of Void type"; DiagnosticPrinter(Val->getSourceLocation()) << CannotReturnVoid; exit(1); } V->setType(Ty); return Ty; }
Type *TypeInfer::visit(IfInst *V) { auto TrueTy = visit(V->getTrueBB()); auto FalseTy = visit(V->getFalseBB()); if (TrueTy != FalseTy) { std::ostringstream ErrMsg; ErrMsg << "mismatched types: true block is inferred to be of type " << *TrueTy << " and false block is inferred to be of type " << *FalseTy; DiagnosticPrinter(V->getSourceLocation()) << ErrMsg.str(); exit(1); } V->setType(TrueTy); return TrueTy; }
bool ToolInvocation::run() { std::vector<const char*> Argv; for (const std::string &Str : CommandLine) Argv.push_back(Str.c_str()); const char *const BinaryName = Argv[0]; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); TextDiagnosticPrinter DiagnosticPrinter( llvm::errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false); const std::unique_ptr<clang::driver::Driver> Driver( newDriver(&Diagnostics, BinaryName, Files->getVirtualFileSystem())); // Since the input might only be virtual, don't check whether it exists. Driver->setCheckInputsExist(false); const std::unique_ptr<clang::driver::Compilation> Compilation( Driver->BuildCompilation(llvm::makeArrayRef(Argv))); // Just print the cc1 options if -### was present. if (Compilation->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) { Compilation->getJobs().Print(llvm::errs(), "\n", true); return true; } // We expect to get back a command job. If there is no job // everything was handled by the driver. const driver::JobList &Jobs = Compilation->getJobs(); if (Jobs.size() == 0) return true; const llvm::opt::ArgStringList *const CC1Args = getCC1Arguments( &Diagnostics, Compilation.get()); if (!CC1Args) { return false; } std::unique_ptr<clang::CompilerInvocation> Invocation( newInvocation(&Diagnostics, *CC1Args)); if(Diagnostics.hasUncompilableErrorOccurred()) return false; // FIXME: remove this when all users have migrated! for (const auto &It : MappedFileContents) { // Inject the code as the given file name into the preprocessor options. std::unique_ptr<llvm::MemoryBuffer> Input = llvm::MemoryBuffer::getMemBuffer(It.getValue()); Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(), Input.release()); } return runInvocation(BinaryName, Compilation.get(), Invocation.release(), PCHContainerOps); }
void TypeInfer::verifyArity(CallInst *V, FunctionType *Ty) { std::vector<Type *> OpTys; for (auto Op : V->operands()) OpTys.push_back(Op->getType()); auto ATys = Ty->getATys(); unsigned OpSize = OpTys.size(); unsigned Arity = ATys.size(); if (OpSize != Arity) { std::ostringstream ErrMsg; ErrMsg << "Call expected " << Arity << " number of arguments, but has been supplied " << OpSize << " arguments"; DiagnosticPrinter(V->getSourceLocation()) << ErrMsg.str(); exit(1); } }
int RefactoringTool::run(FrontendActionFactory *ActionFactory) { int Result = Tool.run(ActionFactory); LangOptions DefaultLangOptions; DiagnosticOptions DefaultDiagnosticOptions; TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), DefaultDiagnosticOptions); DiagnosticsEngine Diagnostics( llvm::IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &DiagnosticPrinter, false); SourceManager Sources(Diagnostics, Tool.getFiles()); Rewriter Rewrite(Sources, DefaultLangOptions); if (!applyAllReplacements(Replace, Rewrite)) { llvm::errs() << "Skipped some replacements.\n"; } if (!saveRewrittenFiles(Rewrite)) { llvm::errs() << "Could not save rewritten files.\n"; return 1; } return Result; }
int RefactoringTool::runAndSave(FrontendActionFactory *ActionFactory) { if (int Result = run(ActionFactory)) { return Result; } LangOptions DefaultLangOptions; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); TextDiagnosticPrinter DiagnosticPrinter(llvm::errs(), &*DiagOpts); DiagnosticsEngine Diagnostics( IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts, &DiagnosticPrinter, false); SourceManager Sources(Diagnostics, getFiles()); Rewriter Rewrite(Sources, DefaultLangOptions); if (!applyAllReplacements(Rewrite)) { llvm::errs() << "Skipped some replacements.\n"; } return saveRewrittenFiles(Rewrite); }
llvm::Function *Prototype::getOrInsert(llvm::Module *M) { auto FnTy = cast<llvm::FunctionType>(type()->generate(M)); auto MangledName = getMangledName(); /// getOrInsertFunction:: /// /// Look up the specified function in the module symbol table. /// Four possibilities: /// 1. If it does not exist, add a prototype for the function and return it. /// 2. If it exists, and has a local linkage, the existing function is /// renamed and a new one is inserted. /// 3. Otherwise, if the existing function has the correct prototype, return /// the existing function. /// 4. Finally, the function exists but has the wrong prototype: return the /// function with a constantexpr cast to the right prototype. auto Const = M->getOrInsertFunction(MangledName, FnTy); if (auto FunctionCandidate = dyn_cast<llvm::Function>(Const)) return FunctionCandidate; auto Error = MangledName + " was declared with different signature earlier"; DiagnosticPrinter(SourceLoc) << Error; exit(1); }
friend ostream &operator<<(ostream &Stream, const Type &T) { auto DiagStream = DiagnosticPrinter(Stream); T.print(DiagStream); return Stream; }