[PATCH] TableGen backend to generate an index in ctags(1) format.
Kevin Schoedel
kevin.p.schoedel at intel.com
Fri Mar 15 11:49:47 PDT 2013
TableGen backend to generate an index in ctags(1) format.
Example use:
$ cd $SRCDIR/lib/Target/$TARGET
$ llvm-tblgen -I=../../../include --gen-ctags $TGT.td >tags
To use this in conjunction with exuberant ctags to generate a single
combined tags file, run tblgen first and then
$ ctags --append [...]
Since some identifiers have corresponding definitions in C++ code,
it can be useful (if using vim) to also use cscope, and
:set cscopetagorder=1
so that
:tag X
will preferentially select the tablegen symbol, while
:cscope find g X
will always find the C++ symbol.
http://llvm-reviews.chandlerc.com/D546
Files:
utils/TableGen/CMakeLists.txt
utils/TableGen/CTagsEmitter.cpp
utils/TableGen/TableGen.cpp
utils/TableGen/TableGenBackends.h
Index: utils/TableGen/CMakeLists.txt
===================================================================
--- utils/TableGen/CMakeLists.txt
+++ utils/TableGen/CMakeLists.txt
@@ -33,4 +33,5 @@
X86DisassemblerTables.cpp
X86ModRMFilters.cpp
X86RecognizableInstr.cpp
+ CTagsEmitter.cpp
)
Index: utils/TableGen/CTagsEmitter.cpp
===================================================================
--- /dev/null
+++ utils/TableGen/CTagsEmitter.cpp
@@ -0,0 +1,104 @@
+//===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits an index of definitions in ctags(1) format.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "ctags-emitter"
+
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+using namespace llvm;
+
+namespace llvm {
+extern SourceMgr SrcMgr;
+}
+
+namespace {
+
+class Tag {
+private:
+ const std::string *Id;
+ SMLoc Loc;
+public:
+ Tag(const std::string &Name, const SMLoc Location):
+ Id(&Name), Loc(Location)
+ {}
+ int operator<(const Tag &B) const {
+ return *Id < *B.Id;
+ }
+ void emit(raw_ostream &OS) const {
+ int BufferID = SrcMgr.FindBufferContainingLoc(Loc);
+ MemoryBuffer *CurMB = SrcMgr.getBufferInfo(BufferID).Buffer;
+ const char *BufferName = CurMB->getBufferIdentifier();
+ std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc);
+ OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n";
+ }
+};
+
+class CTagsEmitter {
+private:
+ RecordKeeper &Records;
+public:
+ CTagsEmitter(RecordKeeper &R):
+ Records(R)
+ {}
+
+ void run(raw_ostream &OS);
+
+private:
+ static SMLoc locate(const Record *R);
+};
+
+} // End anonymous namespace.
+
+SMLoc CTagsEmitter::locate(const Record *R) {
+ ArrayRef<SMLoc> Locs = R->getLoc();
+ if (Locs.empty()) {
+ SMLoc NullLoc;
+ return NullLoc;
+ }
+ return Locs.front();
+}
+
+void CTagsEmitter::run(raw_ostream &OS) {
+ const std::map<std::string, Record*> &Classes = Records.getClasses();
+ const std::map<std::string, Record*> &Defs = Records.getDefs();
+ std::vector<Tag> Tags;
+ // Collect tags.
+ Tags.reserve(Classes.size() + Defs.size());
+ for (std::map<std::string, Record*>::const_iterator I = Classes.begin(),
+ E = Classes.end(); I != E; ++I)
+ Tags.push_back(Tag(I->first, locate(I->second)));
+ for (std::map<std::string, Record*>::const_iterator I = Defs.begin(),
+ E = Defs.end(); I != E; ++I)
+ Tags.push_back(Tag(I->first, locate(I->second)));
+ // Emit tags.
+ std::sort(Tags.begin(), Tags.end());
+ OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n";
+ OS << "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/\n";
+ for (std::vector<Tag>::const_iterator I = Tags.begin(), E = Tags.end();
+ I != E; ++I)
+ I->emit(OS);
+}
+
+namespace llvm {
+
+void EmitCTags(RecordKeeper &RK, raw_ostream &OS) {
+ CTagsEmitter(RK).run(OS);
+}
+
+} // End llvm namespace.
Index: utils/TableGen/TableGen.cpp
===================================================================
--- utils/TableGen/TableGen.cpp
+++ utils/TableGen/TableGen.cpp
@@ -40,7 +40,8 @@
GenTgtIntrinsic,
PrintEnums,
PrintSets,
- GenOptParserDefs
+ GenOptParserDefs,
+ GenCTags
};
namespace {
@@ -82,6 +83,8 @@
"Print expanded sets for testing DAG exprs"),
clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
"Generate option definitions"),
+ clEnumValN(GenCTags, "gen-ctags",
+ "Generate ctags-compatible index"),
clEnumValEnd));
cl::opt<std::string>
@@ -161,6 +164,9 @@
}
break;
}
+ case GenCTags:
+ EmitCTags(Records, OS);
+ break;
}
return false;
Index: utils/TableGen/TableGenBackends.h
===================================================================
--- utils/TableGen/TableGenBackends.h
+++ utils/TableGen/TableGenBackends.h
@@ -75,5 +75,6 @@
void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS);
void EmitMapTable(RecordKeeper &RK, raw_ostream &OS);
void EmitOptParser(RecordKeeper &RK, raw_ostream &OS);
+void EmitCTags(RecordKeeper &RK, raw_ostream &OS);
} // End llvm namespace
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D546.1.patch
Type: text/x-patch
Size: 4773 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130315/3c6166c0/attachment.bin>
More information about the llvm-commits
mailing list