Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 63 additions & 7 deletions _xtool/internal/clang/clang.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ package clang

import (
"errors"
"os/exec"
"unsafe"

"github.com/goplus/lib/c"
"github.com/goplus/lib/c/clang"
"github.com/goplus/llcppg/_xtool/internal/clangtool"
)

const (
LLGoPackage = "link: -L$(llvm-config --libdir) -lclang; -lclang"
)

type Config struct {
Expand All @@ -26,8 +30,14 @@ const TEMP_FILE = "temp.h"
func CreateTranslationUnit(config *Config) (*clang.Index, *clang.TranslationUnit, error) {
// default use the c/c++ standard of clang; c:gnu17 c++:gnu++17
// https://clang.llvm.org/docs/CommandGuide/clang.html
allArgs := clangtool.WithSysRoot(append(defaultArgs(config.IsCpp), config.Args...))

executableName := "clang"
path, err := exec.LookPath(executableName)
if err != nil {
return nil, nil, err
}

allArgs := append(append([]string{path}, defaultArgs(config.IsCpp)...), config.Args...)
cArgs := make([]*c.Char, len(allArgs))
for i, arg := range allArgs {
cArgs[i] = c.AllocaCStr(arg)
Expand All @@ -41,32 +51,38 @@ func CreateTranslationUnit(config *Config) (*clang.Index, *clang.TranslationUnit
}

var unit *clang.TranslationUnit

var code ErrorCode
if config.Temp {
content := c.AllocaCStr(config.File)
tempFile := &clang.UnsavedFile{
Filename: c.Str(TEMP_FILE),
Contents: content,
Length: c.Ulong(c.Strlen(content)),
}

unit = index.ParseTranslationUnit(
code = ParseTranslationUnit2FullArgv(index,
tempFile.Filename,
unsafe.SliceData(cArgs), c.Int(len(cArgs)),
tempFile, 1,
clang.DetailedPreprocessingRecord,
&unit,
)

} else {

cFile := c.AllocaCStr(config.File)
unit = index.ParseTranslationUnit(
code = ParseTranslationUnit2FullArgv(index,
cFile,
unsafe.SliceData(cArgs), c.Int(len(cArgs)),
nil, 0,
clang.DetailedPreprocessingRecord,
&unit,
)
}

if code != Error_Success {
c.Printf(c.Str("code: %d\n"), code)
return nil, nil, errors.New("failed to parse translation unit")
}

if unit == nil {
return nil, nil, errors.New("failed to parse translation unit")
}
Expand Down Expand Up @@ -114,3 +130,43 @@ func defaultArgs(isCpp bool) []string {
}
return args
}

// CINDEX_LINKAGE CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx, const char *source_filename,
// const char *const *command_line_args,
// int num_command_line_args,
// struct CXUnsavedFile *unsaved_files,
// unsigned num_unsaved_files, unsigned options);

/**
* 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.
*/
//go:linkname ParseTranslationUnit C.clang_parseTranslationUnit
func ParseTranslationUnit(index *clang.Index, sourceFilename *c.Char, commandLineArgs **c.Char, numCommandLineArgs c.Int,
unsavedFiles *clang.UnsavedFile, numUnsavedFiles c.Uint, options c.Uint) *clang.TranslationUnit

/**
* Same as clang_parseTranslationUnit2 but requires a full command line
* for \c command_line_args including argv[0]. This is useful if the standard
* library paths are relative to the binary.
*/
// CINDEX_LINKAGE enum CXErrorCode
// clang_parseTranslationUnit2FullArgv(CXIndex CIdx, const char *source_filename, const char *const *command_line_args,
// int num_command_line_args, struct CXUnsavedFile *unsaved_files,
// unsigned num_unsaved_files, unsigned options, CXTranslationUnit *out_TU);

type ErrorCode int

const (
Error_Success = 0
Error_Failure = 1
Error_Crashed = 2
Error_InvalidArguments = 3
Error_ASTReadError = 4
)

//go:linkname ParseTranslationUnit2FullArgv C.clang_parseTranslationUnit2FullArgv
func ParseTranslationUnit2FullArgv(index *clang.Index, sourceFilename *c.Char, commandLineArgs **c.Char, numCommandLineArgs c.Int,
unsavedFiles *clang.UnsavedFile, numUnsavedFiles c.Uint, options c.Uint, out_TU **clang.TranslationUnit) ErrorCode
Loading