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