step towards c++
This commit is contained in:
@@ -11,6 +11,12 @@ static class Program
|
|||||||
|
|
||||||
public static int Main(String[] args)
|
public static int Main(String[] args)
|
||||||
{
|
{
|
||||||
|
if (args.Count == 3 && args[0] == "---__defsyms__")
|
||||||
|
{
|
||||||
|
GenerateAliases(args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
mixin PrintUsage()
|
mixin PrintUsage()
|
||||||
{
|
{
|
||||||
Console.WriteLine("""
|
Console.WriteLine("""
|
||||||
@@ -19,8 +25,9 @@ static class Program
|
|||||||
Usage: $(Var CxxBuilderExe) [<options>] <patterns...> -- src=<> target=<> config=<> builddir=<> output=<> [cflags=<>]
|
Usage: $(Var CxxBuilderExe) [<options>] <patterns...> -- src=<> target=<> config=<> builddir=<> output=<> [cflags=<>]
|
||||||
Example: $(Var CxxBuilderExe) **.c vk_*.cpp -- "src=$(ProjectDir)/MyLib/src" target=$(TargetTriple) config=$(Configuration) "builddir=$(BuildDir)" output=MyLib cflags=-Isome/dir
|
Example: $(Var CxxBuilderExe) **.c vk_*.cpp -- "src=$(ProjectDir)/MyLib/src" target=$(TargetTriple) config=$(Configuration) "builddir=$(BuildDir)" output=MyLib cflags=-Isome/dir
|
||||||
|
|
||||||
--template - TODO
|
|
||||||
--cmake - builds $src/CMakeLists.txt to build, patterns and output are ignored
|
--cmake - builds $src/CMakeLists.txt to build, patterns and output are ignored
|
||||||
|
! --template - TODO
|
||||||
|
! --cpp-aliases - creates aliases from the mangled c++ symbols to the symbols queried by Cpp2Beef-generated c++ bindigs
|
||||||
|
|
||||||
$src - The source dir, all patterns are rooted here
|
$src - The source dir, all patterns are rooted here
|
||||||
$target - the llvm target triple passed to clang
|
$target - the llvm target triple passed to clang
|
||||||
@@ -36,27 +43,36 @@ static class Program
|
|||||||
{
|
{
|
||||||
if (!condition)
|
if (!condition)
|
||||||
{
|
{
|
||||||
Console.WriteLine(str);
|
Console.Error.WriteLine(str);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum { Default, CMake, Template } mode = .Default;
|
enum { Default, CMake, Template } mode = .Default;
|
||||||
|
enum { None, CppAliases } actions = .None;
|
||||||
StringView src = null, target = null, config = null, builddir = null, output = null, cflags = null;
|
StringView src = null, target = null, config = null, builddir = null, output = null, cflags = null;
|
||||||
var iter = args.GetEnumerator();
|
var iter = args.GetEnumerator();
|
||||||
skipPatterns: do
|
skipPatterns: do
|
||||||
{
|
{
|
||||||
for (let arg in iter)
|
for (let arg in iter)
|
||||||
{
|
{
|
||||||
if (arg == "--") break skipPatterns;
|
if (!arg.StartsWith("--")) continue;
|
||||||
if (arg == "--cmake")
|
switch (arg)
|
||||||
{
|
{
|
||||||
|
case "--": break skipPatterns;
|
||||||
|
case "--cmake":
|
||||||
Assert!(mode == .Default, "Conflicting options");
|
Assert!(mode == .Default, "Conflicting options");
|
||||||
mode = .CMake;
|
mode = .CMake;
|
||||||
|
/*case "--cpp-aliases":
|
||||||
|
actions |= .CppAliases;*/
|
||||||
|
default:
|
||||||
|
Console.Error.WriteLine($"Invalid option {_}");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PrintUsage!();
|
PrintUsage!();
|
||||||
}
|
}
|
||||||
|
Assert!(!(mode == .CMake && actions.HasFlag(.CppAliases)), "Comflicting options --cmake and --cpp-aliases");
|
||||||
for (let arg in iter)
|
for (let arg in iter)
|
||||||
{
|
{
|
||||||
var parts = arg.Split('=', 2);
|
var parts = arg.Split('=', 2);
|
||||||
@@ -84,7 +100,7 @@ static class Program
|
|||||||
Assert!(!target.IsNull, "Missing var 'target'");
|
Assert!(!target.IsNull, "Missing var 'target'");
|
||||||
Assert!(!config.IsNull, "Missing var 'config'");
|
Assert!(!config.IsNull, "Missing var 'config'");
|
||||||
Assert!(!builddir.IsNull, "Missing var 'builddir'");
|
Assert!(!builddir.IsNull, "Missing var 'builddir'");
|
||||||
Assert!(!output.IsNull || mode == .CMake, "Missing var 'output'");
|
Assert!(!output.IsNull || (mode == .CMake && !actions.HasFlag(.CppAliases)), "Missing var 'output'");
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
@@ -104,14 +120,14 @@ static class Program
|
|||||||
WriteVarPath("builddir", builddir);
|
WriteVarPath("builddir", builddir);
|
||||||
buffer.AppendF($"""
|
buffer.AppendF($"""
|
||||||
target = {target}
|
target = {target}
|
||||||
cflags = {(config == "Release") ? "-O2" : "-O2 -g"} {cflags}
|
cflags = {(config == "Release") ? "-O3" : "-O2 -g"} {cflags}
|
||||||
""");
|
""");
|
||||||
writer.Write(buffer);
|
writer.Write(buffer);
|
||||||
}
|
}
|
||||||
writer.Write("""
|
writer.Write("""
|
||||||
\n
|
\n
|
||||||
cc = clang
|
cc = clang
|
||||||
ar = ar
|
ar = llvm-ar
|
||||||
|
|
||||||
rule cc
|
rule cc
|
||||||
command = $cc $cflags -target $target -MD -MF $out.d -c -o $out $in
|
command = $cc $cflags -target $target -MD -MF $out.d -c -o $out $in
|
||||||
@@ -126,7 +142,8 @@ static class Program
|
|||||||
|
|
||||||
""");
|
""");
|
||||||
String ar = scope .(1024);
|
String ar = scope .(1024);
|
||||||
ar.AppendF($"\nbuild $builddir/{output}.{target.Contains("windows") ? "lib" : "a"}: ar");
|
StringView libExtension = target.Contains("windows") ? "lib" : "a";
|
||||||
|
ar.AppendF($"\nbuild $builddir/{output}.{libExtension}: ar");
|
||||||
|
|
||||||
int pcount = 0;
|
int pcount = 0;
|
||||||
for (let arg in args)
|
for (let arg in args)
|
||||||
@@ -148,11 +165,45 @@ static class Program
|
|||||||
let abssrc = Path.GetAbsolutePath(src, Directory.GetCurrentDirectory(..scope .(128)), ..scope .(128));
|
let abssrc = Path.GetAbsolutePath(src, Directory.GetCurrentDirectory(..scope .(128)), ..scope .(128));
|
||||||
if (FileMatcher.HandleMatches(patterns, abssrc, scope => HandleMatch) case .Err(let err))
|
if (FileMatcher.HandleMatches(patterns, abssrc, scope => HandleMatch) case .Err(let err))
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Syntax Error in Pattern: {err}");
|
Console.Error.WriteLine($"Syntax Error in Pattern: {err}");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteLine(ar);
|
writer.WriteLine(ar);
|
||||||
|
|
||||||
|
if (actions.HasFlag(.CppAliases))
|
||||||
|
{
|
||||||
|
const String exec = .Empty
|
||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
+ "cmd /c ";
|
||||||
|
#endif
|
||||||
|
writer.Write($"""
|
||||||
|
|
||||||
|
nm = llvm-nm
|
||||||
|
ld = {exec}ld
|
||||||
|
|
||||||
|
rule nm
|
||||||
|
command = {exec}$nm --demangle $in > $out
|
||||||
|
description = Exporting symbols from $in
|
||||||
|
|
||||||
|
rule generate_aliases
|
||||||
|
command = "{Environment.GetExecutableFilePath(..scope .(64))}" ---__defsyms__ $in $out
|
||||||
|
description = Generating aliases
|
||||||
|
|
||||||
|
rule ld_aliases
|
||||||
|
command = $ld -r -o $out @$in "$builddir/{output}.{libExtension}"
|
||||||
|
description = Creating aliases
|
||||||
|
|
||||||
|
rule ar_add
|
||||||
|
command = $ar qs $builddir/{output}.{libExtension} $in
|
||||||
|
|
||||||
|
build $builddir/_symbols__.txt: nm $builddir/{output}.{libExtension}
|
||||||
|
build $builddir/_aliases__.txt: generate_aliases $builddir/_symbols__.txt
|
||||||
|
build $builddir/_aliases__.o: ld_aliases $builddir/_aliases__.txt
|
||||||
|
build add_to_output: ar_add $builddir/_aliases__.o
|
||||||
|
|
||||||
|
""");
|
||||||
|
}
|
||||||
case .CMake:
|
case .CMake:
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
if (File.Exists(scope $"{builddir}/build.ninja"))
|
if (File.Exists(scope $"{builddir}/build.ninja"))
|
||||||
@@ -167,9 +218,84 @@ static class Program
|
|||||||
case .Template: //TODO
|
case .Template: //TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
let ret = system(scope $"ninja -C {builddir}");
|
var ret = system(scope $"ninja -C {builddir}");
|
||||||
if (ret != 0)
|
mixin CheckRetCode(StringView fmt)
|
||||||
Console.WriteLine($"Failed to build {output}");
|
{
|
||||||
return ret;
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(fmt, output);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CheckRetCode!("Failed to build {}");
|
||||||
|
|
||||||
|
/*if (actions.HasFlag(.CppAliases))
|
||||||
|
{
|
||||||
|
let aliasesDir = scope $"{builddir}/cpp2beef_aliases";
|
||||||
|
Directory.CreateDirectory(aliasesDir);
|
||||||
|
{
|
||||||
|
StreamWriter writer = scope .()..Create(scope $"{aliasesDir}/aliases.c");
|
||||||
|
ret = system(scope $"llvm-nm --export-symbols \"{builddir}/{output}.{target.Contains("windows") ? "lib" : "a"}\" > {aliasesDir}/mangled.txt");
|
||||||
|
CheckRetCode!("Failed to fetch symbols from {}");
|
||||||
|
ret = system(scope $"cat {aliasesDir}/mangled.txt | llvm-undname >{aliasesDir}/demangled.txt 2>{
|
||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
("nul")
|
||||||
|
#else
|
||||||
|
("/dev/null")
|
||||||
|
#endif
|
||||||
|
}");
|
||||||
|
CheckRetCode!("Failed to demangle symbols from {}");
|
||||||
|
var mangled = scope StreamReader()..Open(scope $"{aliasesDir}/magled.txt").Lines;
|
||||||
|
var demangled = scope StreamReader()..Open(scope $"{aliasesDir}/demangled.txt").Lines;
|
||||||
|
for (let dline in demangled)
|
||||||
|
{
|
||||||
|
if (dline->IsEmpty) continue;
|
||||||
|
let mline = mangled.GetNext().Value;
|
||||||
|
if (mline == dline) continue;
|
||||||
|
String identifier = scope .(dline);
|
||||||
|
for (let i < identifier.Length)
|
||||||
|
if (!identifier[i].IsLetterOrDigit)
|
||||||
|
identifier[i] = '_';
|
||||||
|
writer.Write($"extern void {identifier}() __attribute__((weak, alias(\"{mline.Value}\")));\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
File.WriteAllText(scope $"{aliasesDir}/build.ninja", scope $"""
|
||||||
|
rule cc
|
||||||
|
command = clang -x c -target {target} -c -o $out $in
|
||||||
|
description = Compiling aliases for {output}
|
||||||
|
|
||||||
|
build aliases.o: cc aliases.c
|
||||||
|
|
||||||
|
""");
|
||||||
|
ret = system(scope $"ninja -C {aliasesDir}");
|
||||||
|
CheckRetCode!("Failed to build aliases for {}");
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void GenerateAliases(String[] args)
|
||||||
|
{
|
||||||
|
StreamReader reader = scope .()..Open(args[1]);
|
||||||
|
StreamWriter writer = scope .()..Create(args[2]);
|
||||||
|
String str = scope .(256);
|
||||||
|
for (var line in reader.Lines)
|
||||||
|
{
|
||||||
|
line->Trim();
|
||||||
|
if (line->IsEmpty || line->EndsWith(':')) continue;
|
||||||
|
var split = line->Split(' ', 3);
|
||||||
|
if (split.GetNext().Value == "U") continue;
|
||||||
|
int addr = int.Parse(split.Current, .Hex);
|
||||||
|
let kind = split.GetNext().Value;
|
||||||
|
if (kind != "T" || addr == 0) continue;
|
||||||
|
let sym = split.GetNext().Value;
|
||||||
|
if (!str.IsEmpty) str..Clear()..Append(' ');
|
||||||
|
str.Append("--defsym=");
|
||||||
|
for (let i < sym.Length)
|
||||||
|
str.Append(sym[i].IsLetterOrDigit ? sym[i] : '_');
|
||||||
|
str.Append('=');
|
||||||
|
addr.ToString(str);
|
||||||
|
writer.Write(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,7 +164,7 @@ static class Program
|
|||||||
}
|
}
|
||||||
|
|
||||||
Directory.CreateDirectory("clang-c");
|
Directory.CreateDirectory("clang-c");
|
||||||
generator.Generate("clang-c.h", null);
|
generator.Generate("clang-c.h");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
213
src/Generator.bf
213
src/Generator.bf
@@ -64,6 +64,7 @@ abstract class Cpp2BeefGenerator
|
|||||||
}, &attrs);
|
}, &attrs);
|
||||||
|
|
||||||
if (Clang.GetCursorAvailability(cursor) == .Deprecated) str.Append("[Obsolete] ");
|
if (Clang.GetCursorAvailability(cursor) == .Deprecated) str.Append("[Obsolete] ");
|
||||||
|
//if (Clang.Cursor_IsFunctionInlined(cursor) != 0) str.Append("[Inline] ");
|
||||||
if (cursor.kind == .EnumDecl) str.Append("[AllowDuplicates] ");
|
if (cursor.kind == .EnumDecl) str.Append("[AllowDuplicates] ");
|
||||||
else if (attrs.HasFlag(.Packed)) str.Append("[Packed] ");
|
else if (attrs.HasFlag(.Packed)) str.Append("[Packed] ");
|
||||||
if (attrs.HasFlag(.NoDiscard)) str.Append("[NoDiscard] ");
|
if (attrs.HasFlag(.NoDiscard)) str.Append("[NoDiscard] ");
|
||||||
@@ -197,13 +198,10 @@ abstract class Cpp2BeefGenerator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void ModifyWrapperPrintingPolicy(CXPrintingPolicy policy) {}
|
|
||||||
|
|
||||||
protected CXIndex index = Clang.CreateIndex(excludeDeclarationsFromPCH: 0, displayDiagnostics: 1) ~ Clang.DisposeIndex(_);
|
protected CXIndex index = Clang.CreateIndex(excludeDeclarationsFromPCH: 0, displayDiagnostics: 1) ~ Clang.DisposeIndex(_);
|
||||||
protected CXTranslationUnit unit;
|
protected CXTranslationUnit unit;
|
||||||
|
|
||||||
protected append String str = .(1024);
|
protected append String str = .(1024);
|
||||||
protected append String wrapperBuf = .(1024);
|
|
||||||
protected CXCursor currentCursor = Clang.GetNullCursor();
|
protected CXCursor currentCursor = Clang.GetNullCursor();
|
||||||
protected append String cursorIndent = .(16);
|
protected append String cursorIndent = .(16);
|
||||||
|
|
||||||
@@ -213,8 +211,6 @@ abstract class Cpp2BeefGenerator
|
|||||||
protected CXPrintingPolicy printingPolicy;
|
protected CXPrintingPolicy printingPolicy;
|
||||||
|
|
||||||
private StreamWriter currentWritter;
|
private StreamWriter currentWritter;
|
||||||
private StreamWriter wrapperWritter;
|
|
||||||
protected StringView WrapperFilePath;
|
|
||||||
|
|
||||||
private append String wrapperTemplateChain = .(16);
|
private append String wrapperTemplateChain = .(16);
|
||||||
private append String templateParams = .(16);
|
private append String templateParams = .(16);
|
||||||
@@ -229,7 +225,7 @@ abstract class Cpp2BeefGenerator
|
|||||||
protected class FileInfo : this(CXSourceLocation prevEnd, CXFile file)
|
protected class FileInfo : this(CXSourceLocation prevEnd, CXFile file)
|
||||||
{
|
{
|
||||||
public append String block = .(64);
|
public append String block = .(64);
|
||||||
public enum { None = 0, LSquirly = 1, RSquirly = 0b10 } queuedTokens = .None;
|
public enum { None = 0, LSquirly = 1, RSquirly = _<<1, Semicolon = _<<1 } queuedTokens = .None;
|
||||||
public (CXType type, int32 curWidth) bitfield = default;
|
public (CXType type, int32 curWidth) bitfield = default;
|
||||||
}
|
}
|
||||||
protected FileInfo fileInfo = null;
|
protected FileInfo fileInfo = null;
|
||||||
@@ -279,40 +275,12 @@ abstract class Cpp2BeefGenerator
|
|||||||
ParsingFailed
|
ParsingFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result<void, GenerationError> Generate(char8* headerPath, StringView wrapperPath = null)
|
public Result<void, GenerationError> Generate(char8* headerPath)
|
||||||
{
|
{
|
||||||
unitMacros.Clear();
|
unitMacros.Clear();
|
||||||
fileInfos.Clear();
|
fileInfos.Clear();
|
||||||
lastRecordOrEnum = Clang.GetNullCursor();
|
lastRecordOrEnum = Clang.GetNullCursor();
|
||||||
|
|
||||||
if (!wrapperPath.IsNull)
|
|
||||||
{
|
|
||||||
wrapperWritter = scope:: .();
|
|
||||||
wrapperWritter.Create(wrapperPath);
|
|
||||||
WrapperFilePath = wrapperPath;
|
|
||||||
wrapperBuf.Set("""
|
|
||||||
#define private public
|
|
||||||
#define protected public
|
|
||||||
|
|
||||||
#include "
|
|
||||||
""");
|
|
||||||
Path.GetFileName(.(headerPath), wrapperBuf);
|
|
||||||
wrapperBuf.Append("""
|
|
||||||
"
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using __type = T;
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
|
|
||||||
""");
|
|
||||||
FlushWrapper();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
wrapperWritter = null;
|
|
||||||
|
|
||||||
let args = Args;
|
let args = Args;
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
findLang: do
|
findLang: do
|
||||||
@@ -331,7 +299,7 @@ abstract class Cpp2BeefGenerator
|
|||||||
if (unit == default) return .Err(.ParsingFailed);
|
if (unit == default) return .Err(.ParsingFailed);
|
||||||
|
|
||||||
printingPolicy = Clang.GetCursorPrintingPolicy(Clang.GetTranslationUnitCursor(unit));
|
printingPolicy = Clang.GetCursorPrintingPolicy(Clang.GetTranslationUnitCursor(unit));
|
||||||
ModifyWrapperPrintingPolicy(printingPolicy);
|
Clang.PrintingPolicy_SetProperty(printingPolicy, .TerseOutput, 1);
|
||||||
defer Clang.PrintingPolicy_Dispose(printingPolicy);
|
defer Clang.PrintingPolicy_Dispose(printingPolicy);
|
||||||
|
|
||||||
PreGeneration();
|
PreGeneration();
|
||||||
@@ -371,9 +339,6 @@ abstract class Cpp2BeefGenerator
|
|||||||
}, Internal.UnsafeCastToPtr(this));
|
}, Internal.UnsafeCastToPtr(this));
|
||||||
PostGeneration();
|
PostGeneration();
|
||||||
|
|
||||||
if (wrapperBuf.IsEmpty)
|
|
||||||
wrapperWritter.Write("}\n\n//begin-comptime\n");
|
|
||||||
|
|
||||||
for (let kv in fileInfos)
|
for (let kv in fileInfos)
|
||||||
{
|
{
|
||||||
fileInfo = kv.value;
|
fileInfo = kv.value;
|
||||||
@@ -462,11 +427,6 @@ abstract class Cpp2BeefGenerator
|
|||||||
currentWritter.Write(str);
|
currentWritter.Write(str);
|
||||||
str.Clear();
|
str.Clear();
|
||||||
}
|
}
|
||||||
protected void FlushWrapper()
|
|
||||||
{
|
|
||||||
wrapperWritter.Write(wrapperBuf);
|
|
||||||
wrapperBuf.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void GetIndentation(CXSourceLocation location, String outString)
|
protected virtual void GetIndentation(CXSourceLocation location, String outString)
|
||||||
{
|
{
|
||||||
@@ -627,6 +587,8 @@ abstract class Cpp2BeefGenerator
|
|||||||
|
|
||||||
QueuedToken!(decltype(fileInfo.queuedTokens).LSquirly, "{");
|
QueuedToken!(decltype(fileInfo.queuedTokens).LSquirly, "{");
|
||||||
QueuedToken!(decltype(fileInfo.queuedTokens).RSquirly, "}");
|
QueuedToken!(decltype(fileInfo.queuedTokens).RSquirly, "}");
|
||||||
|
if (!fileInfo.queuedTokens.HasFlag(.RSquirly))
|
||||||
|
QueuedToken!(decltype(fileInfo.queuedTokens).Semicolon, ";");
|
||||||
|
|
||||||
if (!isWritingQueuedToken) continue;
|
if (!isWritingQueuedToken) continue;
|
||||||
if (fileInfo.queuedTokens == .None) block = @block;
|
if (fileInfo.queuedTokens == .None) block = @block;
|
||||||
@@ -866,22 +828,18 @@ abstract class Cpp2BeefGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const int int_maxDigits = scope $"{int.MaxValue:X}".Length + 1;
|
|
||||||
protected virtual void CppWrapperName(CXCursor cursor, String outString)
|
|
||||||
{
|
|
||||||
String hashCode = ScopeCXString!(Clang.GetCursorUSR(cursor))
|
|
||||||
.GetHashCode().ToString(..scope .(int_maxDigits), "X", null);
|
|
||||||
outString.Append("cpp2beef_");
|
|
||||||
if (hashCode.StartsWith('-')) hashCode[0] = 'm';
|
|
||||||
outString.Append('0', int_maxDigits - hashCode.Length);
|
|
||||||
outString.Append(hashCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual enum { C, Cpp } Linkable_Attributes(CXCursor cursor)
|
protected virtual enum { C, Cpp } Linkable_Attributes(CXCursor cursor)
|
||||||
{
|
{
|
||||||
let mangledName = ScopeCXString!(Clang.Cursor_GetMangling(cursor));
|
let mangledName = ScopeCXString!(Clang.Cursor_GetMangling(cursor));
|
||||||
let name = GetNameInBindings(cursor, ..scope .(mangledName.Length));
|
let name = GetNameInBindings(cursor, ..scope .(mangledName.Length));
|
||||||
WriteCustomAttributes(cursor);
|
WriteCustomAttributes(cursor);
|
||||||
|
void LinkNameWhitespace()
|
||||||
|
{
|
||||||
|
if (Flags.HasFlag(.PreseveColumns))
|
||||||
|
str..Append('\n')..Append(cursorIndent);
|
||||||
|
else
|
||||||
|
str.Append(' ');
|
||||||
|
}
|
||||||
if (mangledName == name)
|
if (mangledName == name)
|
||||||
{
|
{
|
||||||
str.Append("[CLink] ");
|
str.Append("[CLink] ");
|
||||||
@@ -891,20 +849,16 @@ abstract class Cpp2BeefGenerator
|
|||||||
{
|
{
|
||||||
str.Append("[LinkName(");
|
str.Append("[LinkName(");
|
||||||
mangledName.QuoteString(str);
|
mangledName.QuoteString(str);
|
||||||
str.Append(")] ");
|
str.Append(")]");
|
||||||
|
LinkNameWhitespace();
|
||||||
return .C;
|
return .C;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
str.Append("[LinkName(\"");
|
str.Append("[LinkName(");
|
||||||
CppWrapperName(cursor, str);
|
ScopeCXString!(Clang.GetCursorPrettyPrinted(cursor, printingPolicy)).QuoteString(str);
|
||||||
str.Append('"');
|
str.Append(")]");
|
||||||
if (!wrapperTemplateChain.IsEmpty)
|
LinkNameWhitespace();
|
||||||
if (templateParams.IsEmpty)
|
|
||||||
str.Append(" + __template_chain");
|
|
||||||
else
|
|
||||||
str.Append(" + CppWrapperF($\"", wrapperTemplateChain, "\")");
|
|
||||||
str.Append(")] ");
|
|
||||||
return .Cpp;
|
return .Cpp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1111,89 +1065,9 @@ abstract class Cpp2BeefGenerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void WriteMethodWrapper(CXCursor cursor)
|
|
||||||
{
|
|
||||||
let parent = Clang.GetCursorType(Clang.GetCursorSemanticParent(cursor));
|
|
||||||
var resultType = Clang.GetCursorResultType(cursor);
|
|
||||||
bool nonStatic = (cursor.kind == .CXXMethod && Clang.CXXMethod_IsStatic(cursor) == 0) || cursor.kind == .Destructor || cursor.kind == .ConversionFunction;
|
|
||||||
|
|
||||||
if (!wrapperTemplateChain.IsEmpty)
|
|
||||||
FlushWrapper();
|
|
||||||
StringView parentSpelling = "\" + __cpp_type + \"";
|
|
||||||
if (wrapperTemplateChain.IsEmpty)
|
|
||||||
parentSpelling = ScopeCXString!::(Clang.GetFullyQualifiedName(parent, printingPolicy, 0));
|
|
||||||
|
|
||||||
if (cursor.kind == .Constructor)
|
|
||||||
wrapperBuf.Append("__type<", parentSpelling, "> ");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wrapperBuf.Append("__type<");
|
|
||||||
wrapperBuf.Append(ScopeCXString!(Clang.GetFullyQualifiedName(resultType, printingPolicy, 0)));
|
|
||||||
wrapperBuf.Append("> ");
|
|
||||||
}
|
|
||||||
CppWrapperName(cursor, wrapperBuf);
|
|
||||||
if (!wrapperTemplateChain.IsEmpty)
|
|
||||||
{
|
|
||||||
if (templateParams.IsEmpty)
|
|
||||||
wrapperBuf.Append("\" + __template_chain + \"");
|
|
||||||
else
|
|
||||||
wrapperBuf.Append("\" + CppWrapperF($\"", wrapperTemplateChain, "\") + \"");
|
|
||||||
}
|
|
||||||
wrapperBuf.Append('(');
|
|
||||||
if (nonStatic)
|
|
||||||
wrapperBuf.Append(parentSpelling, " *self");
|
|
||||||
for (int i < Clang.Cursor_GetNumArguments(cursor))
|
|
||||||
{
|
|
||||||
let arg = Clang.Cursor_GetArgument(cursor, (.)i);
|
|
||||||
if (nonStatic || i > 0) wrapperBuf.Append(", ");
|
|
||||||
wrapperBuf.Append("__type<");
|
|
||||||
wrapperBuf.Append(ScopeCXString!(Clang.GetFullyQualifiedName(Clang.GetCursorType(arg), printingPolicy, 0)));
|
|
||||||
wrapperBuf.Append("> p");
|
|
||||||
i.ToString(wrapperBuf);
|
|
||||||
}
|
|
||||||
wrapperBuf.Append(") { ");
|
|
||||||
if (resultType.kind != .Void) wrapperBuf.Append("return ");
|
|
||||||
if (nonStatic)
|
|
||||||
{
|
|
||||||
if (cursor.kind != .Destructor)
|
|
||||||
wrapperBuf.Append("self->", GetCursorSpelling!(cursor));
|
|
||||||
else
|
|
||||||
wrapperBuf.Append("self->~", parentSpelling);
|
|
||||||
}
|
|
||||||
else if (cursor.kind == .Constructor)
|
|
||||||
wrapperBuf.Append("return ", parentSpelling);
|
|
||||||
else
|
|
||||||
wrapperBuf.Append(fullCursorName);
|
|
||||||
wrapperBuf.Append('(');
|
|
||||||
for (int i < Clang.Cursor_GetNumArguments(cursor))
|
|
||||||
{
|
|
||||||
if (i > 0) wrapperBuf.Append(", ");
|
|
||||||
wrapperBuf.Append('p');
|
|
||||||
i.ToString(wrapperBuf);
|
|
||||||
}
|
|
||||||
wrapperBuf.Append("); }");
|
|
||||||
|
|
||||||
if (wrapperTemplateChain.IsEmpty)
|
|
||||||
{
|
|
||||||
wrapperBuf.Append('\n');
|
|
||||||
FlushWrapper();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (defferedWrapperWrite == null)
|
|
||||||
defferedWrapperWrite = new .(1024);
|
|
||||||
defferedWrapperWrite.Append(cursorIndent, "\t + \"extern \\\"C\\\" ");
|
|
||||||
wrapperBuf.ToString(defferedWrapperWrite);
|
|
||||||
defferedWrapperWrite.Append("\\n\"\n");
|
|
||||||
wrapperBuf.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void FunctionDecl(CXCursor cursor)
|
protected virtual void FunctionDecl(CXCursor cursor)
|
||||||
{
|
{
|
||||||
if (Linkable_Attributes(cursor) == .Cpp)
|
Linkable_Attributes(cursor);
|
||||||
WriteMethodWrapper(cursor);
|
|
||||||
|
|
||||||
AccessSpecifier(cursor);
|
AccessSpecifier(cursor);
|
||||||
str.Append("static extern ");
|
str.Append("static extern ");
|
||||||
WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor));
|
WriteTypeAndName(cursor, Clang.GetCursorResultType(cursor));
|
||||||
@@ -1208,8 +1082,7 @@ abstract class Cpp2BeefGenerator
|
|||||||
{
|
{
|
||||||
void Attributes()
|
void Attributes()
|
||||||
{
|
{
|
||||||
if (Linkable_Attributes(cursor) == .Cpp)
|
Linkable_Attributes(cursor);
|
||||||
WriteMethodWrapper(cursor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let spelling = GetCursorSpelling!(cursor);
|
let spelling = GetCursorSpelling!(cursor);
|
||||||
@@ -1345,18 +1218,6 @@ abstract class Cpp2BeefGenerator
|
|||||||
if (linkLang == .Cpp && type.kind != .LValueReference && type.kind != .RValueReference)
|
if (linkLang == .Cpp && type.kind != .LValueReference && type.kind != .RValueReference)
|
||||||
str.Append("ref ");
|
str.Append("ref ");
|
||||||
WriteTypeAndName(cursor, type);
|
WriteTypeAndName(cursor, type);
|
||||||
if (linkLang == .Cpp)
|
|
||||||
{
|
|
||||||
let wrapperName = CppWrapperName(cursor, ..scope .());
|
|
||||||
str.Append(" { [LinkName(\"", wrapperName, "\")] get; }");
|
|
||||||
wrapperBuf.Append("__type<");
|
|
||||||
wrapperBuf.Append(ScopeCXString!(Clang.GetFullyQualifiedName(type, printingPolicy, 0)));
|
|
||||||
wrapperBuf.Append("> ");
|
|
||||||
if (type.kind != .LValueReference && type.kind != .RValueReference)
|
|
||||||
wrapperBuf.Append('&');
|
|
||||||
wrapperBuf.Append(wrapperName, "() { return ", fullCursorName, "; }\n");
|
|
||||||
FlushWrapper();
|
|
||||||
}
|
|
||||||
str.Append(';');
|
str.Append(';');
|
||||||
default:
|
default:
|
||||||
Runtime.FatalError(scope $"Unhandled var linkage: {_}");
|
Runtime.FatalError(scope $"Unhandled var linkage: {_}");
|
||||||
@@ -1381,15 +1242,16 @@ abstract class Cpp2BeefGenerator
|
|||||||
}, null) != 0;
|
}, null) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Record(CXCursor cursor)
|
protected virtual void Record(CXCursor cursor, bool attributes = true)
|
||||||
{
|
{
|
||||||
WriteCustomAttributes(cursor);
|
WriteCustomAttributes(cursor);
|
||||||
switch (cursor.kind)
|
if (attributes)
|
||||||
{
|
switch (cursor.kind)
|
||||||
case .StructDecl, .ClassDecl: str.Append("[CRepr] ");
|
{
|
||||||
case .UnionDecl: str.Append("[CRepr, Union] ");
|
case .StructDecl, .ClassDecl: str.Append("[CRepr] ");
|
||||||
default: Runtime.FatalError("Unhandled record type");
|
case .UnionDecl: str.Append("[CRepr, Union] ");
|
||||||
}
|
default: Runtime.FatalError("Unhandled record type");
|
||||||
|
}
|
||||||
AccessSpecifier(cursor);
|
AccessSpecifier(cursor);
|
||||||
str.Append("struct ");
|
str.Append("struct ");
|
||||||
if (Clang.Cursor_IsAnonymous(cursor) == 0)
|
if (Clang.Cursor_IsAnonymous(cursor) == 0)
|
||||||
@@ -1483,9 +1345,22 @@ abstract class Cpp2BeefGenerator
|
|||||||
Self self = (.)Internal.UnsafeCastToObject(client_data);
|
Self self = (.)Internal.UnsafeCastToObject(client_data);
|
||||||
if (self.fileInfo.bitfield != default && Clang.Cursor_IsBitField(cursor) == 0)
|
if (self.fileInfo.bitfield != default && Clang.Cursor_IsBitField(cursor) == 0)
|
||||||
self.DumpBitfieldStorage();
|
self.DumpBitfieldStorage();
|
||||||
self.WriteCursor(cursor);
|
|
||||||
if (Clang.Cursor_IsAnonymousRecordDecl(cursor) != 0)
|
if (Clang.Cursor_IsAnonymousRecordDecl(cursor) != 0)
|
||||||
self.str..TrimEnd()..Append(";");
|
{
|
||||||
|
self.BeginCursor(cursor);
|
||||||
|
switch (cursor.kind)
|
||||||
|
{
|
||||||
|
case .StructDecl, .ClassDecl: self.str.Append("[CRepr] ");
|
||||||
|
case .UnionDecl: self.str.Append("[CRepr, Union] ");
|
||||||
|
default: Runtime.FatalError("Unhandled record type");
|
||||||
|
}
|
||||||
|
self.AccessSpecifier(cursor);
|
||||||
|
self.str.Append("using ");
|
||||||
|
self.Record(cursor, attributes: false);
|
||||||
|
self.fileInfo.queuedTokens |= .Semicolon;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
self.WriteCursor(cursor);
|
||||||
return .Continue;
|
return .Continue;
|
||||||
}, Internal.UnsafeCastToPtr(this));
|
}, Internal.UnsafeCastToPtr(this));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user