From 1ea07c20fbd3484e5ad3c119b886c8399a6fb2b3 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Thu, 28 May 2015 18:43:50 -0700 Subject: [PATCH 01/15] Add MIT license --- LICENSE | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..9d8ae20 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2011-2015 Phillip "Antidote" Stephens, Jack Andersen, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file From dde8ac1a1c2e14542a01709c722af389d858899c Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 14 Jun 2015 16:49:02 -1000 Subject: [PATCH 02/15] initial atdna commit --- AthenaCore.pri | 3 +- atdna/atdna.pro | 47 +++++++++++++ atdna/main.cpp | 147 +++++++++++++++++++++++++++++++++++++++++ atdna/test.hpp | 39 +++++++++++ include/Athena/DNA.hpp | 30 +++++++++ 5 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 atdna/atdna.pro create mode 100644 atdna/main.cpp create mode 100644 atdna/test.hpp create mode 100644 include/Athena/DNA.hpp diff --git a/AthenaCore.pri b/AthenaCore.pri index 3a30e01..2b43eed 100644 --- a/AthenaCore.pri +++ b/AthenaCore.pri @@ -62,7 +62,8 @@ HEADERS += \ $$PWD/include/utf8/unchecked.h \ $$PWD/include/Athena/FileInfo.hpp \ $$PWD/include/Athena/Dir.hpp \ - $$PWD/include/gekko_support.h + $$PWD/include/gekko_support.h \ + $$PWD/include/Athena/DNA.hpp win32:HEADERS += \ $$PWD/include/win32_largefilewrapper.h diff --git a/atdna/atdna.pro b/atdna/atdna.pro new file mode 100644 index 0000000..c19b807 --- /dev/null +++ b/atdna/atdna.pro @@ -0,0 +1,47 @@ +TEMPLATE = app +CONFIG += console c++11 +CONFIG -= app_bundle +CONFIG -= qt +QT = +DEFINES += __STDC_LIMIT_MACROS=1 __STDC_CONSTANT_MACROS=1 +QMAKE_CXXFLAGS += -fno-rtti +QMAKE_CXXFLAGS_WARN_ON = -Wno-unused-parameter + +INCLUDEPATH += ../include /run/media/jacko/Extra/llvm-build/usr/include + +SOURCES += \ + main.cpp + +LIBS += -L/run/media/jacko/Extra/llvm-build/usr/lib \ + -lclangFrontendTool -lclangFrontend -lclangTooling -lclangDriver \ + -lclangSerialization -lclangCodeGen -lclangParse -lclangSema \ + -lclangRewriteFrontend -lclangRewrite -lclangAnalysis -lclangEdit \ + -lclangAST -lclangLex -lclangBasic \ + -lLLVMLTO -lLLVMObjCARCOpts -lLLVMLinker -lLLVMBitWriter -lLLVMIRReader \ + -lLLVMXCoreDisassembler -lLLVMXCoreCodeGen -lLLVMXCoreDesc -lLLVMXCoreInfo \ + -lLLVMXCoreAsmPrinter -lLLVMSystemZDisassembler -lLLVMSystemZCodeGen \ + -lLLVMSystemZAsmParser -lLLVMSystemZDesc -lLLVMSystemZInfo -lLLVMSystemZAsmPrinter \ + -lLLVMSparcDisassembler -lLLVMSparcCodeGen -lLLVMSparcAsmParser -lLLVMSparcDesc \ + -lLLVMSparcInfo -lLLVMSparcAsmPrinter -lLLVMPowerPCDisassembler -lLLVMPowerPCCodeGen \ + -lLLVMPowerPCAsmParser -lLLVMPowerPCDesc -lLLVMPowerPCInfo -lLLVMPowerPCAsmPrinter \ + -lLLVMNVPTXCodeGen -lLLVMNVPTXDesc -lLLVMNVPTXInfo -lLLVMNVPTXAsmPrinter \ + -lLLVMMSP430CodeGen -lLLVMMSP430Desc -lLLVMMSP430Info -lLLVMMSP430AsmPrinter \ + -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc \ + -lLLVMMipsInfo -lLLVMMipsAsmPrinter -lLLVMHexagonDisassembler -lLLVMHexagonCodeGen \ + -lLLVMHexagonDesc -lLLVMHexagonInfo -lLLVMCppBackendCodeGen -lLLVMCppBackendInfo \ + -lLLVMBPFCodeGen -lLLVMBPFDesc -lLLVMBPFInfo -lLLVMBPFAsmPrinter -lLLVMARMDisassembler \ + -lLLVMARMCodeGen -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMARMInfo -lLLVMARMAsmPrinter \ + -lLLVMAMDGPUCodeGen -lLLVMAMDGPUAsmParser -lLLVMAMDGPUDesc -lLLVMAMDGPUInfo \ + -lLLVMAMDGPUAsmPrinter -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser \ + -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter -lLLVMAArch64Utils \ + -lLLVMMIRParser -lLLVMAsmParser -lLLVMLibDriver -lLLVMOption -lLLVMDebugInfoPDB -lLLVMTableGen \ + -lLLVMOrcJIT -lLLVMLineEditor -lLLVMInstrumentation -lLLVMX86Disassembler -lLLVMX86AsmParser \ + -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMX86Desc -lLLVMMCDisassembler \ + -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMDebugInfoDWARF \ + -lLLVMPasses -lLLVMipo -lLLVMVectorize -lLLVMInterpreter -lLLVMExecutionEngine \ + -lLLVMRuntimeDyld -lLLVMCodeGen -lLLVMTarget -lLLVMScalarOpts -lLLVMProfileData \ + -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMInstCombine -lLLVMTransformUtils \ + -lLLVMipa -lLLVMMC -lLLVMAnalysis -lLLVMCore -lLLVMSupport -lz -lpthread -lcurses -ldl -g + +HEADERS += \ + test.hpp diff --git a/atdna/main.cpp b/atdna/main.cpp new file mode 100644 index 0000000..d0e3f34 --- /dev/null +++ b/atdna/main.cpp @@ -0,0 +1,147 @@ +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Tooling/Tooling.h" +#include "clang/Lex/Preprocessor.h" +#include "clang/Sema/Sema.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/DeclCXX.h" + +class FindNamedClassVisitor : public clang::RecursiveASTVisitor +{ + clang::ASTContext& context; +public: + explicit FindNamedClassVisitor(clang::ASTContext& ctxin) + : context(ctxin) {} + + bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) + { + if (decl->isInvalidDecl() || !decl->hasDefinition()) + return true; + + if (!decl->getNumBases()) + return true; + + bool foundDNA = false; + for (const clang::CXXBaseSpecifier& base : decl->bases()) + { + llvm::outs() << "BASE " << base.getType().getCanonicalType().getAsString() << "\n"; + if (!base.getType().getCanonicalType().getAsString().compare("struct Athena::io::DNA")) + { + foundDNA = true; + break; + } + } + if (!foundDNA) + return true; + + llvm::outs() << "DECL name " << decl->getQualifiedNameAsString() << "\n"; + llvm::outs() << "DECL kind " << decl->getKindName() << "\n"; + const clang::ASTRecordLayout& layout = context.getASTRecordLayout(decl); + for (const clang::FieldDecl* field : decl->fields()) + { + llvm::outs() << " Field " << field->getName(); + clang::QualType qualType = field->getType(); + const clang::Type* regType = qualType.getTypePtrOrNull(); + if (regType->getTypeClass() == clang::Type::Typedef) + { + const clang::TypedefType* tdType = (const clang::TypedefType*)regType; + llvm::outs() << " Typedef " << tdType->getDecl()->getNameAsString(); + } + else if (regType->getTypeClass() == clang::Type::TemplateSpecialization) + { + const clang::TemplateSpecializationType* tsType = (const clang::TemplateSpecializationType*)regType; + llvm::outs() << " Alias " << tsType->getTemplateName().getAsTemplateDecl()->getNameAsString(); + llvm::outs() << " " << tsType->getNumArgs() << " "; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Expression) + { + llvm::APSInt value; + if (arg.getAsExpr()->isIntegerConstantExpr(value, context)) + { + llvm::outs() << " Expr " << value; + } + } + else if (arg.getKind() == clang::TemplateArgument::Type) + { + llvm::outs() << " Type " << arg.getAsType().getAsString(); + } + } + } + else if (regType->getTypeClass() == clang::Type::Builtin) + { + const clang::BuiltinType* bType = (const clang::BuiltinType*)regType; + llvm::outs() << " Builtin " << bType->getName(clang::PrintingPolicy(clang::LangOptions())); + } + clang::TypeInfo regTypeInfo = context.getTypeInfo(qualType); + llvm::outs() << " Width " << regTypeInfo.Width; + llvm::outs() << " Off " << layout.getFieldOffset(field->getFieldIndex()) << "\n"; + } + /* + if (decl->getQualifiedNameAsString() == "n::m::C") + { + clang::FullSourceLoc fullLoc = context.getFullLoc(decl->getLocStart()); + if (fullLoc.isValid()) + llvm::outs() << "Found declaration at " + << fullLoc.getSpellingLineNumber() << ":" + << fullLoc.getSpellingColumnNumber() << "\n"; + } + */ + return true; + } +}; + +class FindNamedClassConsumer : public clang::ASTConsumer +{ + FindNamedClassVisitor visitor; +public: + explicit FindNamedClassConsumer(clang::ASTContext& context) + : visitor(context) {} + void HandleTranslationUnit(clang::ASTContext& context) + {visitor.TraverseDecl(context.getTranslationUnitDecl());} +}; + +static const char ATDNA_PREAMBLE[] = +"#include \n" +"typedef uint16_t atUint16;\n" +"typedef int16_t atInt16;\n" +"typedef uint32_t atUint32;\n" +"typedef int32_t atInt32;\n" +"typedef uint64_t atUint64;\n" +"typedef int64_t atInt64;\n" +"#define TYPES_HPP\n"; + +class FindNamedClassAction : public clang::ASTFrontendAction +{ + std::unique_ptr preambleBuf; +public: + explicit FindNamedClassAction() + : preambleBuf(llvm::MemoryBuffer::getMemBuffer(ATDNA_PREAMBLE, "ATDNA_PREAMBLE.hpp")) {} + std::unique_ptr CreateASTConsumer(clang::CompilerInstance& compiler, + llvm::StringRef /*filename*/) + { + //compiler.getDiagnostics().setSuppressAllDiagnostics(); + compiler.getPreprocessorOpts().addRemappedFile("ATDNA_PREAMBLE.hpp", preambleBuf.get()); + compiler.getPreprocessorOpts().ChainedIncludes.push_back("ATDNA_PREAMBLE.hpp"); + compiler.getPreprocessorOpts().RetainRemappedFileBuffers = true; + return std::unique_ptr(new FindNamedClassConsumer(compiler.getASTContext())); + } +}; + +int main(int argc, const char** argv) +{ + if (argc > 1) + { + clang::FileManager fman((clang::FileSystemOptions())); + llvm::ErrorOr> buf = fman.getBufferForFile(argv[1]); + std::error_code ec; + if ((ec = buf.getError())) + throw ec; + llvm::Twine buft(buf->get()->getBuffer()); + clang::tooling::runToolOnCodeWithArgs(new FindNamedClassAction, buft, {"-std=c++11"}, argv[1]); + } + return 0; +} + diff --git a/atdna/test.hpp b/atdna/test.hpp new file mode 100644 index 0000000..9ab3829 --- /dev/null +++ b/atdna/test.hpp @@ -0,0 +1,39 @@ +#include +#include +typedef uint32_t atUint32; +typedef uint16_t atUint16; + +enum Endian +{ + LITTLE, + BIG +}; + +template +using Value = T; + +template +using Vector = std::vector; + +namespace Athena +{ +namespace io +{ +class IStreamReader; +class IStreamWriter; +struct DNA +{ + void read(IStreamReader&); + void write(IStreamWriter&) const; +}; +} +} + +using namespace Athena; + +struct ANCSFile : public io::DNA +{ + Value var32; + Value var16; + Vector vec; +}; diff --git a/include/Athena/DNA.hpp b/include/Athena/DNA.hpp new file mode 100644 index 0000000..27a4f4a --- /dev/null +++ b/include/Athena/DNA.hpp @@ -0,0 +1,30 @@ +#ifndef DNA_HPP +#define DNA_HPP + +#include + +namespace Athena +{ +namespace io +{ +class IStreamReader; +class IStreamWriter; + +template +struct DNA +{ + virtual bool read(IStreamReader& reader)=0; + virtual bool write(IStreamWriter& writer) const=0; +}; + +template +using DNAValue = T; + +template +using DNAVector = std::vector; + +} +} + +#endif // DNA_HPP + From c09f06b43646b19748de8f80d4509aca2d15e5a7 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 15 Jun 2015 16:29:53 -1000 Subject: [PATCH 03/15] working release build of atdna --- atdna/atdna.pro | 22 ++++-- atdna/main.cpp | 140 +++++++++++++++++++++++++++----------- atdna/test.hpp | 36 ++-------- include/Athena/DNA.hpp | 29 +++++--- include/Athena/Global.hpp | 5 +- 5 files changed, 143 insertions(+), 89 deletions(-) diff --git a/atdna/atdna.pro b/atdna/atdna.pro index c19b807..ca09897 100644 --- a/atdna/atdna.pro +++ b/atdna/atdna.pro @@ -7,13 +7,22 @@ DEFINES += __STDC_LIMIT_MACROS=1 __STDC_CONSTANT_MACROS=1 QMAKE_CXXFLAGS += -fno-rtti QMAKE_CXXFLAGS_WARN_ON = -Wno-unused-parameter -INCLUDEPATH += ../include /run/media/jacko/Extra/llvm-build/usr/include +INCLUDEPATH += ../include + +CONFIG(debug, debug|release) { + INCLUDEPATH += /run/media/jacko/Extra/llvm-build/usr/include + LIBS += -L/run/media/jacko/Extra/llvm-build/usr/lib + LIBS += -g +} else { + INCLUDEPATH += /run/media/jacko/Extra/llvm-build/usrmin/include + LIBS += -L/run/media/jacko/Extra/llvm-build/usrmin/lib + LIBS += -flto +} SOURCES += \ main.cpp -LIBS += -L/run/media/jacko/Extra/llvm-build/usr/lib \ - -lclangFrontendTool -lclangFrontend -lclangTooling -lclangDriver \ +LIBS += -lclangFrontendTool -lclangFrontend -lclangTooling -lclangDriver \ -lclangSerialization -lclangCodeGen -lclangParse -lclangSema \ -lclangRewriteFrontend -lclangRewrite -lclangAnalysis -lclangEdit \ -lclangAST -lclangLex -lclangBasic \ @@ -29,10 +38,9 @@ LIBS += -L/run/media/jacko/Extra/llvm-build/usr/lib \ -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc \ -lLLVMMipsInfo -lLLVMMipsAsmPrinter -lLLVMHexagonDisassembler -lLLVMHexagonCodeGen \ -lLLVMHexagonDesc -lLLVMHexagonInfo -lLLVMCppBackendCodeGen -lLLVMCppBackendInfo \ - -lLLVMBPFCodeGen -lLLVMBPFDesc -lLLVMBPFInfo -lLLVMBPFAsmPrinter -lLLVMARMDisassembler \ + -lLLVMARMDisassembler \ -lLLVMARMCodeGen -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMARMInfo -lLLVMARMAsmPrinter \ - -lLLVMAMDGPUCodeGen -lLLVMAMDGPUAsmParser -lLLVMAMDGPUDesc -lLLVMAMDGPUInfo \ - -lLLVMAMDGPUAsmPrinter -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser \ + -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser \ -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter -lLLVMAArch64Utils \ -lLLVMMIRParser -lLLVMAsmParser -lLLVMLibDriver -lLLVMOption -lLLVMDebugInfoPDB -lLLVMTableGen \ -lLLVMOrcJIT -lLLVMLineEditor -lLLVMInstrumentation -lLLVMX86Disassembler -lLLVMX86AsmParser \ @@ -41,7 +49,7 @@ LIBS += -L/run/media/jacko/Extra/llvm-build/usr/lib \ -lLLVMPasses -lLLVMipo -lLLVMVectorize -lLLVMInterpreter -lLLVMExecutionEngine \ -lLLVMRuntimeDyld -lLLVMCodeGen -lLLVMTarget -lLLVMScalarOpts -lLLVMProfileData \ -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMInstCombine -lLLVMTransformUtils \ - -lLLVMipa -lLLVMMC -lLLVMAnalysis -lLLVMCore -lLLVMSupport -lz -lpthread -lcurses -ldl -g + -lLLVMipa -lLLVMMC -lLLVMAnalysis -lLLVMCore -lLLVMSupport -lz -lpthread -lcurses -ldl HEADERS += \ test.hpp diff --git a/atdna/main.cpp b/atdna/main.cpp index d0e3f34..585965c 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -3,17 +3,33 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Tooling/Tooling.h" +#include "clang/Tooling/CommonOptionsParser.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/DeclCXX.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/CommandLine.h" -class FindNamedClassVisitor : public clang::RecursiveASTVisitor +static llvm::cl::opt Help("h", llvm::cl::desc("Alias for -help"), llvm::cl::Hidden); + +static llvm::cl::OptionCategory ATDNAFormatCategory("atdna options"); + +static llvm::cl::opt OutputFilename("o", + llvm::cl::desc("Specify output filename"), + llvm::cl::value_desc("filename"), + llvm::cl::Prefix); +static llvm::cl::list InputFilenames(llvm::cl::Positional, + llvm::cl::desc(""), + llvm::cl::OneOrMore); + +class ATDNAVisitor : public clang::RecursiveASTVisitor { clang::ASTContext& context; + llvm::raw_pwrite_stream& fileOut; public: - explicit FindNamedClassVisitor(clang::ASTContext& ctxin) - : context(ctxin) {} + explicit ATDNAVisitor(clang::ASTContext& ctxin, llvm::raw_pwrite_stream& fo) + : context(ctxin), fileOut(fo) {} bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) { @@ -26,16 +42,36 @@ public: bool foundDNA = false; for (const clang::CXXBaseSpecifier& base : decl->bases()) { - llvm::outs() << "BASE " << base.getType().getCanonicalType().getAsString() << "\n"; - if (!base.getType().getCanonicalType().getAsString().compare("struct Athena::io::DNA")) + clang::QualType canonType = base.getType().getCanonicalType(); + //llvm::outs() << "BASE " << canonType.getAsString() << "\n"; + if (!canonType.getAsString().compare(0, 22, "struct Athena::io::DNA")) { + llvm::outs() << "BASE " << canonType.getAsString() << "\n"; foundDNA = true; + + const clang::CXXRecordDecl* recordDecl = canonType.getTypePtr()->getAsCXXRecordDecl(); + if (recordDecl->getTemplateSpecializationKind()) + { + const clang::ClassTemplateSpecializationDecl* specDecl = (const clang::ClassTemplateSpecializationDecl*)recordDecl; + const clang::TemplateArgumentList& templateArgs = specDecl->getTemplateInstantiationArgs(); + if (templateArgs.size()) + { + const clang::TemplateArgument& arg = templateArgs.get(0); + if (arg.getKind() == clang::TemplateArgument::Integral) + { + llvm::outs() << arg.getIntegralType().getAsString() << " INT " << arg.getAsIntegral() << "\n"; + } + } + } + break; } } if (!foundDNA) return true; + fileOut << "one" << "::" << "two"; + llvm::outs() << "DECL name " << decl->getQualifiedNameAsString() << "\n"; llvm::outs() << "DECL kind " << decl->getKindName() << "\n"; const clang::ASTRecordLayout& layout = context.getASTRecordLayout(decl); @@ -52,8 +88,37 @@ public: else if (regType->getTypeClass() == clang::Type::TemplateSpecialization) { const clang::TemplateSpecializationType* tsType = (const clang::TemplateSpecializationType*)regType; - llvm::outs() << " Alias " << tsType->getTemplateName().getAsTemplateDecl()->getNameAsString(); - llvm::outs() << " " << tsType->getNumArgs() << " "; + const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); + const clang::TemplateParameterList* tsList = tsDecl->getTemplateParameters(); + llvm::outs() << " Alias " << tsDecl->getNameAsString(); + llvm::outs() << " " << tsType->getNumArgs() << " " << tsList->size() << "\n"; + for (const clang::NamedDecl* param : *tsList) + { + llvm::outs() << " " << param->getName() << " " << param->getDeclKindName(); + if (param->getKind() == clang::Decl::NonTypeTemplateParm) + { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)param; + const clang::Expr* defArg = nttParm->getDefaultArgument(); + llvm::APSInt result; + if (defArg->isIntegerConstantExpr(result, context)) + { + llvm::outs() << " " << result; + } + } + llvm::outs() << "\n"; + } + /* + const clang::TypeAliasTemplateDecl* tsOrig = llvm::dyn_cast_or_null(tsType->getTemplateName().getAsTemplateDecl()); + if (tsOrig) + { + const clang::TemplateParameterList* params = tsOrig->getTemplateParameters(); + llvm::outs() << " PARAMS:\n"; + for (const clang::NamedDecl* param : *params) + { + llvm::outs() << " " << param->getName() << "\n"; + } + } + */ for (const clang::TemplateArgument& arg : *tsType) { if (arg.getKind() == clang::TemplateArgument::Expression) @@ -93,55 +158,54 @@ public: } }; -class FindNamedClassConsumer : public clang::ASTConsumer +class ATDNAConsumer : public clang::ASTConsumer { - FindNamedClassVisitor visitor; + ATDNAVisitor visitor; public: - explicit FindNamedClassConsumer(clang::ASTContext& context) - : visitor(context) {} + explicit ATDNAConsumer(clang::ASTContext& context, llvm::raw_pwrite_stream& fo) + : visitor(context, fo) {} void HandleTranslationUnit(clang::ASTContext& context) {visitor.TraverseDecl(context.getTranslationUnitDecl());} }; -static const char ATDNA_PREAMBLE[] = -"#include \n" -"typedef uint16_t atUint16;\n" -"typedef int16_t atInt16;\n" -"typedef uint32_t atUint32;\n" -"typedef int32_t atInt32;\n" -"typedef uint64_t atUint64;\n" -"typedef int64_t atInt64;\n" -"#define TYPES_HPP\n"; - -class FindNamedClassAction : public clang::ASTFrontendAction +class ATDNAAction : public clang::ASTFrontendAction { - std::unique_ptr preambleBuf; public: - explicit FindNamedClassAction() - : preambleBuf(llvm::MemoryBuffer::getMemBuffer(ATDNA_PREAMBLE, "ATDNA_PREAMBLE.hpp")) {} + explicit ATDNAAction() {} std::unique_ptr CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef /*filename*/) { - //compiler.getDiagnostics().setSuppressAllDiagnostics(); - compiler.getPreprocessorOpts().addRemappedFile("ATDNA_PREAMBLE.hpp", preambleBuf.get()); - compiler.getPreprocessorOpts().ChainedIncludes.push_back("ATDNA_PREAMBLE.hpp"); - compiler.getPreprocessorOpts().RetainRemappedFileBuffers = true; - return std::unique_ptr(new FindNamedClassConsumer(compiler.getASTContext())); + llvm::raw_pwrite_stream* fileout; + if (OutputFilename.size()) + fileout = compiler.createOutputFile(OutputFilename, false, true, "", "", true); + else + fileout = compiler.createDefaultOutputFile(false, "a", "cpp"); + return std::unique_ptr(new ATDNAConsumer(compiler.getASTContext(), *fileout)); } }; + int main(int argc, const char** argv) { + llvm::cl::ParseCommandLineOptions(argc, argv, "Athena DNA Generator"); + if (Help) + llvm::cl::PrintHelpMessage(); + if (argc > 1) { - clang::FileManager fman((clang::FileSystemOptions())); - llvm::ErrorOr> buf = fman.getBufferForFile(argv[1]); - std::error_code ec; - if ((ec = buf.getError())) - throw ec; - llvm::Twine buft(buf->get()->getBuffer()); - clang::tooling::runToolOnCodeWithArgs(new FindNamedClassAction, buft, {"-std=c++11"}, argv[1]); + llvm::IntrusiveRefCntPtr fman(new clang::FileManager(clang::FileSystemOptions())); + std::vector args = {"clang-tool", + "-fsyntax-only", + "-std=c++11", + "-I/run/media/jacko/Extra/llvm-build/usrmin/lib/clang/3.7.0/include", + "-I/home/jacko/Athena/include"}; + for (int a=1 ; a #include -typedef uint32_t atUint32; -typedef uint16_t atUint16; +#include -enum Endian -{ - LITTLE, - BIG -}; - -template -using Value = T; - -template -using Vector = std::vector; - -namespace Athena -{ -namespace io -{ -class IStreamReader; -class IStreamWriter; -struct DNA -{ - void read(IStreamReader&); - void write(IStreamWriter&) const; -}; -} -} using namespace Athena; -struct ANCSFile : public io::DNA +struct ANCSFile : public io::DNA { - Value var32; - Value var16; - Vector vec; + Value var32; + Value var16; + Vector vec; }; diff --git a/include/Athena/DNA.hpp b/include/Athena/DNA.hpp index 27a4f4a..80921e0 100644 --- a/include/Athena/DNA.hpp +++ b/include/Athena/DNA.hpp @@ -1,28 +1,35 @@ #ifndef DNA_HPP #define DNA_HPP +#include "Global.hpp" +#include "IStreamReader.hpp" +#include "IStreamWriter.hpp" #include namespace Athena { namespace io { -class IStreamReader; -class IStreamWriter; -template +/** + * @brief Base DNA class used against 'atdna' + * + * Athena bundles a build-tool called 'atdna'. This tool functions + * just like the 'clang' compiler, except it emits + */ +template struct DNA { - virtual bool read(IStreamReader& reader)=0; - virtual bool write(IStreamWriter& writer) const=0; + template + using Value = T; + + template + using Vector = std::vector; + + virtual void read(IStreamReader&)=0; + virtual void write(IStreamWriter&) const=0; }; -template -using DNAValue = T; - -template -using DNAVector = std::vector; - } } diff --git a/include/Athena/Global.hpp b/include/Athena/Global.hpp index df93ac5..3353733 100644 --- a/include/Athena/Global.hpp +++ b/include/Athena/Global.hpp @@ -73,15 +73,16 @@ typedef struct stat64 stat64_t; namespace Athena { -enum class SeekOrigin +enum SeekOrigin { Begin, Current, End }; -enum class Endian +enum Endian { + InheritEndian=0, LittleEndian, BigEndian }; From 0452e34150ac9ade2b45d1b26265bf4297217bfe Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 15 Jun 2015 21:11:56 -1000 Subject: [PATCH 04/15] initial working reader/writer values --- atdna/main.cpp | 308 ++++++++++++++++++++++++++++++----------- atdna/test.hpp | 3 +- include/Athena/DNA.hpp | 6 +- 3 files changed, 235 insertions(+), 82 deletions(-) diff --git a/atdna/main.cpp b/atdna/main.cpp index 585965c..fcbb412 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -10,6 +10,7 @@ #include "clang/AST/DeclCXX.h" #include "llvm/Support/Format.h" #include "llvm/Support/CommandLine.h" +#include static llvm::cl::opt Help("h", llvm::cl::desc("Alias for -help"), llvm::cl::Hidden); @@ -23,13 +24,14 @@ static llvm::cl::list InputFilenames(llvm::cl::Positional, llvm::cl::desc(""), llvm::cl::OneOrMore); -class ATDNAVisitor : public clang::RecursiveASTVisitor +class ATDNAEndianVisitor : public clang::RecursiveASTVisitor { clang::ASTContext& context; - llvm::raw_pwrite_stream& fileOut; + std::map& declTracker; public: - explicit ATDNAVisitor(clang::ASTContext& ctxin, llvm::raw_pwrite_stream& fo) - : context(ctxin), fileOut(fo) {} + explicit ATDNAEndianVisitor(clang::ASTContext& ctxin, + std::map& dt) + : context(ctxin), declTracker(dt) {} bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) { @@ -39,16 +41,14 @@ public: if (!decl->getNumBases()) return true; + /* First ensure this inherits from struct Athena::io::DNA */ bool foundDNA = false; for (const clang::CXXBaseSpecifier& base : decl->bases()) { clang::QualType canonType = base.getType().getCanonicalType(); - //llvm::outs() << "BASE " << canonType.getAsString() << "\n"; if (!canonType.getAsString().compare(0, 22, "struct Athena::io::DNA")) { - llvm::outs() << "BASE " << canonType.getAsString() << "\n"; foundDNA = true; - const clang::CXXRecordDecl* recordDecl = canonType.getTypePtr()->getAsCXXRecordDecl(); if (recordDecl->getTemplateSpecializationKind()) { @@ -59,7 +59,11 @@ public: const clang::TemplateArgument& arg = templateArgs.get(0); if (arg.getKind() == clang::TemplateArgument::Integral) { - llvm::outs() << arg.getIntegralType().getAsString() << " INT " << arg.getAsIntegral() << "\n"; + llvm::APSInt endian = arg.getAsIntegral(); + if (endian == 1) /* LittleEndian */ + declTracker[recordDecl] = 1; + else if (endian == 2) /* BigEndian */ + declTracker[recordDecl] = 2; } } } @@ -67,105 +71,253 @@ public: break; } } + return true; + } +}; + +class ATDNAEmitVisitor : public clang::RecursiveASTVisitor +{ + clang::ASTContext& context; + llvm::raw_pwrite_stream& fileOut; + std::map& declTracker; + + static std::string GetOpString(clang::BuiltinType* bType, unsigned width, + std::string fieldName, bool writerPass) + { + if (writerPass) + { + if (bType->isUnsignedInteger()) + { + if (width == 8) + return "writer.writeUByte(" + fieldName + ");"; + else if (width == 16) + return "writer.writeUint16(" + fieldName + ");"; + else if (width == 32) + return "writer.writeUint32(" + fieldName + ");"; + else if (width == 64) + return "writer.writeUint64(" + fieldName + ");"; + } + else if (bType->isSignedInteger()) + { + if (width == 8) + return "writer.writeByte(" + fieldName + ");"; + else if (width == 16) + return "writer.writeInt16(" + fieldName + ");"; + else if (width == 32) + return "writer.writeInt32(" + fieldName + ");"; + else if (width == 64) + return "writer.writeInt64(" + fieldName + ");"; + } + else if (bType->isFloatingPoint()) + { + if (width == 32) + return "writer.writeFloat(" + fieldName + ");"; + else if (width == 64) + return "writer.writeDouble(" + fieldName + ");"; + } + } + else + { + if (bType->isUnsignedInteger()) + { + if (width == 8) + return fieldName + " = reader.readUByte();"; + else if (width == 16) + return fieldName + " = reader.readUint16();"; + else if (width == 32) + return fieldName + " = reader.readUint32();"; + else if (width == 64) + return fieldName + " = reader.readUint64();"; + } + else if (bType->isSignedInteger()) + { + if (width == 8) + return fieldName + " = reader.readByte();"; + else if (width == 16) + return fieldName + " = reader.readInt16();"; + else if (width == 32) + return fieldName + " = reader.readInt32();"; + else if (width == 64) + return fieldName + " = reader.readInt64();"; + } + else if (bType->isFloatingPoint()) + { + if (width == 32) + return fieldName + " = reader.readFloat();"; + else if (width == 64) + return fieldName + " = reader.readDouble();"; + } + } + return std::string(); + } + +public: + explicit ATDNAEmitVisitor(clang::ASTContext& ctxin, + llvm::raw_pwrite_stream& fo, + std::map& dt) + : context(ctxin), fileOut(fo), declTracker(dt) {} + + bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) + { + if (decl->isInvalidDecl() || !decl->hasDefinition()) + return true; + + if (!decl->getNumBases()) + return true; + + /* First ensure this inherits from struct Athena::io::DNA */ + bool foundDNA = false; + for (const clang::CXXBaseSpecifier& base : decl->bases()) + { + clang::QualType canonType = base.getType().getCanonicalType(); + if (!canonType.getAsString().compare(0, 22, "struct Athena::io::DNA")) + { + foundDNA = true; + break; + } + } if (!foundDNA) return true; - fileOut << "one" << "::" << "two"; + /* Context endian */ + int contextEndian = llvm::sys::IsLittleEndianHost ? 1 : 2; + if (declTracker.find(decl) != declTracker.end()) + contextEndian = declTracker[decl]; - llvm::outs() << "DECL name " << decl->getQualifiedNameAsString() << "\n"; - llvm::outs() << "DECL kind " << decl->getKindName() << "\n"; - const clang::ASTRecordLayout& layout = context.getASTRecordLayout(decl); - for (const clang::FieldDecl* field : decl->fields()) + for (int p=0 ; p<2 ; ++p) { - llvm::outs() << " Field " << field->getName(); - clang::QualType qualType = field->getType(); - const clang::Type* regType = qualType.getTypePtrOrNull(); - if (regType->getTypeClass() == clang::Type::Typedef) + if (p) + fileOut << decl->getQualifiedNameAsString() << "::write(Athena::IStreamWriter& writer)\n{\n"; + else + fileOut << decl->getQualifiedNameAsString() << "::read(Athena::IStreamReader& reader)\n{\n"; + int currentEndian = 0; + + for (const clang::FieldDecl* field : decl->fields()) { - const clang::TypedefType* tdType = (const clang::TypedefType*)regType; - llvm::outs() << " Typedef " << tdType->getDecl()->getNameAsString(); - } - else if (regType->getTypeClass() == clang::Type::TemplateSpecialization) - { - const clang::TemplateSpecializationType* tsType = (const clang::TemplateSpecializationType*)regType; - const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); - const clang::TemplateParameterList* tsList = tsDecl->getTemplateParameters(); - llvm::outs() << " Alias " << tsDecl->getNameAsString(); - llvm::outs() << " " << tsType->getNumArgs() << " " << tsList->size() << "\n"; - for (const clang::NamedDecl* param : *tsList) + clang::QualType qualType = field->getType(); + clang::TypeInfo regTypeInfo = context.getTypeInfo(qualType); + const clang::Type* regType = qualType.getTypePtrOrNull(); + if (regType->getTypeClass() == clang::Type::TemplateSpecialization) { - llvm::outs() << " " << param->getName() << " " << param->getDeclKindName(); - if (param->getKind() == clang::Decl::NonTypeTemplateParm) + const clang::TemplateSpecializationType* tsType = (const clang::TemplateSpecializationType*)regType; + const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); + const clang::TemplateParameterList* classParms = tsDecl->getTemplateParameters(); + int endian = 0; + for (const clang::NamedDecl* param : *classParms) { - const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)param; - const clang::Expr* defArg = nttParm->getDefaultArgument(); - llvm::APSInt result; - if (defArg->isIntegerConstantExpr(result, context)) + if (param->getKind() == clang::Decl::NonTypeTemplateParm) { - llvm::outs() << " " << result; + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)param; + const clang::Expr* defArg = nttParm->getDefaultArgument(); + llvm::APSInt result; + if (defArg->isIntegerConstantExpr(result, context)) + endian = result.getExtValue(); } } - llvm::outs() << "\n"; - } - /* - const clang::TypeAliasTemplateDecl* tsOrig = llvm::dyn_cast_or_null(tsType->getTemplateName().getAsTemplateDecl()); - if (tsOrig) - { - const clang::TemplateParameterList* params = tsOrig->getTemplateParameters(); - llvm::outs() << " PARAMS:\n"; - for (const clang::NamedDecl* param : *params) + + if (!tsDecl->getNameAsString().compare("Value")) { - llvm::outs() << " " << param->getName() << "\n"; - } - } - */ - for (const clang::TemplateArgument& arg : *tsType) - { - if (arg.getKind() == clang::TemplateArgument::Expression) - { - llvm::APSInt value; - if (arg.getAsExpr()->isIntegerConstantExpr(value, context)) + + std::string ioOp; + const clang::TemplateArgument* typeArg = nullptr; + for (const clang::TemplateArgument& arg : *tsType) { - llvm::outs() << " Expr " << value; + if (arg.getKind() == clang::TemplateArgument::Type) + { + typeArg = &arg; + clang::BuiltinType* builtinType = (clang::BuiltinType*)arg.getAsType().getCanonicalType().getTypePtr(); + if (builtinType->isBuiltinType()) + ioOp = GetOpString(builtinType, regTypeInfo.Width, field->getName().str(), p); + } + else if (arg.getKind() == clang::TemplateArgument::Expression) + { + llvm::APSInt value; + if (arg.getAsExpr()->isIntegerConstantExpr(value, context)) + endian = value.getExtValue(); + } } + + if (ioOp.empty()) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(tsDecl->getLocation(), context.getDiagnostics().getDiagnosticIDs()->getCustomDiagID(clang::DiagnosticIDs::Fatal, "Athena error")); + diag.AddString("Unable to use type '" + tsDecl->getNameAsString() + "' with Athena"); + if (typeArg) + diag.AddSourceRange(clang::CharSourceRange(clang::TemplateArgumentLoc(*typeArg, clang::TemplateArgumentLocInfo()).getSourceRange(), false)); + continue; + } + + if (!endian) + endian = contextEndian; + if (endian && currentEndian != endian) + { + if (endian == 1) + fileOut << (p ? " writer.setEndian(Athena::LittleEndian);\n" : " reader.setEndian(Athena::LittleEndian);\n"); + else if (endian == 2) + fileOut << (p ? " writer.setEndian(Athena::BigEndian);\n" : " reader.setEndian(Athena::BigEndian);\n"); + currentEndian = endian; + } + + fileOut << " " << ioOp << "\n"; + } - else if (arg.getKind() == clang::TemplateArgument::Type) + else if (!tsDecl->getNameAsString().compare("Vector")) { - llvm::outs() << " Type " << arg.getAsType().getAsString(); + } + } + } - else if (regType->getTypeClass() == clang::Type::Builtin) - { - const clang::BuiltinType* bType = (const clang::BuiltinType*)regType; - llvm::outs() << " Builtin " << bType->getName(clang::PrintingPolicy(clang::LangOptions())); - } - clang::TypeInfo regTypeInfo = context.getTypeInfo(qualType); - llvm::outs() << " Width " << regTypeInfo.Width; - llvm::outs() << " Off " << layout.getFieldOffset(field->getFieldIndex()) << "\n"; + + fileOut << "}\n\n"; + } - /* - if (decl->getQualifiedNameAsString() == "n::m::C") - { - clang::FullSourceLoc fullLoc = context.getFullLoc(decl->getLocStart()); - if (fullLoc.isValid()) - llvm::outs() << "Found declaration at " - << fullLoc.getSpellingLineNumber() << ":" - << fullLoc.getSpellingColumnNumber() << "\n"; - } - */ + return true; } }; class ATDNAConsumer : public clang::ASTConsumer { - ATDNAVisitor visitor; + ATDNAEndianVisitor endianVisitor; + ATDNAEmitVisitor emitVisitor; + llvm::raw_pwrite_stream& fileOut; + std::map declTracker; public: explicit ATDNAConsumer(clang::ASTContext& context, llvm::raw_pwrite_stream& fo) - : visitor(context, fo) {} + : endianVisitor(context, declTracker), emitVisitor(context, fo, declTracker), + fileOut(fo) {} void HandleTranslationUnit(clang::ASTContext& context) - {visitor.TraverseDecl(context.getTranslationUnitDecl());} + { + /* First pass - map explicit endian specifiers */ + endianVisitor.TraverseDecl(context.getTranslationUnitDecl()); + + /* Resolve endian specifiers */ + for (auto decl : declTracker) + { + for (const clang::DeclContext* prevDecl = decl.first->getParent(); + prevDecl ; prevDecl = prevDecl->getParent()) + { + if (prevDecl->isRecord() && + declTracker.find((clang::CXXRecordDecl*)prevDecl) != declTracker.end()) + { + decl.second = declTracker[(clang::CXXRecordDecl*)prevDecl]; + break; + } + } + } + + /* Write file head */ + fileOut << "/* Auto generated atdna implementation */\n" + "#include \n" + "#include \n\n"; + for (const std::string& inputf : InputFilenames) + fileOut << "#include \"" << inputf << "\"\n"; + fileOut << "\n"; + + /* Second pass - emit file */ + emitVisitor.TraverseDecl(context.getTranslationUnitDecl()); + } }; class ATDNAAction : public clang::ASTFrontendAction diff --git a/atdna/test.hpp b/atdna/test.hpp index 5457073..26aacf2 100644 --- a/atdna/test.hpp +++ b/atdna/test.hpp @@ -8,6 +8,7 @@ using namespace Athena; struct ANCSFile : public io::DNA { Value var32; - Value var16; + Value var16; Vector vec; }; + diff --git a/include/Athena/DNA.hpp b/include/Athena/DNA.hpp index 80921e0..2658d81 100644 --- a/include/Athena/DNA.hpp +++ b/include/Athena/DNA.hpp @@ -17,13 +17,13 @@ namespace io * Athena bundles a build-tool called 'atdna'. This tool functions * just like the 'clang' compiler, except it emits */ -template +template struct DNA { - template + template using Value = T; - template + template using Vector = std::vector; virtual void read(IStreamReader&)=0; From 775b51fd0000cebf68679a3d3d7afcf331e65bab Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 15 Jun 2015 21:15:00 -1000 Subject: [PATCH 05/15] minor tweak --- atdna/main.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/atdna/main.cpp b/atdna/main.cpp index fcbb412..3bd577d 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -343,20 +343,17 @@ int main(int argc, const char** argv) if (Help) llvm::cl::PrintHelpMessage(); - if (argc > 1) - { - llvm::IntrusiveRefCntPtr fman(new clang::FileManager(clang::FileSystemOptions())); - std::vector args = {"clang-tool", - "-fsyntax-only", - "-std=c++11", - "-I/run/media/jacko/Extra/llvm-build/usrmin/lib/clang/3.7.0/include", - "-I/home/jacko/Athena/include"}; - for (int a=1 ; a fman(new clang::FileManager(clang::FileSystemOptions())); + std::vector args = {"clang-tool", + "-fsyntax-only", + "-std=c++11", + "-I/run/media/jacko/Extra/llvm-build/usrmin/lib/clang/3.7.0/include", + "-I/home/jacko/Athena/include"}; + for (int a=1 ; a Date: Tue, 16 Jun 2015 14:25:48 -1000 Subject: [PATCH 06/15] further updates to atdna --- PKGBUILD | 2 +- atdna/PKGBUILD | 30 +++ atdna/atdna.pro | 28 ++- atdna/main.cpp | 437 +++++++++++++++++++++++--------------- atdna/test.hpp | 31 ++- include/Athena/DNA.hpp | 10 +- include/Athena/Global.hpp | 1 - include/Athena/Types.hpp | 28 +++ 8 files changed, 381 insertions(+), 186 deletions(-) create mode 100644 atdna/PKGBUILD diff --git a/PKGBUILD b/PKGBUILD index b64c4c6..322b919 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -7,7 +7,7 @@ pkgdesc="Basic cross platform IO library" arch=('i686' 'x86_64') source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git") options=(staticlibs) -license="GPL3" +license="MIT" makedepends=('git qt5-base sed') md5sums=('SKIP') sha256sums=('SKIP') diff --git a/atdna/PKGBUILD b/atdna/PKGBUILD new file mode 100644 index 0000000..a3b422e --- /dev/null +++ b/atdna/PKGBUILD @@ -0,0 +1,30 @@ +# PKGBUILD for atdna +_pkgname=atdna +pkgname=$_pkgname-git +pkgver=v1.0.0 +pkgrel=1 +pkgdesc="Companion DNA utility for libAthena" +arch=('i686' 'x86_64') +source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git") +options=(staticlibs) +license="MIT" +makedepends=('git qt5-base sed clang libathena-git') +depends=('libathena-git') +md5sums=('SKIP') +sha256sums=('SKIP') + +pkgver() { + cd "$srcdir/$_pkgname" + git describe --tags | sed 's|-|.|g' +} + +build() { + cd "$srcdir/$_pkgname" + qmake && make +} + +package() { + cd "$srcdir/$_pkgname" + qmake PREFIX="$pkgdir/usr" && make install +} + diff --git a/atdna/atdna.pro b/atdna/atdna.pro index ca09897..3d113d3 100644 --- a/atdna/atdna.pro +++ b/atdna/atdna.pro @@ -14,8 +14,8 @@ CONFIG(debug, debug|release) { LIBS += -L/run/media/jacko/Extra/llvm-build/usr/lib LIBS += -g } else { - INCLUDEPATH += /run/media/jacko/Extra/llvm-build/usrmin/include - LIBS += -L/run/media/jacko/Extra/llvm-build/usrmin/lib + #INCLUDEPATH += /run/media/jacko/Extra/llvm-build/usrmin/include + #LIBS += -L/run/media/jacko/Extra/llvm-build/usrmin/lib LIBS += -flto } @@ -42,14 +42,30 @@ LIBS += -lclangFrontendTool -lclangFrontend -lclangTooling -lclangDriver \ -lLLVMARMCodeGen -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMARMInfo -lLLVMARMAsmPrinter \ -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser \ -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter -lLLVMAArch64Utils \ - -lLLVMMIRParser -lLLVMAsmParser -lLLVMLibDriver -lLLVMOption -lLLVMDebugInfoPDB -lLLVMTableGen \ - -lLLVMOrcJIT -lLLVMLineEditor -lLLVMInstrumentation -lLLVMX86Disassembler -lLLVMX86AsmParser \ + -lLLVMAsmParser -lLLVMOption -lLLVMTableGen \ + -lLLVMLineEditor -lLLVMInstrumentation -lLLVMX86Disassembler -lLLVMX86AsmParser \ -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMX86Desc -lLLVMMCDisassembler \ - -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMDebugInfoDWARF \ - -lLLVMPasses -lLLVMipo -lLLVMVectorize -lLLVMInterpreter -lLLVMExecutionEngine \ + -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT \ + -lLLVMipo -lLLVMVectorize -lLLVMInterpreter -lLLVMExecutionEngine \ -lLLVMRuntimeDyld -lLLVMCodeGen -lLLVMTarget -lLLVMScalarOpts -lLLVMProfileData \ -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMInstCombine -lLLVMTransformUtils \ -lLLVMipa -lLLVMMC -lLLVMAnalysis -lLLVMCore -lLLVMSupport -lz -lpthread -lcurses -ldl HEADERS += \ test.hpp + +unix { + isEmpty(PREFIX) { + PREFIX = /usr/local + } + utilFiles.path = $$PREFIX/bin + INSTALLS += utilFiles +} + +win32 { + isEmpty(PREFIX) { + PREFIX = $$PWD/pkg + } + utilFiles.path = $$PREFIX/bin + INSTALLS += utilFiles +} diff --git a/atdna/main.cpp b/atdna/main.cpp index 3bd577d..336f0e4 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -3,14 +3,13 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Tooling/Tooling.h" -#include "clang/Tooling/CommonOptionsParser.h" #include "clang/Lex/Preprocessor.h" #include "clang/Sema/Sema.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/DeclCXX.h" +#include "clang/Basic/Version.h" #include "llvm/Support/Format.h" #include "llvm/Support/CommandLine.h" -#include static llvm::cl::opt Help("h", llvm::cl::desc("Alias for -help"), llvm::cl::Hidden); @@ -20,132 +19,133 @@ static llvm::cl::opt OutputFilename("o", llvm::cl::desc("Specify output filename"), llvm::cl::value_desc("filename"), llvm::cl::Prefix); + static llvm::cl::list InputFilenames(llvm::cl::Positional, llvm::cl::desc(""), llvm::cl::OneOrMore); -class ATDNAEndianVisitor : public clang::RecursiveASTVisitor -{ - clang::ASTContext& context; - std::map& declTracker; -public: - explicit ATDNAEndianVisitor(clang::ASTContext& ctxin, - std::map& dt) - : context(ctxin), declTracker(dt) {} - - bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) - { - if (decl->isInvalidDecl() || !decl->hasDefinition()) - return true; - - if (!decl->getNumBases()) - return true; - - /* First ensure this inherits from struct Athena::io::DNA */ - bool foundDNA = false; - for (const clang::CXXBaseSpecifier& base : decl->bases()) - { - clang::QualType canonType = base.getType().getCanonicalType(); - if (!canonType.getAsString().compare(0, 22, "struct Athena::io::DNA")) - { - foundDNA = true; - const clang::CXXRecordDecl* recordDecl = canonType.getTypePtr()->getAsCXXRecordDecl(); - if (recordDecl->getTemplateSpecializationKind()) - { - const clang::ClassTemplateSpecializationDecl* specDecl = (const clang::ClassTemplateSpecializationDecl*)recordDecl; - const clang::TemplateArgumentList& templateArgs = specDecl->getTemplateInstantiationArgs(); - if (templateArgs.size()) - { - const clang::TemplateArgument& arg = templateArgs.get(0); - if (arg.getKind() == clang::TemplateArgument::Integral) - { - llvm::APSInt endian = arg.getAsIntegral(); - if (endian == 1) /* LittleEndian */ - declTracker[recordDecl] = 1; - else if (endian == 2) /* BigEndian */ - declTracker[recordDecl] = 2; - } - } - } - - break; - } - } - return true; - } -}; - class ATDNAEmitVisitor : public clang::RecursiveASTVisitor { clang::ASTContext& context; - llvm::raw_pwrite_stream& fileOut; - std::map& declTracker; + llvm::raw_fd_ostream& fileOut; - static std::string GetOpString(clang::BuiltinType* bType, unsigned width, - std::string fieldName, bool writerPass) + std::string GetOpString(const clang::Type* theType, unsigned width, + std::string fieldName, bool writerPass) { if (writerPass) { - if (bType->isUnsignedInteger()) + if (theType->isBuiltinType()) { - if (width == 8) - return "writer.writeUByte(" + fieldName + ");"; - else if (width == 16) - return "writer.writeUint16(" + fieldName + ");"; - else if (width == 32) - return "writer.writeUint32(" + fieldName + ");"; - else if (width == 64) - return "writer.writeUint64(" + fieldName + ");"; + const clang::BuiltinType* bType = (clang::BuiltinType*)theType; + if (bType->isUnsignedInteger()) + { + if (width == 8) + return "writer.writeUByte(" + fieldName + ");"; + else if (width == 16) + return "writer.writeUint16(" + fieldName + ");"; + else if (width == 32) + return "writer.writeUint32(" + fieldName + ");"; + else if (width == 64) + return "writer.writeUint64(" + fieldName + ");"; + } + else if (bType->isSignedInteger()) + { + if (width == 8) + return "writer.writeByte(" + fieldName + ");"; + else if (width == 16) + return "writer.writeInt16(" + fieldName + ");"; + else if (width == 32) + return "writer.writeInt32(" + fieldName + ");"; + else if (width == 64) + return "writer.writeInt64(" + fieldName + ");"; + } + else if (bType->isFloatingPoint()) + { + if (width == 32) + return "writer.writeFloat(" + fieldName + ");"; + else if (width == 64) + return "writer.writeDouble(" + fieldName + ");"; + } } - else if (bType->isSignedInteger()) + else if (theType->isRecordType()) { - if (width == 8) - return "writer.writeByte(" + fieldName + ");"; - else if (width == 16) - return "writer.writeInt16(" + fieldName + ");"; - else if (width == 32) - return "writer.writeInt32(" + fieldName + ");"; - else if (width == 64) - return "writer.writeInt64(" + fieldName + ");"; - } - else if (bType->isFloatingPoint()) - { - if (width == 32) - return "writer.writeFloat(" + fieldName + ");"; - else if (width == 64) - return "writer.writeDouble(" + fieldName + ");"; + const clang::RecordDecl* rDecl = ((clang::RecordType*)theType)->getDecl(); + for (const clang::FieldDecl* field : rDecl->fields()) + { + if (!field->getNameAsString().compare("clangVec")) + { + const clang::VectorType* vType = (clang::VectorType*)field->getType().getTypePtr(); + if (vType->isVectorType()) + { + const clang::BuiltinType* eType = (clang::BuiltinType*)vType->getElementType().getTypePtr(); + if (!eType->isBuiltinType() || !eType->isFloatingPoint() || + context.getTypeInfo(eType).Width != 32) + continue; + if (vType->getNumElements() == 3) + return "writer.writeVec3f(" + fieldName + ");"; + else if (vType->getNumElements() == 4) + return "writer.writeVec4f(" + fieldName + ");"; + } + } + } } } else { - if (bType->isUnsignedInteger()) + if (theType->isBuiltinType()) { - if (width == 8) - return fieldName + " = reader.readUByte();"; - else if (width == 16) - return fieldName + " = reader.readUint16();"; - else if (width == 32) - return fieldName + " = reader.readUint32();"; - else if (width == 64) - return fieldName + " = reader.readUint64();"; + const clang::BuiltinType* bType = (clang::BuiltinType*)theType; + if (bType->isUnsignedInteger()) + { + if (width == 8) + return "reader.readUByte()"; + else if (width == 16) + return "reader.readUint16()"; + else if (width == 32) + return "reader.readUint32()"; + else if (width == 64) + return "reader.readUint64()"; + } + else if (bType->isSignedInteger()) + { + if (width == 8) + return "reader.readByte()"; + else if (width == 16) + return "reader.readInt16()"; + else if (width == 32) + return "reader.readInt32()"; + else if (width == 64) + return "reader.readInt64()"; + } + else if (bType->isFloatingPoint()) + { + if (width == 32) + return "reader.readFloat()"; + else if (width == 64) + return "reader.readDouble()"; + } } - else if (bType->isSignedInteger()) + else if (theType->isRecordType()) { - if (width == 8) - return fieldName + " = reader.readByte();"; - else if (width == 16) - return fieldName + " = reader.readInt16();"; - else if (width == 32) - return fieldName + " = reader.readInt32();"; - else if (width == 64) - return fieldName + " = reader.readInt64();"; - } - else if (bType->isFloatingPoint()) - { - if (width == 32) - return fieldName + " = reader.readFloat();"; - else if (width == 64) - return fieldName + " = reader.readDouble();"; + const clang::RecordDecl* rDecl = ((clang::RecordType*)theType)->getDecl(); + for (const clang::FieldDecl* field : rDecl->fields()) + { + if (!field->getNameAsString().compare("clangVec")) + { + const clang::VectorType* vType = (clang::VectorType*)field->getType().getTypePtr(); + if (vType->isVectorType()) + { + const clang::BuiltinType* eType = (clang::BuiltinType*)vType->getElementType().getTypePtr(); + if (!eType->isBuiltinType() || !eType->isFloatingPoint() || + context.getTypeInfo(eType).Width != 32) + continue; + if (vType->getNumElements() == 3) + return "reader.readVec3f()"; + else if (vType->getNumElements() == 4) + return "reader.readVec4f()"; + } + } + } } } return std::string(); @@ -153,9 +153,8 @@ class ATDNAEmitVisitor : public clang::RecursiveASTVisitor public: explicit ATDNAEmitVisitor(clang::ASTContext& ctxin, - llvm::raw_pwrite_stream& fo, - std::map& dt) - : context(ctxin), fileOut(fo), declTracker(dt) {} + llvm::raw_fd_ostream& fo) + : context(ctxin), fileOut(fo) {} bool VisitCXXRecordDecl(clang::CXXRecordDecl* decl) { @@ -179,44 +178,43 @@ public: if (!foundDNA) return true; - /* Context endian */ - int contextEndian = llvm::sys::IsLittleEndianHost ? 1 : 2; - if (declTracker.find(decl) != declTracker.end()) - contextEndian = declTracker[decl]; - for (int p=0 ; p<2 ; ++p) { if (p) - fileOut << decl->getQualifiedNameAsString() << "::write(Athena::IStreamWriter& writer)\n{\n"; + fileOut << "void " << decl->getQualifiedNameAsString() << "::write(Athena::IStreamWriter& writer) const\n{\n"; else - fileOut << decl->getQualifiedNameAsString() << "::read(Athena::IStreamReader& reader)\n{\n"; - int currentEndian = 0; + fileOut << "void " << decl->getQualifiedNameAsString() << "::read(Athena::IStreamReader& reader)\n{\n"; + int currentEndian = -1; for (const clang::FieldDecl* field : decl->fields()) { clang::QualType qualType = field->getType(); clang::TypeInfo regTypeInfo = context.getTypeInfo(qualType); const clang::Type* regType = qualType.getTypePtrOrNull(); + if (regType->getTypeClass() == clang::Type::Elaborated) + regType = regType->getUnqualifiedDesugaredType(); + if (regType->getTypeClass() == clang::Type::TemplateSpecialization) { const clang::TemplateSpecializationType* tsType = (const clang::TemplateSpecializationType*)regType; const clang::TemplateDecl* tsDecl = tsType->getTemplateName().getAsTemplateDecl(); const clang::TemplateParameterList* classParms = tsDecl->getTemplateParameters(); - int endian = 0; - for (const clang::NamedDecl* param : *classParms) - { - if (param->getKind() == clang::Decl::NonTypeTemplateParm) - { - const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)param; - const clang::Expr* defArg = nttParm->getDefaultArgument(); - llvm::APSInt result; - if (defArg->isIntegerConstantExpr(result, context)) - endian = result.getExtValue(); - } - } if (!tsDecl->getNameAsString().compare("Value")) { + int endian = -1; + if (classParms->size() >= 2) + { + const clang::NamedDecl* endianParm = classParms->getParam(1); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) + { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + const clang::Expr* defArg = nttParm->getDefaultArgument(); + llvm::APSInt result; + if (defArg->isIntegerConstantExpr(result, context)) + endian = result.getSExtValue(); + } + } std::string ioOp; const clang::TemplateArgument* typeArg = nullptr; @@ -225,48 +223,158 @@ public: if (arg.getKind() == clang::TemplateArgument::Type) { typeArg = &arg; - clang::BuiltinType* builtinType = (clang::BuiltinType*)arg.getAsType().getCanonicalType().getTypePtr(); - if (builtinType->isBuiltinType()) - ioOp = GetOpString(builtinType, regTypeInfo.Width, field->getName().str(), p); + const clang::Type* type = arg.getAsType().getCanonicalType().getTypePtr(); + ioOp = GetOpString(type, regTypeInfo.Width, field->getName().str(), p); } else if (arg.getKind() == clang::TemplateArgument::Expression) { llvm::APSInt value; if (arg.getAsExpr()->isIntegerConstantExpr(value, context)) - endian = value.getExtValue(); + endian = value.getSExtValue(); } } if (ioOp.empty()) { - clang::DiagnosticBuilder diag = context.getDiagnostics().Report(tsDecl->getLocation(), context.getDiagnostics().getDiagnosticIDs()->getCustomDiagID(clang::DiagnosticIDs::Fatal, "Athena error")); + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(tsDecl->getLocation(), context.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Fatal, "Athena error")); diag.AddString("Unable to use type '" + tsDecl->getNameAsString() + "' with Athena"); if (typeArg) diag.AddSourceRange(clang::CharSourceRange(clang::TemplateArgumentLoc(*typeArg, clang::TemplateArgumentLocInfo()).getSourceRange(), false)); continue; } - if (!endian) - endian = contextEndian; - if (endian && currentEndian != endian) + if (currentEndian != endian) { - if (endian == 1) + if (endian == 0) fileOut << (p ? " writer.setEndian(Athena::LittleEndian);\n" : " reader.setEndian(Athena::LittleEndian);\n"); - else if (endian == 2) + else if (endian == 1) fileOut << (p ? " writer.setEndian(Athena::BigEndian);\n" : " reader.setEndian(Athena::BigEndian);\n"); currentEndian = endian; } - fileOut << " " << ioOp << "\n"; - + if (!p) + fileOut << " " << field->getName() << " = " << ioOp << ";\n"; + else + fileOut << " " << ioOp << "\n"; } else if (!tsDecl->getNameAsString().compare("Vector")) { + int endian = -1; + if (classParms->size() >= 3) + { + const clang::NamedDecl* endianParm = classParms->getParam(2); + if (endianParm->getKind() == clang::Decl::NonTypeTemplateParm) + { + const clang::NonTypeTemplateParmDecl* nttParm = (clang::NonTypeTemplateParmDecl*)endianParm; + const clang::Expr* defArg = nttParm->getDefaultArgument(); + llvm::APSInt result; + if (defArg->isIntegerConstantExpr(result, context)) + endian = result.getSExtValue(); + } + } + + std::string ioOp; + std::string sizeVar; + const clang::TemplateArgument* typeArg = nullptr; + const clang::TemplateArgument* sizeArg = nullptr; + size_t idx = 0; + for (const clang::TemplateArgument& arg : *tsType) + { + if (arg.getKind() == clang::TemplateArgument::Type) + { + typeArg = &arg; + const clang::Type* type = arg.getAsType().getCanonicalType().getTypePtr(); + clang::TypeInfo typeInfo = context.getTypeInfo(arg.getAsType().getCanonicalType()); + ioOp = GetOpString(type, typeInfo.Width, "*it", p); + } + else if (arg.getKind() == clang::TemplateArgument::Expression) + { + const clang::Expr* expr = arg.getAsExpr(); + if (idx == 1) + { + sizeArg = &arg; + const clang::UnaryExprOrTypeTraitExpr* uExpr = (clang::UnaryExprOrTypeTraitExpr*)expr; + if (uExpr->getStmtClass() == clang::Stmt::UnaryExprOrTypeTraitExprClass && + uExpr->getKind() == clang::UETT_SizeOf) + { + const clang::Expr* argExpr = uExpr->getArgumentExpr(); + while (argExpr->getStmtClass() == clang::Stmt::ParenExprClass) + argExpr = ((clang::ParenExpr*)argExpr)->getSubExpr(); + if (argExpr->getStmtClass() == clang::Stmt::DeclRefExprClass) + { + const clang::DeclRefExpr* refExpr = (clang::DeclRefExpr*)argExpr; + sizeVar = refExpr->getFoundDecl()->getNameAsString(); + } + } + } + else if (idx == 2) + { + llvm::APSInt value; + if (expr->isIntegerConstantExpr(value, context)) + endian = value.getSExtValue(); + } + } + ++idx; + } + + if (ioOp.empty()) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(tsDecl->getLocation(), context.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Fatal, "Athena error")); + diag.AddString("Unable to use type '" + tsDecl->getNameAsString() + "' with Athena"); + if (typeArg) + diag.AddSourceRange(clang::CharSourceRange(clang::TemplateArgumentLoc(*typeArg, clang::TemplateArgumentLocInfo()).getSourceRange(), false)); + continue; + } + + if (sizeVar.empty()) + { + clang::DiagnosticBuilder diag = context.getDiagnostics().Report(tsDecl->getLocation(), context.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Fatal, "Athena error")); + diag.AddString("Unable to use type '" + tsDecl->getNameAsString() + "' with Athena"); + if (sizeArg) + diag.AddSourceRange(clang::CharSourceRange(clang::TemplateArgumentLoc(*sizeArg, clang::TemplateArgumentLocInfo()).getSourceRange(), false)); + continue; + } + + if (currentEndian != endian) + { + if (endian == 0) + fileOut << (p ? " writer.setEndian(Athena::LittleEndian);\n" : " reader.setEndian(Athena::LittleEndian);\n"); + else if (endian == 1) + fileOut << (p ? " writer.setEndian(Athena::BigEndian);\n" : " reader.setEndian(Athena::BigEndian);\n"); + currentEndian = endian; + } + + if (!p) + { + fileOut << " " << field->getName() << ".clear();\n"; + fileOut << " " << field->getName() << ".reserve(" << sizeVar << ");\n"; + fileOut << " for (int i=0 ; i<" << sizeVar << " ; ++i)\n " << field->getName() << ".push_back(" << ioOp << ");\n"; + } + else + fileOut << " for (int i=0, auto it=" << field->getName() << ".begin() ; i<" << sizeVar << " && it!=" << field->getName() << ".end() ; ++i, ++it)\n " << ioOp << "\n"; } } + else if (regType->getTypeClass() == clang::Type::Record) + { + const clang::CXXRecordDecl* cxxRDecl = regType->getAsCXXRecordDecl(); + if (cxxRDecl) + { + for (const clang::CXXBaseSpecifier& base : cxxRDecl->bases()) + { + clang::QualType canonType = base.getType().getCanonicalType(); + if (!canonType.getAsString().compare(0, 22, "struct Athena::io::DNA")) + { + fileOut << " " << field->getNameAsString() << (p ? ".write(writer);\n" : ".read(reader);\n"); + currentEndian = -1; + break; + } + } + } + } + } fileOut << "}\n\n"; @@ -279,36 +387,17 @@ public: class ATDNAConsumer : public clang::ASTConsumer { - ATDNAEndianVisitor endianVisitor; ATDNAEmitVisitor emitVisitor; - llvm::raw_pwrite_stream& fileOut; - std::map declTracker; + llvm::raw_fd_ostream& fileOut; public: - explicit ATDNAConsumer(clang::ASTContext& context, llvm::raw_pwrite_stream& fo) - : endianVisitor(context, declTracker), emitVisitor(context, fo, declTracker), + explicit ATDNAConsumer(clang::ASTContext& context, llvm::raw_fd_ostream& fo) + : emitVisitor(context, fo), fileOut(fo) {} void HandleTranslationUnit(clang::ASTContext& context) { - /* First pass - map explicit endian specifiers */ - endianVisitor.TraverseDecl(context.getTranslationUnitDecl()); - - /* Resolve endian specifiers */ - for (auto decl : declTracker) - { - for (const clang::DeclContext* prevDecl = decl.first->getParent(); - prevDecl ; prevDecl = prevDecl->getParent()) - { - if (prevDecl->isRecord() && - declTracker.find((clang::CXXRecordDecl*)prevDecl) != declTracker.end()) - { - decl.second = declTracker[(clang::CXXRecordDecl*)prevDecl]; - break; - } - } - } - /* Write file head */ fileOut << "/* Auto generated atdna implementation */\n" + "#include \n" "#include \n" "#include \n\n"; for (const std::string& inputf : InputFilenames) @@ -327,7 +416,7 @@ public: std::unique_ptr CreateASTConsumer(clang::CompilerInstance& compiler, llvm::StringRef /*filename*/) { - llvm::raw_pwrite_stream* fileout; + llvm::raw_fd_ostream* fileout; if (OutputFilename.size()) fileout = compiler.createOutputFile(OutputFilename, false, true, "", "", true); else @@ -343,14 +432,22 @@ int main(int argc, const char** argv) if (Help) llvm::cl::PrintHelpMessage(); - llvm::IntrusiveRefCntPtr fman(new clang::FileManager(clang::FileSystemOptions())); std::vector args = {"clang-tool", "-fsyntax-only", - "-std=c++11", - "-I/run/media/jacko/Extra/llvm-build/usrmin/lib/clang/3.7.0/include", - "-I/home/jacko/Athena/include"}; + "-std=c++11"}; + + llvm::IntrusiveRefCntPtr fman(new clang::FileManager(clang::FileSystemOptions())); + const clang::FileEntry* selfEntry = fman->getFile(argv[0]); + if (selfEntry && selfEntry->isValid()) + { + std::string base(selfEntry->getDir()->getName()); + args.push_back("-I" + base + "/clang/" + CLANG_VERSION_STRING + "/include"); + args.push_back("-I" + base); + } + for (int a=1 ; a -#include #include - using namespace Athena; -struct ANCSFile : public io::DNA +struct ANCSSubFile : public io::DNA { - Value var32; - Value var16; - Vector vec; + DECL_DNA + Value sub1; + Value sub2; +}; + +struct ANCSFile : public io::DNA +{ + DECL_DNA + Value var32; + Value var16; + Value vec3; + Value vec4; + + struct ANCSNestedSubFile : public io::DNA + { + DECL_DNA + Value nestSub1; + Value nestSub2; + } nestedSubFile; + + ANCSSubFile subFile; + + Value arrCount; + Vector array; }; diff --git a/include/Athena/DNA.hpp b/include/Athena/DNA.hpp index 2658d81..31ad754 100644 --- a/include/Athena/DNA.hpp +++ b/include/Athena/DNA.hpp @@ -5,6 +5,7 @@ #include "IStreamReader.hpp" #include "IStreamWriter.hpp" #include +#include namespace Athena { @@ -17,19 +18,24 @@ namespace io * Athena bundles a build-tool called 'atdna'. This tool functions * just like the 'clang' compiler, except it emits */ -template +template struct DNA { template using Value = T; - template + template using Vector = std::vector; virtual void read(IStreamReader&)=0; virtual void write(IStreamWriter&) const=0; }; +/** Macro to automatically declare read/write methods in subclasses */ +#define DECL_DNA \ + void read(Athena::io::IStreamReader&); \ + void write(Athena::io::IStreamWriter&) const; \ + } } diff --git a/include/Athena/Global.hpp b/include/Athena/Global.hpp index 3353733..c9b6d16 100644 --- a/include/Athena/Global.hpp +++ b/include/Athena/Global.hpp @@ -82,7 +82,6 @@ enum SeekOrigin enum Endian { - InheritEndian=0, LittleEndian, BigEndian }; diff --git a/include/Athena/Types.hpp b/include/Athena/Types.hpp index 7e55f11..53445df 100644 --- a/include/Athena/Types.hpp +++ b/include/Athena/Types.hpp @@ -56,6 +56,34 @@ typedef unsigned long atUint32; typedef signed long long atInt64; typedef unsigned long long atUint64; +// Vector types +#if __SSE__ +#include +#endif + +typedef union +{ +#if __clang__ + float clangVec __attribute__((__vector_size__(12))); +#endif +#if __SSE__ + __m128 mVec128; +#endif + float vec[3]; +} atVec3f; + +typedef union +{ +#if __clang__ + float clangVec __attribute__((__vector_size__(16))); +#endif +#if __SSE__ + __m128 mVec128; +#endif + float vec[4]; +} atVec4f; + + #ifndef NULL #ifdef __cplusplus #define NULL 0 From 2bb60ab1524bb7d3a9976facd1e7ae45940bc821 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 16 Jun 2015 14:33:04 -1000 Subject: [PATCH 07/15] build system tweaks --- PKGBUILD | 4 ++-- atdna/PKGBUILD | 8 ++++---- atdna/atdna.pro | 2 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 322b919..949c66e 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,11 +1,11 @@ # PKGBUILD for libAthena _pkgname=libathena pkgname=$_pkgname-git -pkgver=v1.0.0 +pkgver=1.1.0.17.gfb722a9 pkgrel=1 pkgdesc="Basic cross platform IO library" arch=('i686' 'x86_64') -source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git") +source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git#branch=atdna") options=(staticlibs) license="MIT" makedepends=('git qt5-base sed') diff --git a/atdna/PKGBUILD b/atdna/PKGBUILD index a3b422e..c52f576 100644 --- a/atdna/PKGBUILD +++ b/atdna/PKGBUILD @@ -1,11 +1,11 @@ # PKGBUILD for atdna _pkgname=atdna pkgname=$_pkgname-git -pkgver=v1.0.0 +pkgver=1.1.0.17.gfb722a9 pkgrel=1 pkgdesc="Companion DNA utility for libAthena" arch=('i686' 'x86_64') -source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git") +source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git#branch=atdna") options=(staticlibs) license="MIT" makedepends=('git qt5-base sed clang libathena-git') @@ -19,12 +19,12 @@ pkgver() { } build() { - cd "$srcdir/$_pkgname" + cd "$srcdir/$_pkgname/atdna" qmake && make } package() { - cd "$srcdir/$_pkgname" + cd "$srcdir/$_pkgname/atdna" qmake PREFIX="$pkgdir/usr" && make install } diff --git a/atdna/atdna.pro b/atdna/atdna.pro index 3d113d3..ddf2da0 100644 --- a/atdna/atdna.pro +++ b/atdna/atdna.pro @@ -59,6 +59,7 @@ unix { PREFIX = /usr/local } utilFiles.path = $$PREFIX/bin + utilFiles.files = $$OUT_PWD/atdna INSTALLS += utilFiles } @@ -67,5 +68,6 @@ win32 { PREFIX = $$PWD/pkg } utilFiles.path = $$PREFIX/bin + utilFiles.files = $$OUT_PWD/atdna INSTALLS += utilFiles } From 96ed8a2ce20533790c74b0e7033f360940500c70 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 16 Jun 2015 14:57:06 -1000 Subject: [PATCH 08/15] more build system tweaks --- PKGBUILD | 2 +- atdna/PKGBUILD | 4 ++-- atdna/atdna.pro | 3 +++ atdna/main.cpp | 20 ++++++++++---------- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 949c66e..15936d8 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -19,7 +19,7 @@ pkgver() { build() { cd "$srcdir/$_pkgname" - qmake && make + qmake PREFIX="$pkgdir/usr" && make } package() { diff --git a/atdna/PKGBUILD b/atdna/PKGBUILD index c52f576..c17db0e 100644 --- a/atdna/PKGBUILD +++ b/atdna/PKGBUILD @@ -1,7 +1,7 @@ # PKGBUILD for atdna _pkgname=atdna pkgname=$_pkgname-git -pkgver=1.1.0.17.gfb722a9 +pkgver=1.1.0.18.g2bb60ab pkgrel=1 pkgdesc="Companion DNA utility for libAthena" arch=('i686' 'x86_64') @@ -20,7 +20,7 @@ pkgver() { build() { cd "$srcdir/$_pkgname/atdna" - qmake && make + qmake PREFIX="$pkgdir/usr" && make } package() { diff --git a/atdna/atdna.pro b/atdna/atdna.pro index ddf2da0..744e6b5 100644 --- a/atdna/atdna.pro +++ b/atdna/atdna.pro @@ -71,3 +71,6 @@ win32 { utilFiles.files = $$OUT_PWD/atdna INSTALLS += utilFiles } + +DEFINES += SYSTEM_PREFIX="$$PREFIX" + diff --git a/atdna/main.cpp b/atdna/main.cpp index 336f0e4..75068a0 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -11,6 +11,13 @@ #include "llvm/Support/Format.h" #include "llvm/Support/CommandLine.h" +#ifndef SYSTEM_PREFIX +#define SYSTEM_PREFIX /usr/local +#endif + +#define XSTR(s) STR(s) +#define STR(s) #s + static llvm::cl::opt Help("h", llvm::cl::desc("Alias for -help"), llvm::cl::Hidden); static llvm::cl::OptionCategory ATDNAFormatCategory("atdna options"); @@ -435,19 +442,12 @@ int main(int argc, const char** argv) std::vector args = {"clang-tool", "-fsyntax-only", "-std=c++11"}; - - llvm::IntrusiveRefCntPtr fman(new clang::FileManager(clang::FileSystemOptions())); - const clang::FileEntry* selfEntry = fman->getFile(argv[0]); - if (selfEntry && selfEntry->isValid()) - { - std::string base(selfEntry->getDir()->getName()); - args.push_back("-I" + base + "/clang/" + CLANG_VERSION_STRING + "/include"); - args.push_back("-I" + base); - } - + args.push_back("-I" + std::string(XSTR(SYSTEM_PREFIX)) + "/lib/clang/" + CLANG_VERSION_STRING + "/include"); + llvm::outs() << args.back() << "\n"; for (int a=1 ; a fman(new clang::FileManager(clang::FileSystemOptions())); clang::tooling::ToolInvocation TI(args, new ATDNAAction, fman.get()); if (TI.run()) return 0; From b195c194f7c933d7194fb64c0a4d571c9e5b2b59 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 16 Jun 2015 15:02:58 -1000 Subject: [PATCH 09/15] futher adjustments --- atdna/PKGBUILD | 6 +++--- atdna/atdna.pro | 8 +++++++- atdna/main.cpp | 1 - 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/atdna/PKGBUILD b/atdna/PKGBUILD index c17db0e..d809203 100644 --- a/atdna/PKGBUILD +++ b/atdna/PKGBUILD @@ -1,7 +1,7 @@ # PKGBUILD for atdna _pkgname=atdna pkgname=$_pkgname-git -pkgver=1.1.0.18.g2bb60ab +pkgver=1.1.0.19.g96ed8a2 pkgrel=1 pkgdesc="Companion DNA utility for libAthena" arch=('i686' 'x86_64') @@ -20,11 +20,11 @@ pkgver() { build() { cd "$srcdir/$_pkgname/atdna" - qmake PREFIX="$pkgdir/usr" && make + qmake PREFIX="$pkgdir/usr" INSTALL_PREFIX="/usr" && make } package() { cd "$srcdir/$_pkgname/atdna" - qmake PREFIX="$pkgdir/usr" && make install + qmake PREFIX="$pkgdir/usr" INSTALL_PREFIX="/usr" && make install } diff --git a/atdna/atdna.pro b/atdna/atdna.pro index 744e6b5..4302641 100644 --- a/atdna/atdna.pro +++ b/atdna/atdna.pro @@ -58,6 +58,9 @@ unix { isEmpty(PREFIX) { PREFIX = /usr/local } + isEmpty(INSTALL_PREFIX) { + INSTALL_PREFIX = /usr/local + } utilFiles.path = $$PREFIX/bin utilFiles.files = $$OUT_PWD/atdna INSTALLS += utilFiles @@ -67,10 +70,13 @@ win32 { isEmpty(PREFIX) { PREFIX = $$PWD/pkg } + isEmpty(INSTALL_PREFIX) { + INSTALL_PREFIX = $$PWD/pkg + } utilFiles.path = $$PREFIX/bin utilFiles.files = $$OUT_PWD/atdna INSTALLS += utilFiles } -DEFINES += SYSTEM_PREFIX="$$PREFIX" +DEFINES += INSTALL_PREFIX="$$INSTALL_PREFIX" diff --git a/atdna/main.cpp b/atdna/main.cpp index 75068a0..6ca23cc 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -14,7 +14,6 @@ #ifndef SYSTEM_PREFIX #define SYSTEM_PREFIX /usr/local #endif - #define XSTR(s) STR(s) #define STR(s) #s From 7fccd416f396e0d878a7f9d7542ac141eabf351a Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 16 Jun 2015 15:05:43 -1000 Subject: [PATCH 10/15] even more tweaks --- atdna/PKGBUILD | 2 +- atdna/main.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/atdna/PKGBUILD b/atdna/PKGBUILD index d809203..dd133b9 100644 --- a/atdna/PKGBUILD +++ b/atdna/PKGBUILD @@ -1,7 +1,7 @@ # PKGBUILD for atdna _pkgname=atdna pkgname=$_pkgname-git -pkgver=1.1.0.19.g96ed8a2 +pkgver=1.1.0.20.gb195c19 pkgrel=1 pkgdesc="Companion DNA utility for libAthena" arch=('i686' 'x86_64') diff --git a/atdna/main.cpp b/atdna/main.cpp index 6ca23cc..07ab351 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -11,8 +11,8 @@ #include "llvm/Support/Format.h" #include "llvm/Support/CommandLine.h" -#ifndef SYSTEM_PREFIX -#define SYSTEM_PREFIX /usr/local +#ifndef INSTALL_PREFIX +#define INSTALL_PREFIX /usr/local #endif #define XSTR(s) STR(s) #define STR(s) #s @@ -441,7 +441,7 @@ int main(int argc, const char** argv) std::vector args = {"clang-tool", "-fsyntax-only", "-std=c++11"}; - args.push_back("-I" + std::string(XSTR(SYSTEM_PREFIX)) + "/lib/clang/" + CLANG_VERSION_STRING + "/include"); + args.push_back("-I" + std::string(XSTR(INSTALL_PREFIX)) + "/lib/clang/" + CLANG_VERSION_STRING + "/include"); llvm::outs() << args.back() << "\n"; for (int a=1 ; a Date: Tue, 16 Jun 2015 15:08:39 -1000 Subject: [PATCH 11/15] hopefully the last tweak --- atdna/PKGBUILD | 2 +- atdna/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atdna/PKGBUILD b/atdna/PKGBUILD index dd133b9..d498db7 100644 --- a/atdna/PKGBUILD +++ b/atdna/PKGBUILD @@ -1,7 +1,7 @@ # PKGBUILD for atdna _pkgname=atdna pkgname=$_pkgname-git -pkgver=1.1.0.20.gb195c19 +pkgver=1.1.0.21.g7fccd41 pkgrel=1 pkgdesc="Companion DNA utility for libAthena" arch=('i686' 'x86_64') diff --git a/atdna/main.cpp b/atdna/main.cpp index 07ab351..84a1c25 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -442,7 +442,7 @@ int main(int argc, const char** argv) "-fsyntax-only", "-std=c++11"}; args.push_back("-I" + std::string(XSTR(INSTALL_PREFIX)) + "/lib/clang/" + CLANG_VERSION_STRING + "/include"); - llvm::outs() << args.back() << "\n"; + args.push_back("-I" + std::string(XSTR(INSTALL_PREFIX)) + "/include"); for (int a=1 ; a Date: Tue, 16 Jun 2015 15:20:31 -1000 Subject: [PATCH 12/15] Another tweak --- atdna/PKGBUILD | 2 +- atdna/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atdna/PKGBUILD b/atdna/PKGBUILD index d498db7..5f606a5 100644 --- a/atdna/PKGBUILD +++ b/atdna/PKGBUILD @@ -1,7 +1,7 @@ # PKGBUILD for atdna _pkgname=atdna pkgname=$_pkgname-git -pkgver=1.1.0.21.g7fccd41 +pkgver=1.1.0.22.gec4ac68 pkgrel=1 pkgdesc="Companion DNA utility for libAthena" arch=('i686' 'x86_64') diff --git a/atdna/main.cpp b/atdna/main.cpp index 84a1c25..9cb6439 100644 --- a/atdna/main.cpp +++ b/atdna/main.cpp @@ -442,7 +442,7 @@ int main(int argc, const char** argv) "-fsyntax-only", "-std=c++11"}; args.push_back("-I" + std::string(XSTR(INSTALL_PREFIX)) + "/lib/clang/" + CLANG_VERSION_STRING + "/include"); - args.push_back("-I" + std::string(XSTR(INSTALL_PREFIX)) + "/include"); + args.push_back("-I" + std::string(XSTR(INSTALL_PREFIX)) + "/include/Athena"); for (int a=1 ; a Date: Tue, 16 Jun 2015 15:43:35 -1000 Subject: [PATCH 13/15] Restored master branch for PKGBUILDs --- PKGBUILD | 2 +- atdna/PKGBUILD | 4 ++-- atdna/test.hpp | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 15936d8..5172e21 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -5,7 +5,7 @@ pkgver=1.1.0.17.gfb722a9 pkgrel=1 pkgdesc="Basic cross platform IO library" arch=('i686' 'x86_64') -source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git#branch=atdna") +source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git") options=(staticlibs) license="MIT" makedepends=('git qt5-base sed') diff --git a/atdna/PKGBUILD b/atdna/PKGBUILD index 5f606a5..5c49e19 100644 --- a/atdna/PKGBUILD +++ b/atdna/PKGBUILD @@ -1,11 +1,11 @@ # PKGBUILD for atdna _pkgname=atdna pkgname=$_pkgname-git -pkgver=1.1.0.22.gec4ac68 +pkgver=1.1.0.23.g647f9c4 pkgrel=1 pkgdesc="Companion DNA utility for libAthena" arch=('i686' 'x86_64') -source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git#branch=atdna") +source=("${pkgname%-*}::git+https://github.com/Antidote/Athena.git") options=(staticlibs) license="MIT" makedepends=('git qt5-base sed clang libathena-git') diff --git a/atdna/test.hpp b/atdna/test.hpp index 886c412..7d7d97f 100644 --- a/atdna/test.hpp +++ b/atdna/test.hpp @@ -1,4 +1,3 @@ -#include #include using namespace Athena; From 3071db8f611f027f944a6541b59f7a903c32bccf Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 16 Jun 2015 16:02:35 -1000 Subject: [PATCH 14/15] hard-path comments --- atdna/atdna.pro | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/atdna/atdna.pro b/atdna/atdna.pro index 4302641..e34b5ce 100644 --- a/atdna/atdna.pro +++ b/atdna/atdna.pro @@ -10,12 +10,12 @@ QMAKE_CXXFLAGS_WARN_ON = -Wno-unused-parameter INCLUDEPATH += ../include CONFIG(debug, debug|release) { - INCLUDEPATH += /run/media/jacko/Extra/llvm-build/usr/include - LIBS += -L/run/media/jacko/Extra/llvm-build/usr/lib + # FOR FULL DEBUGGING, PLEASE UNCOMMENT THESE AND POINT THEM TO + # THE INSTALL PREFIX OF YOUR OWN DEBUG BUILD OF LLVM/CLANG!! + #INCLUDEPATH += /home/jacko/llvm-build/usr/include + #LIBS += -L/home/jacko/llvm-build/usr/lib LIBS += -g } else { - #INCLUDEPATH += /run/media/jacko/Extra/llvm-build/usrmin/include - #LIBS += -L/run/media/jacko/Extra/llvm-build/usrmin/lib LIBS += -flto } From 9ebdb37b850163ef63d5bf01d7e8f178c3343d33 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 16 Jun 2015 16:20:38 -1000 Subject: [PATCH 15/15] removed unneeded libs --- atdna/atdna.pro | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/atdna/atdna.pro b/atdna/atdna.pro index e34b5ce..e6b7a11 100644 --- a/atdna/atdna.pro +++ b/atdna/atdna.pro @@ -22,34 +22,12 @@ CONFIG(debug, debug|release) { SOURCES += \ main.cpp -LIBS += -lclangFrontendTool -lclangFrontend -lclangTooling -lclangDriver \ - -lclangSerialization -lclangCodeGen -lclangParse -lclangSema \ - -lclangRewriteFrontend -lclangRewrite -lclangAnalysis -lclangEdit \ +LIBS += -lclangFrontend -lclangTooling -lclangDriver \ + -lclangSerialization -lclangParse -lclangSema \ + -lclangAnalysis -lclangEdit \ -lclangAST -lclangLex -lclangBasic \ - -lLLVMLTO -lLLVMObjCARCOpts -lLLVMLinker -lLLVMBitWriter -lLLVMIRReader \ - -lLLVMXCoreDisassembler -lLLVMXCoreCodeGen -lLLVMXCoreDesc -lLLVMXCoreInfo \ - -lLLVMXCoreAsmPrinter -lLLVMSystemZDisassembler -lLLVMSystemZCodeGen \ - -lLLVMSystemZAsmParser -lLLVMSystemZDesc -lLLVMSystemZInfo -lLLVMSystemZAsmPrinter \ - -lLLVMSparcDisassembler -lLLVMSparcCodeGen -lLLVMSparcAsmParser -lLLVMSparcDesc \ - -lLLVMSparcInfo -lLLVMSparcAsmPrinter -lLLVMPowerPCDisassembler -lLLVMPowerPCCodeGen \ - -lLLVMPowerPCAsmParser -lLLVMPowerPCDesc -lLLVMPowerPCInfo -lLLVMPowerPCAsmPrinter \ - -lLLVMNVPTXCodeGen -lLLVMNVPTXDesc -lLLVMNVPTXInfo -lLLVMNVPTXAsmPrinter \ - -lLLVMMSP430CodeGen -lLLVMMSP430Desc -lLLVMMSP430Info -lLLVMMSP430AsmPrinter \ - -lLLVMMipsDisassembler -lLLVMMipsCodeGen -lLLVMMipsAsmParser -lLLVMMipsDesc \ - -lLLVMMipsInfo -lLLVMMipsAsmPrinter -lLLVMHexagonDisassembler -lLLVMHexagonCodeGen \ - -lLLVMHexagonDesc -lLLVMHexagonInfo -lLLVMCppBackendCodeGen -lLLVMCppBackendInfo \ - -lLLVMARMDisassembler \ - -lLLVMARMCodeGen -lLLVMARMAsmParser -lLLVMARMDesc -lLLVMARMInfo -lLLVMARMAsmPrinter \ - -lLLVMAArch64Disassembler -lLLVMAArch64CodeGen -lLLVMAArch64AsmParser \ - -lLLVMAArch64Desc -lLLVMAArch64Info -lLLVMAArch64AsmPrinter -lLLVMAArch64Utils \ - -lLLVMAsmParser -lLLVMOption -lLLVMTableGen \ - -lLLVMLineEditor -lLLVMInstrumentation -lLLVMX86Disassembler -lLLVMX86AsmParser \ - -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMX86Desc -lLLVMMCDisassembler \ - -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT \ - -lLLVMipo -lLLVMVectorize -lLLVMInterpreter -lLLVMExecutionEngine \ - -lLLVMRuntimeDyld -lLLVMCodeGen -lLLVMTarget -lLLVMScalarOpts -lLLVMProfileData \ - -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMInstCombine -lLLVMTransformUtils \ - -lLLVMipa -lLLVMMC -lLLVMAnalysis -lLLVMCore -lLLVMSupport -lz -lpthread -lcurses -ldl + -lLLVMOption -lLLVMMCParser -lLLVMBitReader \ + -lLLVMMC -lLLVMSupport -lz -lpthread -lcurses -ldl HEADERS += \ test.hpp