Browse Source

Added support for parsing native library symbols.

pull/1/head
triton 12 years ago
parent
commit
fe85a6590b
  1. 34
      src/Bridge/Library.cs
  2. 36
      src/Generator/Driver.cs
  3. 19
      src/Parser/Main.cpp
  4. 76
      src/Parser/Parser.cpp
  5. 8
      src/Parser/Parser.h
  6. 1
      src/Parser/Parser.lua

34
src/Bridge/Library.cs

@ -15,6 +15,24 @@ namespace Cxxi
Unavailable Unavailable
} }
public class NativeLibrary
{
public NativeLibrary(string file)
: this()
{
FileName = file;
}
public NativeLibrary()
{
Symbols = new List<string>();
}
public string FileName;
public IList<string> Symbols;
}
/// <summary> /// <summary>
/// A library contains all the modules. /// A library contains all the modules.
/// </summary> /// </summary>
@ -23,12 +41,27 @@ namespace Cxxi
public string Name; public string Name;
public string SharedLibrary; public string SharedLibrary;
public List<TranslationUnit> TranslationUnits; public List<TranslationUnit> TranslationUnits;
public List<NativeLibrary> Libraries;
public Library(string name, string sharedLibrary) public Library(string name, string sharedLibrary)
{ {
Name = name; Name = name;
SharedLibrary = sharedLibrary; SharedLibrary = sharedLibrary;
TranslationUnits = new List<TranslationUnit>(); TranslationUnits = new List<TranslationUnit>();
Libraries = new List<NativeLibrary>();
}
public NativeLibrary FindOrCreateLibrary(string file)
{
var library = Libraries.Find(m => m.FileName.Equals(file));
if (library == null)
{
library = new NativeLibrary(file);
Libraries.Add(library);
}
return library;
} }
/// Finds an existing module or creates a new one given a file path. /// Finds an existing module or creates a new one given a file path.
@ -85,7 +118,6 @@ namespace Cxxi
} }
} }
/// Finds an existing typedef in the library modules. /// Finds an existing typedef in the library modules.
public IEnumerable<TypedefDecl> FindTypedef(string name) public IEnumerable<TypedefDecl> FindTypedef(string name)
{ {

36
src/Generator/Driver.cs

@ -48,11 +48,16 @@ namespace Cxxi
Options.IncludeDirs[i] = Path.GetFullPath(Options.IncludeDirs[i]); Options.IncludeDirs[i] = Path.GetFullPath(Options.IncludeDirs[i]);
} }
for (var i = 0; i < Options.LibraryDirs.Count; i++)
{
Options.LibraryDirs[i] = Path.GetFullPath(Options.LibraryDirs[i]);
}
if (string.IsNullOrWhiteSpace(Options.OutputNamespace)) if (string.IsNullOrWhiteSpace(Options.OutputNamespace))
Options.OutputNamespace = Options.LibraryName; Options.OutputNamespace = Options.LibraryName;
} }
private void OnHeaderParsed(string file, ParserResult result) private void OnFileParsed(string file, ParserResult result)
{ {
switch (result.Kind) switch (result.Kind)
{ {
@ -80,11 +85,26 @@ namespace Cxxi
Console.WriteLine("Parsing code..."); Console.WriteLine("Parsing code...");
var parser = new Parser(Options); var parser = new Parser(Options);
parser.HeaderParsed += OnHeaderParsed; parser.OnHeaderParsed += OnFileParsed;
if( !parser.ParseHeaders(Options.Headers) ) if( !parser.ParseHeaders(Options.Headers) )
return false; return false;
Library = parser.Library;
return true;
}
public bool ParseLibraries()
{
Console.WriteLine("Parsing libraries...");
var parser = new Parser(Options);
parser.OnLibraryParsed += OnFileParsed;
if (!parser.ParseLibraries(Options.Libraries))
return false;
Library = parser.Library; Library = parser.Library;
return true; return true;
@ -161,7 +181,7 @@ namespace Cxxi
var driver = new Driver(options, library); var driver = new Driver(options, library);
driver.Setup(); driver.Setup();
if (driver.ParseCode()) if (driver.ParseLibraries() && driver.ParseCode())
{ {
driver.ProcessCode(); driver.ProcessCode();
driver.GenerateCode(); driver.GenerateCode();
@ -183,6 +203,10 @@ namespace Cxxi
WriteOnlyWhenChanged = false; WriteOnlyWhenChanged = false;
GeneratePartialClasses = true; GeneratePartialClasses = true;
// Library options
LibraryDirs = new List<string>();
Libraries = new List<string>();
var platform = Environment.OSVersion.Platform; var platform = Environment.OSVersion.Platform;
Abi = (platform == PlatformID.Unix || platform == PlatformID.MacOSX) ? Abi = (platform == PlatformID.Unix || platform == PlatformID.MacOSX) ?
CppAbi.Itanium : CppAbi.Microsoft; CppAbi.Itanium : CppAbi.Microsoft;
@ -213,6 +237,10 @@ namespace Cxxi
public LanguageGeneratorKind GeneratorKind; public LanguageGeneratorKind GeneratorKind;
public bool WriteOnlyWhenChanged; public bool WriteOnlyWhenChanged;
// Library options
public List<string> LibraryDirs;
public List<string> Libraries;
public bool IsItaniumAbi { get { return Abi == CppAbi.Itanium; } } public bool IsItaniumAbi { get { return Abi == CppAbi.Itanium; } }
public bool IsMicrosoftAbi { get { return Abi == CppAbi.Microsoft; } } public bool IsMicrosoftAbi { get { return Abi == CppAbi.Microsoft; } }
} }

19
src/Parser/Main.cpp

@ -11,15 +11,26 @@
public ref class ClangParser public ref class ClangParser
{ {
public: public:
static ParserResult^ Parse(ParserOptions^ Opts) static ParserResult^ ParseHeader(ParserOptions^ Opts)
{
if (!Opts->FileName) return nullptr;
using namespace clix;
std::string File = marshalString<E_UTF8>(Opts->FileName);
Parser parser(Opts);
return parser.ParseHeader(File);
}
static ParserResult^ ParseLibrary(ParserOptions^ Opts)
{ {
if (!Opts->FileName) return nullptr; if (!Opts->FileName) return nullptr;
using namespace clix; using namespace clix;
std::string File = marshalString<E_UTF8>(Opts->FileName); std::string File = marshalString<E_UTF8>(Opts->FileName);
Parser p(Opts); Parser parser(Opts);
return p.Parse(File); return parser.ParseLibrary(File);
} }
}; };

76
src/Parser/Parser.cpp

@ -9,6 +9,7 @@
#include "Interop.h" #include "Interop.h"
#include <llvm/Support/Path.h> #include <llvm/Support/Path.h>
#include <llvm/Object/Archive.h>
#include <clang/Basic/Version.h> #include <clang/Basic/Version.h>
#include <clang/Config/config.h> #include <clang/Config/config.h>
#include <clang/AST/ASTContext.h> #include <clang/AST/ASTContext.h>
@ -27,9 +28,8 @@
//-----------------------------------// //-----------------------------------//
Parser::Parser(ParserOptions^ Opts) : Lib(Opts->Library), Index(0) Parser::Parser(ParserOptions^ Opts) : Lib(Opts->Library), Opts(Opts), Index(0)
{ {
Setup(Opts);
} }
//-----------------------------------// //-----------------------------------//
@ -68,7 +68,7 @@ static std::string GetClangBuiltinIncludeDir()
std::vector<std::string> GetWindowsSystemIncludeDirs(); std::vector<std::string> GetWindowsSystemIncludeDirs();
#endif #endif
void Parser::Setup(ParserOptions^ Opts) void Parser::SetupHeader()
{ {
using namespace clang; using namespace clang;
using namespace clix; using namespace clix;
@ -1631,7 +1631,7 @@ struct DiagnosticConsumer : public clang::DiagnosticConsumer
std::vector<Diagnostic> Diagnostics; std::vector<Diagnostic> Diagnostics;
}; };
ParserResult^ Parser::Parse(const std::string& File) ParserResult^ Parser::ParseHeader(const std::string& File)
{ {
auto res = gcnew ParserResult(); auto res = gcnew ParserResult();
res->Library = Lib; res->Library = Lib;
@ -1642,6 +1642,8 @@ ParserResult^ Parser::Parse(const std::string& File)
return res; return res;
} }
SetupHeader();
auto SC = new clang::SemaConsumer(); auto SC = new clang::SemaConsumer();
C->setASTConsumer(SC); C->setASTConsumer(SC);
@ -1736,4 +1738,68 @@ ParserResult^ Parser::Parse(const std::string& File)
res->Kind = ParserResultKind::Success; res->Kind = ParserResultKind::Success;
return res; return res;
} }
ParserResult^ Parser::ParseLibrary(const std::string& File)
{
using namespace clix;
auto res = gcnew ParserResult();
res->Library = Lib;
if (File.empty())
{
res->Kind = ParserResultKind::FileNotFound;
return res;
}
C.reset(new clang::CompilerInstance());
C->createFileManager();
auto &FM = C->getFileManager();
const clang::FileEntry* FileEntry = 0;
for each(System::String^ LibDir in Opts->LibraryDirs)
{
auto DirName = marshalString<E_UTF8>(LibDir);
llvm::sys::Path Path(DirName);
Path.appendComponent(File);
if (FileEntry = FM.getFile(Path.str()))
break;
}
if (!FileEntry)
{
res->Kind = ParserResultKind::FileNotFound;
return res;
}
auto Buffer = FM.getBufferForFile(FileEntry);
llvm::error_code Code;
llvm::object::Archive Archive(Buffer, Code);
if (Code)
{
res->Kind = ParserResultKind::Error;
return res;
}
auto LibName = marshalString<E_UTF8>(File);
auto NativeLib = Lib->FindOrCreateLibrary(LibName);
for(auto it = Archive.begin_symbols(); it != Archive.end_symbols(); ++it)
{
llvm::StringRef SymRef;
if (it->getName(SymRef))
continue;
System::String^ SymName = marshalString<E_UTF8>(SymRef);
NativeLib->Symbols->Add(SymName);
}
res->Kind = ParserResultKind::Success;
return res;
}

8
src/Parser/Parser.h

@ -38,11 +38,13 @@ public ref struct ParserOptions
{ {
IncludeDirs = gcnew List<System::String^>(); IncludeDirs = gcnew List<System::String^>();
Defines = gcnew List<System::String^>(); Defines = gcnew List<System::String^>();
LibraryDirs = gcnew List<System::String^>();
} }
// Include directories // Include directories
List<System::String^>^ IncludeDirs; List<System::String^>^ IncludeDirs;
List<System::String^>^ Defines; List<System::String^>^ Defines;
List<System::String^>^ LibraryDirs;
// C/C++ header file name. // C/C++ header file name.
System::String^ FileName; System::String^ FileName;
@ -96,8 +98,9 @@ struct Parser
{ {
Parser(ParserOptions^ Opts); Parser(ParserOptions^ Opts);
void Setup(ParserOptions^ Opts); void SetupHeader();
ParserResult^ Parse(const std::string& File); ParserResult^ ParseHeader(const std::string& File);
ParserResult^ ParseLibrary(const std::string& File);
protected: protected:
@ -137,6 +140,7 @@ protected:
int Index; int Index;
gcroot<Cxxi::Library^> Lib; gcroot<Cxxi::Library^> Lib;
gcroot<ParserOptions^> Opts;
llvm::OwningPtr<clang::CompilerInstance> C; llvm::OwningPtr<clang::CompilerInstance> C;
clang::ASTContext* AST; clang::ASTContext* AST;
}; };

1
src/Parser/Parser.lua

@ -58,6 +58,7 @@ project "Parser"
links links
{ {
"LLVMSupport", "LLVMSupport",
"LLVMObject",
"LLVMAsmParser", "LLVMAsmParser",
"LLVMBitReader", "LLVMBitReader",
"LLVMBitWriter", "LLVMBitWriter",

Loading…
Cancel
Save