From 3fd688191cfd80b14b3086d4e0a2463305612574 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Tue, 25 Jun 2024 00:33:48 +0800 Subject: [PATCH] c/clang --- c/clang/_demo/castdump/astdump.go | 49 ++++++ c/clang/basic.go | 59 +++++++ c/clang/clang.go | 262 ++++++++++++++++++++++++++++++ c/clang/llgo_autogen.lla | Bin 0 -> 658 bytes 4 files changed, 370 insertions(+) create mode 100644 c/clang/_demo/castdump/astdump.go create mode 100644 c/clang/basic.go create mode 100644 c/clang/clang.go create mode 100644 c/clang/llgo_autogen.lla diff --git a/c/clang/_demo/castdump/astdump.go b/c/clang/_demo/castdump/astdump.go new file mode 100644 index 00000000..336c8d6f --- /dev/null +++ b/c/clang/_demo/castdump/astdump.go @@ -0,0 +1,49 @@ +package main + +import ( + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/clang" +) + +func visit(cursor, parent clang.Cursor, clientData c.Pointer) clang.ChildVisitResult { + depth := *(*c.Uint)(clientData) + printAST(cursor, depth+1) + return clang.ChildVisit_Continue +} + +func printAST(cursor clang.Cursor, depth c.Uint) { + cursorKind := cursor.Kind.String() + cursorSpelling := cursor.String() + + for i := c.Uint(0); i < depth; i++ { + c.Fputs(c.Str(" "), c.Stdout) + } + + c.Printf(c.Str("%s: %s\n"), cursorKind.CStr(), cursorSpelling.CStr()) + + cursorKind.Dispose() + cursorSpelling.Dispose() + + clang.VisitChildren(cursor, visit, c.Pointer(&depth)) +} + +func main() { + index := clang.CreateIndex(0, 0) + unit := index.ParseTranslationUnit( + c.Str("todo"), + nil, 0, + nil, 0, + clang.TranslationUnit_None, + ) + + if unit == nil { + println("Unable to parse translation unit. Quitting.") + c.Exit(1) + } + + cursor := unit.Cursor() + printAST(cursor, 0) + + unit.Dispose() + index.Dispose() +} diff --git a/c/clang/basic.go b/c/clang/basic.go new file mode 100644 index 00000000..1d33d1fe --- /dev/null +++ b/c/clang/basic.go @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package clang + +import ( + _ "unsafe" + + "github.com/goplus/llgo/c" +) + +/** + * A character string. + * + * The \c CXString type is used to return strings from the interface when + * the ownership of that string might differ from one call to the next. + * Use \c clang_getCString() to retrieve the string data and, once finished + * with the string data, call \c clang_disposeString() to free the string. + */ +type String struct { + Data c.Pointer + PrivateFlags c.Uint +} + +/** + * Retrieve the character data associated with the given string. + */ +// llgo:link C.clang_getCString +func (String) CStr() *c.Char { return nil } + +/** + * Free the given string. + */ +// llgo:link C.clang_disposeString +func (String) Dispose() {} + +type StringSet struct { + Strings *String + Count c.Uint +} + +/** + * Free the given string set. + */ +// llgo:link C.clang_disposeStringSet +func (*StringSet) Dispose() {} diff --git a/c/clang/clang.go b/c/clang/clang.go new file mode 100644 index 00000000..52a981f3 --- /dev/null +++ b/c/clang/clang.go @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package clang + +import ( + _ "unsafe" + + "github.com/goplus/llgo/c" +) + +/** + * Opaque pointer representing client data that will be passed through + * to various callbacks and visitors. + */ +type ClientData = c.Pointer + +/** + * Provides the contents of a file that has not yet been saved to disk. + * + * Each CXUnsavedFile instance provides the name of a file on the + * system along with the current contents of that file that have not + * yet been saved to disk. + */ +type UnsavedFile struct { + /** + * The file whose contents have not yet been saved. + * + * This file must already exist in the file system. + */ + Filename *c.Char + + /** + * A buffer containing the unsaved contents of this file. + */ + Contents *c.Char + + /** + * The length of the unsaved contents of this buffer. + */ + Length c.Ulong +} + +/** + * An "index" that consists of a set of translation units that would + * typically be linked together into an executable or library. + */ +type Index struct { + Unused [0]byte +} + +/** + * Provides a shared context for creating translation units. + * + * It provides two options: + * + * - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local" + * declarations (when loading any new translation units). A "local" declaration + * is one that belongs in the translation unit itself and not in a precompiled + * header that was used by the translation unit. If zero, all declarations + * will be enumerated. + * + * Here is an example: + * + * \code + * // excludeDeclsFromPCH = 1, displayDiagnostics=1 + * Idx = clang_createIndex(1, 1); + * + * // IndexTest.pch was produced with the following command: + * // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch" + * TU = clang_createTranslationUnit(Idx, "IndexTest.pch"); + * + * // This will load all the symbols from 'IndexTest.pch' + * clang_visitChildren(clang_getTranslationUnitCursor(TU), + * TranslationUnitVisitor, 0); + * clang_disposeTranslationUnit(TU); + * + * // This will load all the symbols from 'IndexTest.c', excluding symbols + * // from 'IndexTest.pch'. + * char *args[] = { "-Xclang", "-include-pch=IndexTest.pch" }; + * TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args, + * 0, 0); + * clang_visitChildren(clang_getTranslationUnitCursor(TU), + * TranslationUnitVisitor, 0); + * clang_disposeTranslationUnit(TU); + * \endcode + * + * This process of creating the 'pch', loading it separately, and using it (via + * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks + * (which gives the indexer the same performance benefit as the compiler). + */ +//go:linkname CreateIndex C.clang_createIndex +func CreateIndex(excludeDeclarationsFromPCH, displayDiagnostics c.Int) *Index + +/** + * Destroy the given index. + * + * The index must not be destroyed until all of the translation units created + * within that index have been destroyed. + */ +// llgo:link (*Index).Dispose C.clang_disposeIndex +func (*Index) Dispose() {} + +/** + * Flags that control the creation of translation units. + * + * The enumerators in this enumeration type are meant to be bitwise + * ORed together to specify which options should be used when + * constructing the translation unit. + */ +const ( + TranslationUnit_None = 0x0 +) + +/** + * Same as \c clang_parseTranslationUnit2, but returns + * the \c CXTranslationUnit instead of an error code. In case of an error this + * routine returns a \c NULL \c CXTranslationUnit, without further detailed + * error codes. + */ +// llgo:link (*Index).ParseTranslationUnit C.clang_parseTranslationUnit +func (*Index) ParseTranslationUnit( + sourceFilename *c.Char, commandLineArgs **c.Char, numCommandLineArgs c.Int, + unsavedFiles *UnsavedFile, numUnsavedFiles c.Uint, options c.Uint) *TranslationUnit { + return nil +} + +/** + * A single translation unit, which resides in an index. + */ +type TranslationUnit struct { + Unused [0]byte +} + +/** + * Destroy the specified CXTranslationUnit object. + */ +// llgo:linke (*TranslationUnit).Dispose C.clang_disposeTranslationUnit +func (*TranslationUnit) Dispose() {} + +/** + * Retrieve the cursor that represents the given translation unit. + * + * The translation unit cursor can be used to start traversing the + * various declarations within the given translation unit. + */ +// llgo:link (*TranslationUnit).Cursor C.clang_getTranslationUnitCursor +func (*TranslationUnit) Cursor() (ret Cursor) { + return +} + +/** + * Describes the kind of entity that a cursor refers to. + */ +type CursorKind c.Int + +/* for debug/testing */ +// llgo:link (CursorKind).String C.clang_getCursorKindSpelling +func (CursorKind) String() (ret String) { + return +} + +/** + * A cursor representing some element in the abstract syntax tree for + * a translation unit. + * + * The cursor abstraction unifies the different kinds of entities in a + * program--declaration, statements, expressions, references to declarations, + * etc.--under a single "cursor" abstraction with a common set of operations. + * Common operation for a cursor include: getting the physical location in + * a source file where the cursor points, getting the name associated with a + * cursor, and retrieving cursors for any child nodes of a particular cursor. + * + * Cursors can be produced in two specific ways. + * clang_getTranslationUnitCursor() produces a cursor for a translation unit, + * from which one can use clang_visitChildren() to explore the rest of the + * translation unit. clang_getCursor() maps from a physical source location + * to the entity that resides at that location, allowing one to map from the + * source code into the AST. + */ +type Cursor struct { + Kind CursorKind + Xdata c.Int + Data [3]c.Pointer +} + +/** + * Retrieve a name for the entity referenced by this cursor. + */ +// llgo:link C.clang_getCursorSpelling +func (Cursor) String() (ret String) { + return +} + +/** + * Describes how the traversal of the children of a particular + * cursor should proceed after visiting a particular child cursor. + * + * A value of this enumeration type should be returned by each + * \c CXCursorVisitor to indicate how clang_visitChildren() proceed. + */ +type ChildVisitResult c.Int + +const ( + /** + * Terminates the cursor traversal. + */ + ChildVisit_Break ChildVisitResult = iota + /** + * Continues the cursor traversal with the next sibling of + * the cursor just visited, without visiting its children. + */ + ChildVisit_Continue + /** + * Recursively traverse the children of this cursor, using + * the same visitor and client data. + */ + ChildVisit_Recurse +) + +/** + * Visit the children of a particular cursor. + * + * This function visits all the direct children of the given cursor, + * invoking the given \p visitor function with the cursors of each + * visited child. The traversal may be recursive, if the visitor returns + * \c CXChildVisit_Recurse. The traversal may also be ended prematurely, if + * the visitor returns \c CXChildVisit_Break. + * + * \param parent the cursor whose child may be visited. All kinds of + * cursors can be visited, including invalid cursors (which, by + * definition, have no children). + * + * \param visitor the visitor function that will be invoked for each + * child of \p parent. + * + * \param client_data pointer data supplied by the client, which will + * be passed to the visitor each time it is invoked. + * + * \returns a non-zero value if the traversal was terminated + * prematurely by the visitor returning \c CXChildVisit_Break. + */ +//go:linkname VisitChildren C.clang_visitChildren +func VisitChildren( + cusor Cursor, + visitor func(cursor, parent Cursor, clientData ClientData) ChildVisitResult, + clientData ClientData) c.Uint { + return 0 +} diff --git a/c/clang/llgo_autogen.lla b/c/clang/llgo_autogen.lla new file mode 100644 index 0000000000000000000000000000000000000000..3a5e839a4b08af5f2cccf70be8be52b64fbc76a9 GIT binary patch literal 658 zcmWIWW@Zs#U|`^2U}U)&v7*e#{vIO(g9$eS13!ZdLrzY5etcqSNq%~2o?cE)Xb2|* zbL0HVv}PbKt>6ag`3h7GHsETQulHdGfxYk7OLQF#bGq%qzlftL&c$Y>`ovAX+X@r! z@a~rW$ozlzW?!jf(aAzgx148RI8&W}Z#GXgPq@{|z?eCQIo~Y1Wc#GsbB+A+mFEn$ z2OkOXf1KG9vvl{FS9gvi?VF+@QZEu>^kZ+zfg2khPCU8Qc+xx-gYT0#E1J*DWO!1? z^8W16^qm`TUFlk>r?Kzdw}&^A?+Wu-=Q2(5+BMhYx!T7B%~!1M6BKnUqXZe;XKHas zdLIeWVqCjBOGVEr!rngX?#BYNHgmJ@|Ieno^Bmx~9(QfE!L98&D-Cz0y|*nfyQRIQ zZ}l^c-uJuO6(##-sh_=)`kqn5;dKO`t(S|2q5B{1i!G0HKTEjnbqUbeHAQRXt`GXx z{?C-v-~08?nz-NV7Z+Z5ol#@HE%{SijdFRQrRC!LV$P8t|4iBWJlHbH_t4~Np4q(5 zFQwh;T4!YQe4Ad+H?9+fnJ(Aw266qV-Tq~!zp0frAOko|C$&C3IY$vZZkn0w{bv}sBCK6Q`z+-66fTXk2Q?d`J7Wfy+hTw~Dbv48uc zXQDpK+EY!cw{|QS4yY_-S!;iMg5<=ANl}Z=bX>5?ZFydzCO&s-z35&s$x=bjwrfwW z75!!i@MdI^W5$(GB!CHsfdQBj7?w1GSQyEM6_RYwl1zX%D;r2TBM^oHX>}$L4*(4d B5<>t0 literal 0 HcmV?d00001