From: Ebersold Date: Mon, 20 Dec 2021 20:37:26 +0000 (+0100) Subject: Initial import from SVN X-Git-Url: https://git.ebersold.fr/?a=commitdiff_plain;h=09c461092c6c4e7cc01da9fea83146bab8ead9c2;p=parser%2Fcommon.git Initial import from SVN --- 09c461092c6c4e7cc01da9fea83146bab8ead9c2 diff --git a/ADT/CMakeLists.txt b/ADT/CMakeLists.txt new file mode 100644 index 0000000..2263e26 --- /dev/null +++ b/ADT/CMakeLists.txt @@ -0,0 +1,3 @@ + + +SUBDIRS(asn1) diff --git a/ADT/asn1/Asn1Boolean.cpp b/ADT/asn1/Asn1Boolean.cpp new file mode 100644 index 0000000..86d290a --- /dev/null +++ b/ADT/asn1/Asn1Boolean.cpp @@ -0,0 +1,16 @@ +#include +#include "ADT/asn1/Asn1Boolean.h" + +// +Asn1Boolean::Asn1Boolean() +{ +} +// +Asn1Boolean::Asn1Boolean(const Asn1Boolean &o) +{ +} + +// +Asn1Boolean::~Asn1Boolean() +{ +} diff --git a/ADT/asn1/Asn1Choice.cpp b/ADT/asn1/Asn1Choice.cpp new file mode 100644 index 0000000..c51128f --- /dev/null +++ b/ADT/asn1/Asn1Choice.cpp @@ -0,0 +1,17 @@ +#include +#include "ADT/asn1/Asn1Choice.h" + +// default Contructor +Asn1Choice::Asn1Choice() +{ +} + +// +Asn1Choice::Asn1Choice(const Asn1Choice &o) +{ +} + +// default Desctructor +Asn1Choice::~Asn1Choice() +{ +} diff --git a/ADT/asn1/Asn1Class.cpp b/ADT/asn1/Asn1Class.cpp new file mode 100644 index 0000000..4fec3fe --- /dev/null +++ b/ADT/asn1/Asn1Class.cpp @@ -0,0 +1,17 @@ +#include +#include "ADT/asn1/Asn1Class.h" + +// default Contructor +Asn1Class::Asn1Class() +{ +} + +// +Asn1Class::Asn1Class(const Asn1Class &o) +{ +} + +// default Desctructor +Asn1Class::~Asn1Class() +{ +} diff --git a/ADT/asn1/Asn1Constraint.cpp b/ADT/asn1/Asn1Constraint.cpp new file mode 100644 index 0000000..a9eb4fe --- /dev/null +++ b/ADT/asn1/Asn1Constraint.cpp @@ -0,0 +1,19 @@ +#include + +#include "ADT/asn1/Asn1Decl.h" +#include "ADT/asn1/Asn1Constraint.h" + +// default Contructor +Asn1Constraint::Asn1Constraint() +{ +} + +// +Asn1Constraint::Asn1Constraint(const Asn1Constraint &o) +{ +} + +// default Desctructor +Asn1Constraint::~Asn1Constraint() +{ +} diff --git a/ADT/asn1/Asn1Context.cpp b/ADT/asn1/Asn1Context.cpp new file mode 100644 index 0000000..268c19e --- /dev/null +++ b/ADT/asn1/Asn1Context.cpp @@ -0,0 +1,18 @@ +#include +#include "ADT/asn1/Asn1Decl.h" +#include "ADT/asn1/Asn1Context.h" + +// default Contructor +Asn1Context::Asn1Context() +{ +} + +// +Asn1Context::Asn1Context(const Asn1Context &o) +{ +} + +// default Desctructor +Asn1Context::~Asn1Context() +{ +} diff --git a/ADT/asn1/Asn1Decl.cpp b/ADT/asn1/Asn1Decl.cpp new file mode 100644 index 0000000..f972e1f --- /dev/null +++ b/ADT/asn1/Asn1Decl.cpp @@ -0,0 +1,17 @@ +#include +#include "ADT/asn1/Asn1Decl.h" + +// default Contructor +Asn1Decl::Asn1Decl() +{ +} + +// +Asn1Decl::Asn1Decl(const Asn1Decl &o) +{ +} + +// default Desctructor +Asn1Decl::~Asn1Decl() +{ +} diff --git a/ADT/asn1/Asn1Field.cpp b/ADT/asn1/Asn1Field.cpp new file mode 100644 index 0000000..dbe9655 --- /dev/null +++ b/ADT/asn1/Asn1Field.cpp @@ -0,0 +1,17 @@ +#include +#include "ADT/asn1/Asn1Field.h" + +// default Contructor +Asn1Field::Asn1Field() +{ +} + +// +Asn1Field::Asn1Field(const Asn1Field &o) +{ +} + +// default Desctructor +Asn1Field::~Asn1Field() +{ +} diff --git a/ADT/asn1/Asn1Integer.cpp b/ADT/asn1/Asn1Integer.cpp new file mode 100644 index 0000000..fe0f563 --- /dev/null +++ b/ADT/asn1/Asn1Integer.cpp @@ -0,0 +1,17 @@ +#include +#include "ADT/asn1/Asn1Integer.h" + +// default Contructor +Asn1Integer::Asn1Integer() +{ +} + +// +Asn1Integer::Asn1Integer(const Asn1Integer &o) +{ +} + +// default Desctructor +Asn1Integer::~Asn1Integer() +{ +} diff --git a/ADT/asn1/Asn1Module.cpp b/ADT/asn1/Asn1Module.cpp new file mode 100644 index 0000000..dc54a1b --- /dev/null +++ b/ADT/asn1/Asn1Module.cpp @@ -0,0 +1,17 @@ +#include +#include "ADT/asn1/Asn1Module.h" + +// default Contructor +Asn1Module::Asn1Module() +{ +} + +// +Asn1Module::Asn1Module(const Asn1Module &o) +{ +} + +// default Desctructor +Asn1Module::~Asn1Module() +{ +} diff --git a/ADT/asn1/Asn1Object.cpp b/ADT/asn1/Asn1Object.cpp new file mode 100644 index 0000000..99144c2 --- /dev/null +++ b/ADT/asn1/Asn1Object.cpp @@ -0,0 +1,17 @@ +#include +#include "ADT/asn1/Asn1Object.h" + +// default Contructor +Asn1Object::Asn1Object() +{ +} + +// +Asn1Object::Asn1Object(const Asn1Object &o) +{ +} + +// default Desctructor +Asn1Object::~Asn1Object() +{ +} diff --git a/ADT/asn1/Asn1Oid.cpp b/ADT/asn1/Asn1Oid.cpp new file mode 100644 index 0000000..c856cb9 --- /dev/null +++ b/ADT/asn1/Asn1Oid.cpp @@ -0,0 +1,18 @@ +#include +#include "ADT/asn1/Asn1Type.h" +#include "ADT/asn1/Asn1Oid.h" + +// default Contructor +Asn1ObjectIdentifier::Asn1ObjectIdentifier() +{ +} + +// +Asn1ObjectIdentifier::Asn1ObjectIdentifier(const Asn1ObjectIdentifier &o) +{ +} + +// default Desctructor +Asn1ObjectIdentifier::~Asn1ObjectIdentifier() +{ +} diff --git a/ADT/asn1/Asn1Sequence.cpp b/ADT/asn1/Asn1Sequence.cpp new file mode 100644 index 0000000..88b4b33 --- /dev/null +++ b/ADT/asn1/Asn1Sequence.cpp @@ -0,0 +1,17 @@ +#include +#include "ADT/asn1/Asn1Sequence.h" + +// default Contructor +Asn1Sequence::Asn1Sequence() +{ +} + +// +Asn1Sequence::Asn1Sequence(const Asn1Sequence &o) +{ +} + +// default Desctructor +Asn1Sequence::~Asn1Sequence() +{ +} diff --git a/ADT/asn1/Asn1Set.cpp b/ADT/asn1/Asn1Set.cpp new file mode 100644 index 0000000..b660b69 --- /dev/null +++ b/ADT/asn1/Asn1Set.cpp @@ -0,0 +1,17 @@ +#include +#include "ADT/asn1/Asn1Set.h" + +// default Contructor +Asn1Set::Asn1Set() +{ +} + +// +Asn1Set::Asn1Set(const Asn1Set &o) +{ +} + +// default Desctructor +Asn1Set::~Asn1Set() +{ +} diff --git a/ADT/asn1/Asn1Type.cpp b/ADT/asn1/Asn1Type.cpp new file mode 100644 index 0000000..28e2747 --- /dev/null +++ b/ADT/asn1/Asn1Type.cpp @@ -0,0 +1,17 @@ +#include +#include "ADT/asn1/Asn1Type.h" + +// default Contructor +Asn1Type::Asn1Type() +{ +} + +// +Asn1Type::Asn1Type(const Asn1Type &o) +{ +} + +// default Desctructor +Asn1Type::~Asn1Type() +{ +} diff --git a/ADT/asn1/CMakeLists.txt b/ADT/asn1/CMakeLists.txt new file mode 100644 index 0000000..b601467 --- /dev/null +++ b/ADT/asn1/CMakeLists.txt @@ -0,0 +1,19 @@ +PROJECT(AdtAsn1) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../include/) +ADD_LIBRARY(commonAdtAsn1 + Asn1Boolean.cpp + Asn1Choice.cpp + Asn1Class.cpp + Asn1Constraint.cpp + Asn1Context.cpp + Asn1Decl.cpp + Asn1Field.cpp + Asn1Integer.cpp + Asn1Module.cpp + Asn1Object.cpp + Asn1Oid.cpp + Asn1Sequence.cpp + Asn1Set.cpp + Asn1Type.cpp + ) diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp new file mode 100644 index 0000000..fa93557 --- /dev/null +++ b/AST/ASTContext.cpp @@ -0,0 +1,142 @@ +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + +#include +#include + + +namespace AST { + +/** + * Default Constructor + */ +ASTContext::ASTContext() + : m_Types() + // BuiltinTypes ... +#define BUILTIN_TYPE(Id,Cls) , Cls(BuiltinType::Id) +#include "AST/BuiltinTypes.h.def" +{ + m_TranslationUnitDecl = AST::TranslationUnitDecl::Create(*this,NULL,"rootDecl"); +} + +/** + * Default Destructor + */ +ASTContext::~ASTContext() +{ +} +/** + * + */ +Type & +ASTContext::getValueTypeType(const ValueTypeDecl *D) +{ + // Check If Decl already has TypeForDecl + if (D->getTypeForDecl()) + return *D->getTypeForDecl(); + // Check If Decl has Previous Decl and if Previous has TypeForDecl + TypelistConstIterator it = m_Types.find(D->getName()) ; + if ( it != m_Types.end() ) + { + ValueType *nT = reinterpret_cast((*it).second); + const_cast( D )->setTypeForDecl(nT); + return *nT; + } + // Create new Type and push it in the map + ValueType *nT = new ValueType(D); + m_Types[D->getName()] = nT; + const_cast( D )->setTypeForDecl(nT); + return *nT; +} + +/** + * + */ +Type & +ASTContext::getTypedefType(const TypedefDecl *D) +{ + // Check If Decl already has TypeForDecl + if (D->getTypeForDecl()) + return *D->getTypeForDecl(); + // Check If Decl has Previous Decl and if Previous has TypeForDecl + // Create new Type and push it in the map + TypedefType *nT = new TypedefType(D); + + m_Types[D->getName()] = nT; + const_cast( D )->setTypeForDecl(nT); + return *nT; +} + + + +/** + * + */ +Type & +ASTContext::getRecordType(const RecordDecl *D) +{ + // Check If Decl already has TypeForDecl + if (D->getTypeForDecl()) + return *D->getTypeForDecl(); + // Check If Decl has Previous Decl and if Previous has TypeForDecl + TypelistConstIterator it = m_Types.find(D->getName()) ; + if ( it != m_Types.end() ) + { + RecordType *nT = reinterpret_cast((*it).second); + const_cast( D )->setTypeForDecl(nT); + return *nT; + } + // Create new Type and push it in the map + std::cerr<<"ASTContext::getRecordType: TODO "<getName()<getName()] = nT; + const_cast( D )->setTypeForDecl(nT); + return *nT; +} + +Type & +ASTContext::getConstantArrayType(Type *EltTy,long length) +{ + std::cerr<<"ASTContext::getConstantArrayType: TODO "<Parma,const std::string &fn) +{ + return CharTy; +} + +Type &ASTContext::getTypeDeclType(TypeDecl *Decl,TypeDecl *prevDecl ) +{ + if (Decl->m_TypeForDecl) + return *Decl->m_TypeForDecl; + // + if (prevDecl && prevDecl->m_TypeForDecl) + { + Decl->m_TypeForDecl = prevDecl->m_TypeForDecl; + return *prevDecl->m_TypeForDecl; + } + std::cout<<"ASTContext::getTypeDeclType Todo"< +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + +#include +#include + +namespace AST +{ + +/** + * Find the Translation unit for the given Declaration + */ +TranslationUnitDecl * +Decl::getTranslationUnitDecl(TypeClass _tc) +{ + if (TranslationUnitDecl *TUD = dynamic_cast(this)) + { + return TUD; + } + /* If not, get The DeclContext and check parents*/ + DeclContext *DC = getDeclContext(); + + const DeclContext *DC = getDeclContext() const; + return NULL; +} + +/** + * ?? + */ +DeclContext *Decl::getDeclContext() +{ +} + + +void EventDecl::Signature(SignatureNodeID &id) +{ + id+=getName(); + // Add Parameters as well +} + +void FunctionDecl::Signature(SignatureNodeID &id) +{ + id+=getName(); + // Add Parameters as well +} + +void RecordDecl::Signature(SignatureNodeID &id) +{ + id+=getName(); + // Add Parameters as well +} + + +field_iterator RecordDecl::field_begin() const +{ + return field_iterator(decl_iterator(m_FirstDecl)); +} + +field_iterator RecordDecl::field_begin() const +{ + return field_iterator(decl_iterator(m_LastDecl)); +} + +} diff --git a/AST/DeclContext.cpp b/AST/DeclContext.cpp new file mode 100644 index 0000000..d15ad3e --- /dev/null +++ b/AST/DeclContext.cpp @@ -0,0 +1,152 @@ +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + +namespace AST { + + void DeclContext::addHiddenDecl(Decl *d) + { + // std::cout<<"DeclContext::addHiddenDecl Ctx="<<(long)this<<" decl kind "<getKind()<setNextDeclInContext(d); + m_LastDecl = d; + } else { + m_FirstDecl = m_LastDecl = d; + } + + }; + + /** + * + * + */ + DeclContext::lookup_result DeclContext::lookup(const std::string &_n) + { + lookup_result result; + Decl *l = m_FirstDecl; + DeclContext *current = this; + bool found = false; + while (! found && (l != NULL)) + { + NamedDecl *c = dynamic_cast(l); + if ( (c) && ! _n.compare(c->getName() ) ) { + found = true; + result.push_back(c); + } + // Check if it's a Transition + EventDecl *evt = dynamic_cast(l); + if (current->isTransition() && evt ) + { + // Loop over Event and check arguments + //std::cout<<"lookup in event"<param_size() > 0 ) + { + // std::cout<<"Event "<getName()<<" Has parameters"<param_begin() + ; pit != evt->param_end() + ; ++pit) + { + //std::cout<<"Event Check:"<<(*pit)->getName()<<" "<getName())) + { + result.push_back(*pit); + found = true; + } + } + } + } + + // Move up until Translation Unit + l = l->getNextDeclInContext() ; + if ( l == NULL ) { +#if 0 + std::cout<<"DeclContext::lookup go to parent Current T="<isTransition(); + std::cout<<" S="<isState()<getParent(); + while ( (l == NULL) && p &&!p->isTranslationUnit() ) + { + current = p; + l = p->m_FirstDecl; +#if 0 + std::cout<<"DeclContext::lookup "<(m_Specialization)) + { + return r->getDecl()->isStruct(); + } + return false; +} +/** + * + */ +bool +ValueTypeDecl::isUnion() const +{ + if (RecordType *r = dynamic_cast(m_Specialization)) + { + return r->getDecl()->isUnion(); + } + return false; +} + +/** + * + */ +bool +ValueTypeDecl::isEnum() const +{ + if (EnumType *r = dynamic_cast(m_Specialization)) + { + return true; + } + return false; +} + +/** + * + */ +bool +ValueTypeDecl::isArray() const +{ + if (ArrayType *r = dynamic_cast(m_Specialization)) + { + return true; + } + return false; +} + + +} diff --git a/AST/Expr.cpp b/AST/Expr.cpp new file mode 100644 index 0000000..dbce1f0 --- /dev/null +++ b/AST/Expr.cpp @@ -0,0 +1,139 @@ +#include +#include +#include + +#include + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + +namespace AST { + +Expr *ExprIterator::operator [](size_t i) +{ + return static_cast< Expr *>(I[i]); +} + +Expr *ExprIterator::operator *() const +{ + return static_cast< Expr *>(*I); +} + +Expr *ExprIterator::operator ->() const +{ + return static_cast< Expr *>(*I); +} + +bool +Expr::evalute(EvalResult &result) +{ + return true; +} + +ParenListExpr::ParenListExpr() : Expr(ParenListExprClass) , m_NbExprs(0) { + memset(m_Stmts,0x00, ParenListExpr::MAX); +} + +Stmt::range_iterator +ParenListExpr::children() { + Stmt::range_iterator r(&m_Stmts[0],&m_Stmts[m_NbExprs]); + return r; +} +/** + * MemberExpr implementation methods + */ +MemberExpr::MemberExpr(Expr *base,ValueDecl *mem,Type *Ty) + : Expr(MemberExprClass,Ty) , m_Base(base), m_Member(mem) +{ +} + +/* To be improved */ +MemberExpr * +MemberExpr::Create(ASTContext &AC,Expr *base,ValueDecl *_member,Type *Ty) +{ + return new MemberExpr(base,_member,Ty); +} + + +#if 0 +Expr* getBase() const +{ + return reinterpret_cast(m_Base); +} + +ValueDecl *getMember() const +{ + return reinterpret_cast(m_Member); +} +#endif + +ArraySubscriptExpr::ArraySubscriptExpr(Expr *base,Expr *idx,Type *Ty) + : m_Base(base),m_Index(idx) , Expr(ArraySubscriptExprClass,Ty) +{ +} + + +ArraySubscriptExpr * +ArraySubscriptExpr::Create(ASTContext &AC,Expr *base,Expr *_idx,Type *Ty) +{ + return new ArraySubscriptExpr(base,_idx,Ty); +} + + + +#if 0 +enum BinaryOperatorKind { + // Operators are listed in ORDER of precedence + BO_Mul, BO_Div, BO_Rem, // Multiplicative operators + BO_Add, BO_Sub, // Additive operators + BO_Shl, BO_Shr, // Bitwise shift operators + BO_LT, BO_GT, BO_LE, BO_GE, // Relation operators + BO_EQ, BO_NE, // Equal Operators + BO_And, // Bitwise And, Xor, Or + BO_Xor, + BO_Or, + BO_LAnd, // Logical And / Or + BO_LOr, + BO_Assign // Assignement Operators +}; + +enum UnaryOperatorKind { + UO_PostInc, UO_PostDec, // postfix increment and decrement + UO_PreInc, UO_PreDec, // prefix increment and decrement + UO_Plus, UO_Minus, // Unary arithmetic + UO_Not, UO_LNot, UO_Test // +}; + +#endif +const char * +BinaryOperator::getOpcodeStr( ) const +{ + switch (getOpcode()) + { + case BO_Mul: return "*"; + case BO_Div: return "/"; + case BO_Rem: return ""; + case BO_Add: return "+"; + case BO_Sub: return "-"; + case BO_Shl: return ">>"; + case BO_Shr: return "<<"; + case BO_LT: return "<"; + case BO_GT: return ">"; + case BO_LE: return "<="; + case BO_GE: return ">="; + case BO_EQ: return "="; + case BO_NE: return "/="; + case BO_And: return "and"; + case BO_Xor: return ""; + case BO_Or: return ""; + case BO_LAnd: return ""; + case BO_LOr: return ""; + case BO_Assign: return ":="; // Assignement Operators + default: return "unknown"; + } +} + +} diff --git a/AST/ExprCallExpr.cpp b/AST/ExprCallExpr.cpp new file mode 100644 index 0000000..23fe9f5 --- /dev/null +++ b/AST/ExprCallExpr.cpp @@ -0,0 +1,32 @@ + +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + +namespace AST { + + CallExpr::CallExpr(const DeclContext *ctx,Expr *fn,std::vector args) : Expr(CallExprClass) { + m_NumArgs = args.size(); + int i = 1; + for( std::vector::iterator it = args.begin() ; it != args.end() ; ++it) { + m_Args[i++] = *it; + } + m_Args[FN] = fn; + } + +FunctionDecl * +CallExpr::getCalleeDecl() const { + if ( DeclRefExpr *r = dynamic_cast(m_Args[FN]) ) { + return dynamic_cast(r->getDecl()); + } else return NULL; +} + + +} diff --git a/AST/ExprDeclRefExpr.cpp b/AST/ExprDeclRefExpr.cpp new file mode 100644 index 0000000..c453db1 --- /dev/null +++ b/AST/ExprDeclRefExpr.cpp @@ -0,0 +1,30 @@ +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + +namespace AST { + +Decl * +DeclRefExpr::getDecl() const { + return dynamic_cast(m_value); +} + + +bool DeclRefExpr::isRefFunctionDecl() const +{ return dynamic_cast(getDecl()) != NULL ; } + +bool DeclRefExpr::isRefVarDecl() const +{ return dynamic_cast(getDecl()) != NULL ; } + +bool DeclRefExpr::isRefParmVarDecl() const +{ return dynamic_cast(getDecl()) != NULL ; } + + +} diff --git a/AST/StmtAsmStmt.cpp b/AST/StmtAsmStmt.cpp new file mode 100644 index 0000000..ed7fb28 --- /dev/null +++ b/AST/StmtAsmStmt.cpp @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" +#include "AST/StmtIterator.h" + + +namespace AST { + + + AST::StringLiteral *AsmStmt::getLiteral() const { + return dynamic_cast(m_Stmts[LIT]); + }; + + void AsmStmt::setLiteral(AST::Expr *E) { + m_Stmts[LIT] = E; + } + + void AsmStmt::setExpr(AST::Expr *E) { + m_Stmts[EXPR] = E; + } + + AsmStmt::AsmStmt(DeclContext *DC,StmtClass KD,const std::string &op ) : Stmt(KD) { + memset(m_Stmts,0x00,END); + // m_Stmts[LIT] = cond; + } + + VarDecl *AsmStmt::getVarDecl() const + { + AST::DeclRefExpr *ref = dynamic_cast(m_Stmts[LIT]); + if (ref) + { + return dynamic_cast(ref->getDecl()); + } else + return NULL; + } + + TimerDecl *AsmStmt::getTimerDecl() const + { + AST::DeclRefExpr *ref = dynamic_cast(m_Stmts[LIT]); + if (ref) + { + return dynamic_cast(ref->getDecl()); + } else + return NULL; + } + + /// For SET and RESET Statements + bool AsmStmt::isArgVariable() const + { + AST::DeclRefExpr *ref = dynamic_cast(m_Stmts[LIT]); + if (ref) + { + return dynamic_cast(ref->getDecl()) != NULL; + } else + return false; + } + + bool AsmStmt::isArgTimer() const + { + AST::DeclRefExpr *ref = dynamic_cast(m_Stmts[LIT]); + if (ref) + { + return dynamic_cast(ref->getDecl()) != NULL; + } else + return false; + } + + + /** + * LDS ASM + */ + LdsAsmStmt::LdsAsmStmt(DeclContext *DC,const std::string &op ) : AsmStmt(DC,Stmt::LdsAsmStmtClass,op) { + +#define SETOP(x) if (! op.compare( #x ) ) { m_Opcode = x ;} + if (! op.compare("AEL_RETURN") ) { m_Opcode = AEL_RETURN ;} + SETOP(AEL_SET) + SETOP(AEL_NOP) + SETOP(AEL_LOOP_MSG) + SETOP(AEL_SET) + SETOP(AEL_RESET) + SETOP(AEL_JSR_IND) + SETOP(AEL_RTS) + } + +}; + diff --git a/AST/StmtIfStmt.cpp b/AST/StmtIfStmt.cpp new file mode 100644 index 0000000..8d28375 --- /dev/null +++ b/AST/StmtIfStmt.cpp @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" +#include "AST/StmtIterator.h" + + +namespace AST { + + IfStmt::IfStmt(DeclContext *DC,Expr *cond,Stmt *_then,Stmt *_else ) : Stmt(Stmt::IfStmtClass) { + memset(m_Stmts,0x00,END); + m_Stmts[COND] = cond; + m_Stmts[THEN] = _then; + m_Stmts[ELSE] = _else; + } + + AST::Expr *IfStmt::getCond() const { + return dynamic_cast(m_Stmts[COND]); + }; + + Stmt::range_iterator IfStmt::children() { + return range_iterator(&m_Stmts[0],&m_Stmts[0]+3); + } +} diff --git a/AST/StmtOutputStmt.cpp b/AST/StmtOutputStmt.cpp new file mode 100644 index 0000000..fbea3fe --- /dev/null +++ b/AST/StmtOutputStmt.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" +#include "AST/StmtIterator.h" + + +namespace AST { + + + OutputStmt::OutputStmt(DeclContext *DC,const std::string &op,DeclRefExpr *sig,Expr *dest) + : m_NumArgs(0) , Stmt(Stmt::OutputStmtClass) + { + memset(m_Stmts,0x00,END); + m_Stmts[SIG] = sig; + } + + EventDecl *OutputStmt::getEventDecl() const + { + + DeclRefExpr *dref = dynamic_cast(m_Stmts[SIG]); + if (dref) + return dynamic_cast(dref->getDecl()); + return NULL; + } + + void OutputStmt::setDestination(Expr *dest) + { + m_Stmts[DEST] = dest; + } + + void OutputStmt::setArgs(std::vector &_args) + { + m_NumArgs = _args.size(); + int i = 0; + for( std::vector::iterator it = _args.begin() ; it != _args.end() ; ++it) { + m_Args[i++] = *it; + } + } + Expr *OutputStmt::getArg(unsigned i) + { + return static_cast(m_Args[i]); + } + + const Expr *OutputStmt::getArg(unsigned i) const + { + return static_cast(m_Args[i]); + } + +}; + +/* + * ex: set sw=2 et list: + */ diff --git a/AST/StmtWhileStmt.cpp b/AST/StmtWhileStmt.cpp new file mode 100644 index 0000000..2eb1a3e --- /dev/null +++ b/AST/StmtWhileStmt.cpp @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" +#include "AST/StmtIterator.h" + + +namespace AST { + + WhileStmt::WhileStmt(DeclContext *DC,Expr *cond,Stmt *_body ) : Stmt(Stmt::WhileStmtClass) { + memset(m_Stmts,0x00,END); + m_Stmts[COND] = cond; + m_Stmts[BODY] = _body; + } + + AST::Expr *WhileStmt::getCond() const { + return dynamic_cast(m_Stmts[COND]); + }; + + +/** + * + */ + BreakStmt::BreakStmt(DeclContext *DC,Expr *cond) : m_Cond(NULL), Stmt(Stmt::BreakStmtClass) + { + m_Cond = cond; + }; + + Expr *BreakStmt::getCond() + { return dynamic_cast(m_Cond); }; + + + + +} diff --git a/AST/Type.cpp b/AST/Type.cpp new file mode 100644 index 0000000..ded5323 --- /dev/null +++ b/AST/Type.cpp @@ -0,0 +1,37 @@ +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + +#include +#include + +namespace AST +{ + +/** + * + */ +Type::Type(TypeClass _tc) : TC(_tc) +{ +} + +const char * +BuiltinType::getNameAsStr() const +{ + switch (m_Kind) + { +#define BUILTIN_TYPE(Id,Cls) case Id: return #Id; +#include "AST/BuiltinTypes.h.def" + default: return "Uknown"; + }; +} + + +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..04fd1ba --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ + +OPTION(CG_DEBUG_IF "Debug Code Gen If" OFF) +OPTION(CG_DEBUG_EXPR "Debug Code Gen Expr" OFF) + +IF(CG_DEBUG_IF) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCG_DEBUG_IF") +ENDIF(CG_DEBUG_IF) +SUBDIRS(AST CodeGen IR UnitTests ADT LDSExecutionEngine LDSBytecode) diff --git a/CodeGen/CGExprScalar.cpp b/CodeGen/CGExprScalar.cpp new file mode 100644 index 0000000..b3a815c --- /dev/null +++ b/CodeGen/CGExprScalar.cpp @@ -0,0 +1,389 @@ +#include +#include +#include +#include +#include +#include +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + +#include "AST/StmtVisitor.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +typedef aeb::lds::Value * RetValue; + +// Helper class to Emit Code for Scaler Expression +// +class ScalarExprEmitterHelper : public AST::StmtVisitor { + protected: + /** + * Try to keep track of temporarly Values used during evaluation or Visit + */ + struct StackResult { + StackResult() : m_Index(0) , m_Value(NULL) {} + long m_Index; + aeb::lds::Value *m_Value; + }; + protected: + aeb::lds::Builder &m_Builder; + aeb::lds::CodeGen::CodeGenFunction m_CGF; + aeb::lds::CodeGen::CodeGenModule &m_CGM; + std::stack m_Stack; + long m_depth; + public: + ScalarExprEmitterHelper(aeb::lds::CodeGen::CodeGenFunction &cgf) + : m_CGF(cgf) + , m_Builder(cgf.getBuilder()) + , m_depth(0) + , m_CGM(cgf.getModule()) + {}; + + //delegate work to parent class !!! + // Emiters .... + + // Start with Visitors, + // + RetValue Visit(AST::Expr *E) { + return AST::StmtVisitor::Visit(E); + } + // + RetValue VisitBinaryOperator(AST::BinaryOperator *E) { + //CGDBG_EXPR("SEEH::VisitBinaryOperator TOBE Implemented") + std::cout<<"SEEH::VisitBinaryOperator "<getOpcode()<<" TOBE Implemented"<getOpcode()) { + case AST::UO_LNot : + std::cout<<"SEEH::VisitUnaryOperator "<getOpcode()<<" TOBE Implemented"<getOpcode()<<" TOBE Implemented"<getOpcode()<<" TOBE Implemented"<(E->getAgent()); + if (s) + { + std::cout<<"SEEH::VisitCreateExpr "<getString()<<" TOBE Implemented"<getBase()); + std::cout<<"SEEH::VisitMemberExpr "<getName()<<" TOBE Implemented"<getBase()); + std::cout<<"SEEH::VisitArraySubscriptExpr "<getName()<<" TOBE Implemented"<get_value()); + // Should be CreateLoadConstInt + return m_Builder.CreateTest(E->get_value()); + } + // + RetValue VisitDeclRefExpr(AST::DeclRefExpr *E) { + if ( E->isRefFunctionDecl()) + { + CGDBG_EXPR("SEEH::VisitDeclRefExpr Fct "); + return m_Builder.CreateTest("FLAG_TMP_1"); + } else if (E->isRefParmVarDecl()) + { + int Count = 0; + aeb::lds::Function *f = m_CGF.getCurrentFunction(); + AST::ParmVarDecl* var = dynamic_cast(E->getDecl()); + CGDBG_EXPR_ARGS("SEEH::VisitDeclRefExpr ParmVar %s",dynamic_cast(E->getDecl())->getName()); + for (aeb::lds::Function::ArgumentIterator ait = f->arg_begin(); + ait != f->arg_end() + ; ++ait) + { + Count++; + // std::cout<<"Compare <"<getName()<<">"<getName().compare(var->getName())) + { + CGDBG_EXPR_ARGS("SEEH: Found Argument ",var->getName()); + return m_Builder.CreateLoad(ait); + break; + } + } + return m_Builder.CreateTest("FLAG_TMP_1"); + } else if (E->isRefVarDecl()) + { + AST::VarDecl* var = dynamic_cast(E->getDecl()); + CGDBG_EXPR_ARGS("SEEH::VisitDeclRefExpr Var %s",dynamic_cast(E->getDecl())->getName()); + aeb::lds::GlobalVariable *lv = m_CGF.getModule().GetGlobalVariable(var); + return m_Builder.CreateLoad(lv); + } else { + // Unknown ref for now should Stop + std::cout<<"SEEH::VisitDeclRefExpr Unknown "<(E->getDecl())->getName()); + } + + // + RetValue VisitStringLiteral(AST::StringLiteral *E) { + std::cout<<"SEEH::VisitStringLiteral ERROR CreateCall Not NICE nor good but that's how it is "<getString()<getString()); + } + + // Unary + RetValue VisitUnaryNot(AST::UnaryOperator *E) { + // std::cout<<"VisitNot TO BE COMPLETED"<getSubExpr()); + return m_Builder.CreateNot(NULL); + } + RetValue VisitUnaryLNot(AST::UnaryOperator *E) { + // std::cout<<"VisitLNot TO BE COMPLETED "<getSubExpr()); + return m_Builder.CreateNot(NULL); + } + + RetValue VisitUnaryTest(AST::UnaryOperator *E) { + // std::cout<<"VisitTest TO BE COMPLETED "<(E->getSubExpr()); + AST::IntegerLiteral *i = dynamic_cast(E->getSubExpr()); + AST::DeclRefExpr *ref = dynamic_cast(E->getSubExpr()); + if (l) + { + std::cerr<<"SEEH::VisitUnaryTest Error, SubExpr is StringLiteral"<getString()); + } else if (i) + { + std::cerr<<"SEEH::VisitUnaryTest Error, SubExpr is IntegerLiteral"<get_value()); + } else if (ref) + { + AST::NamedDecl *decl = dynamic_cast(ref->getDecl()); + if (AST::ParmVarDecl *v = dynamic_cast(ref->getDecl())) + { + std::cerr<<"SEEH::VisitUnaryTest Error, SubExpr is DeclRef Param"<getName()<getName()); + } else if (AST::VarDecl *v = dynamic_cast(ref->getDecl())) + { + aeb::lds::GlobalVariable *lv = m_CGF.getModule().GetGlobalVariable(v); + return m_Builder.CreateLoad(lv); + } else + return m_Builder.CreateTest(decl->getName()); + } else { + std::cerr<<"SEEH::VisitUnaryTest Error, SubExpr is not a StringLiteral nor Integer nor DeclRef !! Aiee"<Visit(dynamic_cast(E->getStmt())); + } + + RetValue EmitBinaryOp(AST::BinaryOperator *E) { + std::ostringstream oss; + oss<<"FLAG_TMP_"; +#if 0 + std::cout<<"Build EmitBinOp "<getOpcode()<<" depth="<(E->getLHS()); + std::cout<<" Load RHS "<(E->getRHS()); + std::cout<getLHS()); + m_Stack.push(m_depth++); + // Store result + // std::cout<<"Build Load depth="<setName(oss.str()); + } else + std::cerr<<"EmitBinaryOp: LHS == NULL"<getRHS()); + + switch (E->getOpcode() ) { + case AST::BO_And : + m_Builder.CreateAnd(oss.str()); + break; + case AST::BO_Or : + m_Builder.CreateOr(NULL,NULL); + break; + case AST::BO_LOr : + m_Builder.CreateOr(oss.str()); + break; + case AST::BO_Add : + m_Builder.CreatePlus(LHS,RHS); + break; + case AST::BO_Sub : + m_Builder.CreateMoin(LHS,RHS); + break; + default: + std::cout<<"SEEH::UNSUPPORTED OPERATION "<getOpcode()< 0) { + m_Builder.CreateStore(oss.str()); + m_Builder.CreateCmp(oss.str()); + } else if (m_Stack.size() == 1) { + // :std::cout<<" Shoudl Store ? "<getLHS()); + m_Stack.push(m_depth++); + // Store result + oss<setName(oss.str()); + RetValue RHS = Visit(E->getRHS()); + // + m_depth--; + m_Stack.pop(); + /** The code below is a bit wierd to me */ + if (m_Stack.size() > 0) + { + m_Builder.CreateStore(oss.str()); + return m_Builder.CreateCmp(oss.str()); + } else if (m_Stack.size() == 1) { + // :std::cout<<" Shoudl Store ? "<(E->getLHS()); + CGDBG_EXPR("SEEH::Handle VisitBinAssign"); + // This is wrong + //RetValue LHS = Visit(E->getLHS()); + RetValue RHS = Visit(E->getRHS()); + if (l) + { + return m_Builder.CreateStore(l->getString()); + } else if (AST::MemberExpr *member = dynamic_cast(E->getLHS())) + { + std::cerr<<"SEEH:VisitBinAssign LHS TODO MemberExpr "<(E->getLHS())) + { + std::cerr<<"SEEH:VisitBinAssign LHS TODO ArraySubcrtiptExpr "<(E->getLHS())) + { // Handle Differnt Kind of Store + if (drexpr->isRefFunctionDecl()) + { // This is an error. Cannot Store into a Function. Forbidden + std::cerr<<"SEEH:VisitBinAssign LHS ERROR DeclRefExpr is Function "<isRefVarDecl()) + { + AST::VarDecl *var = dynamic_cast(drexpr->getDecl()); + aeb::lds::GlobalVariable *lv = m_CGF.getModule().GetGlobalVariable(var); + return m_Builder.CreateStore(lv); + } + } else { + std::cerr<<"SEEH:VisitBinAssign LHS cannot be other than StringLiteral"< +#include +#include +#include +#include +#include + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#define CG_DEBUG +//#define CG_DEBUG_IF + +namespace aeb { +namespace lds { +namespace CodeGen { + +// A Builder that provide Blocks and set +CodeGenFunction::CodeGenFunction(CodeGenModule &CGM,const Builder &builder) : m_Builder(builder) , m_CurFn(NULL),m_CGM(CGM) + , m_SwitchInst(NULL) +{ +// std::cout<<"CodeGenFunction::CodeGenFunction constructor"<getBody() ) { + EmitStmt(stmt); + } + aeb::lds::BasicBlock *cb = m_Builder.GetInsertBlock(); + m_Builder.ClearInsertPoint(); + m_CurFn = NULL; +} + +/** + * + */ +void +CodeGenFunction::GenerateCode(const AST::TransitionDecl *FnDecl,Function *Fn) +{ + if ( !Fn ) { + std::cerr<<"CodeGenFunction::GenerateCode Error no function"<setName(FnDecl->getName()); + m_CurFn = Fn; + // Maybe I should transfer Events and TargetState here or at least create a link + + + EnsureInsertPoint(); + if (AST::Stmt * stmt = FnDecl->getBody() ) { + EmitStmt(stmt); + } +#if 0 + std::cout<<"CodeGenFunction::GenerateCode After Emit Statements"<getName()<getBlockList().size()<setName(FnDecl->getName()); + m_Builder.ClearInsertPoint(); + m_CurFn = NULL; +} + +void CodeGenFunction::EmitBreakStmt(AST::BreakStmt *S) +{ + //std::cout<<"CodeGenFunction::EmitBreak Need to Branch Stack Size="<getLabel()->getName()); +} + +/** + * + * + */ +void CodeGenFunction::EmitWhileStmt(AST::WhileStmt *S) +{ + aeb::lds::BasicBlock *condBlock = createBasicBlock("WHILE.COND"); + aeb::lds::BasicBlock *endBlock = createBasicBlock("WHILE.END"); + aeb::lds::BasicBlock *bodyBlock = createBasicBlock("WHILE.BODY"); + std::cout<<"CodeGenFunction::EmitWhile"<getCond()); + m_Builder.CreateCondBr(bodyBlock,endBlock); + + EmitBlock(bodyBlock); + EmitStmt(S->getBody()); + EmitBranch(condBlock); + EmitBlock(endBlock); + +} + +/** + * + * + */ +void CodeGenFunction::EmitSwitchCaseStmt(AST::SwitchCaseStmt *S) +{ + + aeb::lds::BasicBlock *CB = NULL; + aeb::lds::BasicBlock *Block = createBasicBlock("SW.DO"); + + if (m_SwitchHashBlock) { + aeb::lds::BasicBlock *curBB = m_Builder.GetInsertBlock(); + if (curBB) { + m_Builder.SetInsertPoint(m_SwitchHashBlock); + m_Builder.CreateBr(Block); + } else { + m_Builder.SetInsertPoint(m_SwitchHashBlock); + m_Builder.CreateBr(Block); + } + } else { + std::cout<<"CodeGenFunction::EmitSwitchCase ??? No HashBlock"<getSubStmt()); + + m_Builder.ClearInsertPoint(); +} + +/** + * + * + */ +void CodeGenFunction::EmitSwitchStmt(AST::SwitchStmt *S) +{ + m_SwitchHashBlock = createBasicBlock("SW.HASH"); + + if (AST::StringLiteral *s = dynamic_cast(S->getCond()) ) + { + /* Is it a global Variable ? */ + aeb::lds::GlobalVariable *gv = m_CGM.getOrCreateGlobal(s->getString(),false); + + m_SwitchInst = m_Builder.CreateSwitch(reinterpret_cast(gv),m_SwitchHashBlock); + }else if (AST::Expr *e = dynamic_cast(S->getCond()) ) + { + /* Evaluate or emit the expression first */ + /* Put Result in a temporaly variable */ + std::cerr<<"CodeGenFunction::EmitSwitchCase ??? Not Yet CODEDE"<case_begin(); it != S->case_end() ; it++) + { + EmitStmt(*it); + } + if (m_SwitchHashBlock) { + EmitBlock(m_SwitchHashBlock); + } else { + std::cout<<"CodeGenFunction::EmitSwitch Hoops SwitchHashBlock lost .... "< 0) { + m_SwitchHashBlock = m_BreakContinueStack.top().m_Hash; + } else + m_SwitchHashBlock = NULL; +} + + +void CodeGenFunction::EmitIfStmt(AST::IfStmt *S) +{ + CGDBG_IF("CodeGenFunction::EmitIfStmt Begin"); + // aeb::lds::BasicBlock *CondBlock = createBasicBlock("IF.COND"); + aeb::lds::BasicBlock *ThenBlock = createBasicBlock("IF.THEN"); + aeb::lds::BasicBlock *ContBlock = createBasicBlock("IF.END"); + aeb::lds::BasicBlock *ElseBlock = ContBlock; + + if ( S->getElse()) + { + CGDBG_IF("CodeGenFunction::EmitIfStmt createBasicBlock IF.ELSE"); + ElseBlock = createBasicBlock("IF.ELSE"); + } + // EmitBlock( CondBlock); + EmitScalarExpression( S->getCond()); + // Branch instruction goes here + // ??? ConV should be the result of the evaluation ? + m_Builder.CreateCondBr(ThenBlock,ElseBlock); + // + CGDBG_IF("CodeGenFunction::EmitIfStmt : Before EmitBlock ThenBlock (IF.THEN)"); + EmitBlock(ThenBlock); + + if (S->getThen()) { + EmitStmt( S->getThen()); + } + // This Section replaces EmitBranch(ContBlock) + CGDBG_IF_ARGS("CodeGenFunction::EmitIfStmt : Before EmitBranch (%s)",ContBlock->getName()); + EmitBranch(ContBlock); + // + if (const AST::Stmt *Else = S->getElse()) { + CGDBG_IF("CodeGenFunction::EmitIfStmt : Handle Else case "); + // std::cout<<"EMitIf : Before EmitBranch ContBlock (IF.END)"<getElse()); + // std::cout<<"EMitIf : Before EmitBranch ContBlock"<getStmtClass()) { + case AST::Stmt::CompoundStmtClass: + EmitCompoundStmt(dynamic_cast(S)); + break; + case AST::Stmt::GotoStmtClass: + EmitGotoStmt(static_cast(S)); + break; + case AST::Stmt::IfStmtClass: + EmitIfStmt(static_cast(S)); + break; + case AST::Stmt::SwitchCaseStmtClass: + EmitSwitchCaseStmt(static_cast(S)); + break; + case AST::Stmt::SwitchStmtClass: + EmitSwitchStmt(static_cast(S)); + break; + case AST::Stmt::WhileStmtClass: + EmitWhileStmt(static_cast(S)); + break; + case AST::Stmt::BreakStmtClass: + EmitBreakStmt(static_cast(S)); + break; + case AST::Stmt::ForStmtClass: + std::cout<<"TOBE CODED "<(S)); + break; + case AST::Stmt::ParenExprClass: + EmitStmt(dynamic_cast(S)->getStmt()); + break; + case AST::Stmt::BinaryOperatorClass: + { + AST::BinaryOperator *u = dynamic_cast(S); + CGDBG_ARGS("CodeGenFunction::EmitSmt BinaryOperator %d",u->getOpcode()); + EmitScalarExpression(u); + } + break; + case AST::Stmt::UnaryOperatorClass: + { + AST::UnaryOperator *u = dynamic_cast(S); + std::cout<<"UnaryOperator "<getOpcode()<(S); + std::cout<<"String var or Fct Call ? "<getString()<getString()); + } + break; + + case AST::Stmt::ReturnStmtClass: + { + if (AST::ReturnStmt *ret = dynamic_cast(S)) { + if ( ret->getIndirect() ) { + aeb::lds::ReturnInst *c = m_Builder.CreateRetSub(); + } else + aeb::lds::ReturnInst *c = m_Builder.CreateRetVoid(); + } + } + break; + case AST::Stmt::LdsAsmStmtClass: + { + EmitLdsAsmStmt(dynamic_cast(S)); + } + break; + case AST::Stmt::OutputStmtClass: + { + EmitOutputStmt(dynamic_cast(S)); + } + break; + default: + std::cout<<"EmitStmt unknown ... "<getStmtClass()<getStmtClass()) { + default: return false; + //case Stmt::NullStmtClass: break; + case AST::Stmt::CompoundStmtClass: + EmitCompoundStmt(dynamic_cast(S)); + break; +#if 0 + case AST::Stmt::DeclStmtClass: + EmitDeclStmt(dynamic_cast(S)); + break; + case AST::Stmt::LabelStmtClass: + EmitLabelStmt(dynamic_cast(S)); + break; +#endif + //case AST::Stmt::AttributedStmtClass: + // EmitAttributedStmt(dynamic_cast(S)); break; + case AST::Stmt::GotoStmtClass: + EmitGotoStmt(dynamic_cast(S)); + break; + case AST::Stmt::BreakStmtClass: + EmitBreakStmt(dynamic_cast(S)); + break; + case AST::Stmt::OutputStmtClass: + EmitOutputStmt(dynamic_cast(S)); + break; + //case AST::Stmt::ContinueStmtClass: EmitContinueStmt(dynamic_cast(S)); break; + //case AST::Stmt::DefaultStmtClass: EmitDefaultStmt(dynamic_cast(S)); break; + case AST::Stmt::SwitchCaseStmtClass: + EmitSwitchCaseStmt(dynamic_cast(S)); + break; + } +#if 0 +STMT(ReturnStmt,Stmt) +STMT(ForStmt,Stmt) +STMT(OutputStmt,Stmt) +STMT(AsmStmt,Stmt) +STMT(LdsAsmStmt,AsmStmt) +#endif + return true; +} + + + +/** + * + */ +void CodeGenFunction::EmitOutputStmt(AST::OutputStmt *S) +{ + AST::EventDecl *sig = S->getEventDecl(); + aeb::lds::Value *v = m_CGM.getModule().getOrInsertSignal(sig->getName()); + aeb::lds::SendEventInst *c = m_Builder.CreateOutput(v); + + CGDBG_ARGS("CodeGenFunction::EmitOutputStmt %s Args=%d",sig->getName(),S->getNumArgs()); + /* Process Arguments */ + int ParamIdx = 1; + AST::Stmt::range_iterator rit = S->children() ; + for ( AST::Stmt::child_iterator it = begin(rit) + ; it != end(rit) + ; ++it, ParamIdx++ ) + { + aeb::lds::Value *value = NULL; + + if ( AST::StringLiteral *u = dynamic_cast(*it) ) + { + // + // This is wrong. I should check from which context is the parameter. + // Only if the parameter name is from global context + std::cerr<<"ERROR: CodeGenFunction::EmitOutputStmt Parameter is StringLiteral NOT GOOD missing declaration "<getString()<getString(),false); + if (c) + { + // Call c function there is no definition or body + //TODO Missing the type here + std::cout<<"CodeGenFunction::EmitOutputStmt C call "<getName(); + std::cout<<" p:"<getString()<addParam(reinterpret_cast(value)); + } + } else if ( AST::DeclRefExpr *u = dynamic_cast(*it) ) + { + AST::ValueDecl *nv = dynamic_cast(u->getDecl()); + AST::ParmVarDecl *pv = dynamic_cast(u->getDecl()); + if (pv) + { + value = getCurrentFunction()->getArgument(pv->getName()); + if (value) + { + std::cout<<"CodeGenFunction::EmitOutput "<getName(); + std::cout<<" FOUND Param "<getName()<<" Idx="<getType() == NULL)<getName(); + std::cout<<" Param NamedDecl: "<getName()<<" "<addParam(reinterpret_cast(value)); + } + } else if ( AST::Expr *u = dynamic_cast(*it) ) + { + std::cout<<"CodeGenFunction::EmitOutputStmt call "<getName(); + std::cout<<" TODO parameter is expression"<getName(); + std::cout<<" TODO parameter is may be a constant "<getOpcode()) { + case AST::LdsAsmStmt::AEL_RETURN: + { + aeb::lds::ReturnInst *c = m_Builder.CreateRetVoid(); + } + break; + case AST::LdsAsmStmt::AEL_RESET: + { + if (S->isArgVariable()) + { + //m_CGM.getOrCreateGlobal(S->getLiteral()->getString()); + m_CGM.getOrCreateGlobal(S->getVarDecl()); + aeb::lds::Instruction *c = m_Builder.CreateReset(S->getLiteral()->getString()); + } else if (S->isArgTimer()) + { + std::cout<<"CodeGenFunction::EmitLdsAsmStmt TODO RESET TIMER"<isArgVariable()) + { + //m_CGM.getOrCreateGlobal(S->getLiteral()->getString()); + m_CGM.getOrCreateGlobal(S->getVarDecl()); + aeb::lds::Instruction *c = m_Builder.CreateSet(S->getLiteral()->getString()); + } else if (S->isArgTimer()) + { + std::cout<<"CodeGenFunction::EmitLdsAsmStmt TODO SET TIMER"<getLiteral()->getString(),false); + aeb::lds::Instruction *c = m_Builder.CreateJsrInd(S->getLiteral()->getString()); + } + break; + case AST::LdsAsmStmt::AEL_RTS: + { + aeb::lds::ReturnInst *c = m_Builder.CreateRetSub(); + } + break; + case AST::LdsAsmStmt::AEL_NOP: + { + aeb::lds::Instruction *c = m_Builder.CreateNop(); + } + break; + case AST::LdsAsmStmt::AEL_LOOP_MSG: + { + // AST::EventDecl *sig = S->getEventDecl(); + aeb::lds::Value *v = m_CGM.getModule().getOrInsertSignal(S->getLiteral()->getString()); + aeb::lds::Instruction *c = m_Builder.CreateSendEvent(v); + } + break; + default: + std::cout<<"EmitLdsAsmStmt UNKNOWN Statement ... "<getStmtClass()<begin() ; it != S->end() ; ++it) + EmitStmt(*it); + + aeb::lds::BasicBlock *outgoing = m_Builder.GetInsertBlock(); + if (incoming != outgoing) + { + //std::cout<<"CodeGenFunction::EmitCompoundStmt Clear Insert :"<(S->getCalleeDecl()) ; + aeb::lds::BasicBlock *BB = m_Builder.GetInsertBlock(); + int ParamIdx = 0; + if (! BB) + { + std::cout<<"CodeGenFunction::EmitCallExpr ERROR BB== NULL "<getName()<(S->getCalleeDecl()) ; + std::cout<<"CodeGenFunction::EmitCallExpr Problem, d is not of type FunctionDecl "<getStmtClass()<getCalleeDecl()) { + std::cout<<"CodeGenFunction::EmitCallExpr no callee "<getString()<getName()<getName()<<" )"<hasDefinition()) + { + // Jump to Function ... CreateJsr Value not string + m_Builder.CreateJsr(d->getName()); + } else + c= m_Builder.CreateCall(d->getName()); + // Handle Parameter stuff to complete the Call. + // Also add function declaration in module + m_CGM.EmitGlobalFunctionDefinition(d,true); + // Parameters should be defined as globalVariables !!!! + // For now, we add the parameters in the CallInst ... + AST::Stmt::range_iterator rit = S->children() ; + for ( AST::Stmt::child_iterator it = begin(rit) + ; it != end(rit) + ; ++it, ParamIdx++ ) + { + aeb::lds::Value *value = NULL; + if ( AST::StringLiteral *u = dynamic_cast(*it) ) + { + // + // This is wrong. I should check from which context is the parameter. + // Only if the parameter name is from global context + std::cerr<<"ERROR: CodeGenFunction::EmitCallExpr Parameter is StringLiteral NOT GOOD missing declaration "<getString()<getString(),false); + if (c) + { + // Call c function there is no definition or body + //TODO Missing the type here + std::cout<<"CodeGenFunction::EmittCallExpr C call "<getName()<<" p:"<getString()<addParam(reinterpret_cast(value)); + } else { + // Internal defined Function do not have parameters yet + std::cout<<"CodeGenFunction::EmittCallExpr call "<getName()<<" of defined function with parameters not supported"<(*it) ) + { + AST::ValueDecl *nv = dynamic_cast(u->getDecl()); + AST::ParmVarDecl *pv = dynamic_cast(u->getDecl()); + if (pv) + { + value = getCurrentFunction()->getArgument(pv->getName()); + if (value) + { + std::cout<<"CodeGenFunction::EmitCallExpr "<getName()<<" FOUND Param "<getName()<<" Idx="<getType() == NULL)<getName()<<" Param NamedDecl: "<getName()<<" "<addParam(reinterpret_cast(value)); + } + } else if ( AST::Expr *u = dynamic_cast(*it) ) + { + std::cout<<"CodeGenFunction::EmittCallExpr call "<getName()<<" TODO parameter is expression"<getName()<<" TODO parameter is may be a constant "<getParent()) { + // Place the block after the current block + // std::cout<<"CodeGenFunction::EmitBlock insert in "<getName()<<" after ("<getName()<<") block (" << target->getName()<<")"<getBlockList().insertAfter(cb->getIterator(),target); + } else { + // Place The blck aat the end + // std::cout<<"CodeGenFunction::EmitBlock insert in "<getName()<<" end "<getName()<getBlockList().push_back(target); + } + // std::cout<<"CodeGenFunction::EmitBlock insert in "<getName()<<" New Size "<getBlockList().size()<getTerminator()) + { + // If there is no curBlock or if curBlock is terminated. Don't do + // anything + /* I have in Issue with if expr the execute call else do something else endif + * Because execute is a Terminator + */ +#if 0 + std::cout<<"CodeGenFunction::EmitBranch... !curBB || curBB->getTerminator() "; + if (curBB) + { + std::cout<<" Clear Insert Point "<getName()<getName()< +#include +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace aeb { +namespace lds { +namespace CodeGen { + + + CodeGenModule::CodeGenModule(AST::ASTContext &C, aeb::lds::Module *m) + : m_Context(C),m_Module(m) , m_CodeGenType(*this) + { + } + + void CodeGenModule::EmitTopLevelDecl(AST::Decl *decl) + { + switch (decl->getKind() ) { + case AST::DeclBase::FunctionDecl : + EmitGlobalFunctionDefinition(dynamic_cast(decl),false); + break; + case AST::DeclBase::StateDecl : + EmitGlobalStateDefinition(dynamic_cast(decl)); + break; + case AST::DeclBase::TransitionDecl : + std::cout<<"CodeGenModule::EmitTopLevelDecl Transition:"<getKind()<(decl)); + } + break; + case AST::DeclBase::TimerDecl : + { + EmitTimerDefinition(dynamic_cast(decl)); + } + break; + case AST::DeclBase::VarDecl : + { + AST::VarDecl *v = dynamic_cast(decl); + if (v->isConstant()) + { + EmitConstantValueInit(v); + } else + EmitGlobalVarDefinition(dynamic_cast(decl)); + } + break; + case AST::DeclBase::LabelDecl : + { + AST::LabelDecl *l = dynamic_cast(decl); + std::cout<<"CodeGenModele::EmitTopLevelDecl Label "; + std::cout<getName()<<" "<getKind()<(decl); + std::cout<<"CodeGenModele::EmitTopLevelDecl Typedef: TODO "<getName()<(decl)); + break; + case AST::DeclBase::AutomatonDecl: + case AST::DeclBase::PackageDecl: + case AST::DeclBase::SystemDecl: + case AST::DeclBase::BlockDecl: + std::cout<<"CodeGenModele::EmitTopLevelDecl Ingore: Auth decl,PckDecl,SysDecl,BlcDecl"<getKind()<<")"<hasDefinition() && ! onlydef) { + // std::cout<<"Emit Code For Function "<<_d->getName()<getOrInsertFunction(_d->getName(),NULL,aeb::lds::Function::Local); + CodeGenFunction m_CGF(*this,aeb::lds::Builder()); + m_CGF.GenerateCode(_d,Fct); + + } else { + // std::cout<<"Emit Code For Function "<<_d->getName()<<" Builder Not called Params:"<<_d->param_size()<getOrInsertFunction(_d->getName(),NULL,aeb::lds::Function::ExternalLink); + // I need the function signature in order to be able to call the right code + Fct->setNbParams(_d->param_size()); + if ( _d->param_size() != Fct->args().size()) + for (AST::FunctionDecl::const_param_iterator pit = _d->param_begin() + ; pit != _d->param_end() + ; ++pit) + { + if (AST::ParmVarDecl *pv = dynamic_cast(*pit)) + { + aeb::lds::Type *iTy = NULL; + if (pv->getType() != NULL) + { +#if 1 + iTy = getType().ConvertType(pv->getType()); +#else + // std::cout<<"CodeGenModule::EmitGlobalFunctionDefinition "<getName()<<" Has type "; + switch (pv->getType()->getClass()) + { + case AST::Type::Builtin : + case AST::Type::Typedef : + { + AST::BuiltinType *bTy = dynamic_cast(pv->getType()); + // std::cout<getNameAsStr(); + iTy = getType().ConvertType(pv->getType()); + } + break; + default: + //std::cout<<" Used Defined"; + std::cerr<<"EmitGlobalFunctionDefinition "<getName()<<" Unhandled type"<getKind()<<" "<<_d->getName()<(_d); + // Simply loop through + if (DC) { + aeb::lds::State *state = new State(_d->getName()); + m_Module->getOrInsertState(_d->getName(),state); + + for (AST::DeclContext::decl_iterator it = DC->begin(); it != DC->end() ; ++it ) + { + if ( AST::TransitionDecl *t = dynamic_cast(*it)) + { + //std::cout<<"Emit Code For State "<getName()<<"Transition "<getName()<getOrInsertFunction(t->getName()); + + CodeGenFunction m_CGF(*this,aeb::lds::Builder()); + // Add Parameters to the function before generating the code + AST::EventDecl *e = *(t->events_begin()); + if ( e->param_size() > 0 ) + { + //std::cout<<"Function "<getName()<<" Has parameters "; + for (AST::FunctionDecl::const_param_iterator pit = e->param_begin() + ; pit != e->param_end() + ; ++pit) + { + //std::cout<<" <"<<(*pit)->getName()<<">"; + aeb::lds::Argument *arg = new Argument((*pit)->getName(),Fct); + } + //std::cout<events_begin() ; evt != t->events_end() ; ++evt ) + { + // std::cout<<"EmitGloblStateDef:: Create "<getName()<<" Transition for Event "<<(*evt)->getName()<getName()); + aeb::lds::Signal *sig = GetSignal(*evt); + state->insertTransition(lTransition,sig,Fct,t->getTargetState()); + } + // Generated code should be in lTransition. I should be able to do the Same with Global Functions. + // Add The Transition into Module + } + } + } else { + std::cerr<<"WRONG Decl"<getName()<getName()<getOrInsertSignal(e->getName()); + Sig->setNbParams(e->param_size()); + if ( e->param_size() != Sig->args().size()) + { + std::cout<<"CodeGenModele::GetSignal:"; + std::cout<<" "<getName()<<" Set Type for argument "<param_begin() + ; pit != e->param_end() + ; ++pit) + { + aeb::lds::Type *iTy = NULL; + if (AST::ParmVarDecl *pv = dynamic_cast(*pit)) + { + iTy = getType().ConvertType(pv->getType()); + } + aeb::lds::SigArgument *arg = new SigArgument((*pit)->getName(),Sig); + arg->setType(iTy); + } + } + return Sig; + } + /** + * Get Or create LDS Variable + */ + aeb::lds::GlobalVariable *CodeGenModule::GetGlobalVariable(AST::VarDecl *D) + { + GlobalVariable *GV; + CGDBG_ARGS("CodeGenModule::GetGlobalVariable %s", + D->getName()); + aeb::lds::Type *Ty = getType().ConvertType(D->getType()); + GV =m_Module->insertGlobal(D->getName(),false,Ty); + return GV; + } + + + /** + * + */ + void CodeGenModule::EmitConstantValueInit(AST::VarDecl *D) + { + GlobalVariable *GV; + std::cout<<"CodeGenModule::EmitConstantValueInit TODO Var:"; + std::cout<<" "<getName()<getType()); + GV =m_Module->insertGlobal(D->getName(),true,Ty); + } + /** + * + */ + void CodeGenModule::EmitGlobalVarDefinition(AST::VarDecl *D) + { + GlobalVariable *GV; + CGDBG_ARGS("CodeGenModule::EmitGlobalVarDefinition ", + ,D->getName()); + aeb::lds::Type *Ty = getType().ConvertType(D->getType()); + GV =m_Module->insertGlobal(D->getName(),false,Ty); + } + /** + * + */ + void CodeGenModule::EmitTimerDefinition(AST::TimerDecl *D) + { + std::cout<<"CodeGenModule::EmitTimerDefinition "; + std::cout<<" "<getName()<getOrInsertSignal(D->getName()); + } +#if 1 + /* + * + * + */ + GlobalVariable * CodeGenModule::getOrCreateGlobal(const std::string &_flag,bool constant,void *_Ty ) + { + GlobalVariable *GV; + std::cout<<"CodeGenModule::getOrCreateGlobal deprecated: "<<_flag<insertGlobal(_flag,constant); + return GV; + } +#endif + GlobalVariable * CodeGenModule::getOrCreateGlobal(const AST::ValueDecl *D) + { + GlobalVariable *GV; + aeb::lds::Type *Ty = getType().ConvertType(D->getType()); + //std::cout<<"CodeGenModule::getOrCreateGlobal "<getName()<insertGlobal(D->getName(),Ty); + return GV; + } +} +} +} +/** + * vim: sw=2 et ts=2 list: + */ diff --git a/CodeGen/CMakeLists.txt b/CodeGen/CMakeLists.txt new file mode 100644 index 0000000..10670be --- /dev/null +++ b/CodeGen/CMakeLists.txt @@ -0,0 +1,13 @@ +PROJECT(AST) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/) +INCLUDE_DIRECTORIES(${aebutils_SOURCE_DIR}) + + +ADD_LIBRARY(commonCodeGen + CGFunction.cpp + ModuleBuilder.cpp + CGModule.cpp + CGExprScalar.cpp + CodeGenType.cpp + ) diff --git a/CodeGen/CodeGenType.cpp b/CodeGen/CodeGenType.cpp new file mode 100644 index 0000000..a38e8f0 --- /dev/null +++ b/CodeGen/CodeGenType.cpp @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace aeb { +namespace lds { +namespace CodeGen { + + + CodeGenType::CodeGenType(CodeGenModule &CGM) + : m_Module(CGM), m_Context(CGM.getContext()) + { + } + + aeb::lds::Type * + CodeGenType::ConvertBuiltinType(AST::BuiltinType *BITy) + { + switch (BITy->getKind()) + { + case AST::BuiltinType::Integer: + return aeb::lds::Type::getPrimitiveType(aeb::lds::Type::IntegerTyID); + case AST::BuiltinType::Boolean: + return aeb::lds::Type::getPrimitiveType(aeb::lds::Type::IntegerTyID); + case AST::BuiltinType::Char: + return aeb::lds::Type::getPrimitiveType(aeb::lds::Type::IntegerTyID); + case AST::BuiltinType::String: + return aeb::lds::Type::getPrimitiveType(aeb::lds::Type::ArrayTyID); + case AST::BuiltinType::Natural: + return aeb::lds::Type::getPrimitiveType(aeb::lds::Type::TimeTyID); + case AST::BuiltinType::Time: + return aeb::lds::Type::getPrimitiveType(aeb::lds::Type::TimeTyID); + case AST::BuiltinType::Duration: + return aeb::lds::Type::getPrimitiveType(aeb::lds::Type::DurationTyID); + case AST::BuiltinType::Pid: + return aeb::lds::Type::getPrimitiveType(aeb::lds::Type::PidTyID); + case AST::BuiltinType::Void: + return aeb::lds::Type::getPrimitiveType(aeb::lds::Type::VoidTyID); + default: + return aeb::lds::Type::getPrimitiveType(aeb::lds::Type::VoidTyID); + } + } + + aeb::lds::Type * + CodeGenType::ConvertType(AST::Type *Ty) + { + + if (Ty) + { + if (Ty->getClass() == AST::Type::Builtin) + { + AST::BuiltinType *BITy = dynamic_cast(Ty); + return ConvertBuiltinType(BITy); + }else if (Ty->getClass() == AST::Type::Typedef) + { + AST::TypedefType *TDTy = dynamic_cast(Ty); + AST::TypedefDecl *td = static_cast(TDTy->getDecl()); + return ConvertType(td->getBaseType()); + }else + { + std::cerr<<"CodeGenType::ConvertType Not builtin TODO return NULL not good"< +#include +#include +#include +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/DeclContext.h" + + +#include +#include +#include + + +#include +#include +#include + +#include +#include +#include "CodeGen/CodeGenModule.h" +#include + + +#include "CodeGen/ModuleBuilder.h" +namespace aeb { + namespace lds { + namespace CodeGen { + +/** + * + * + */ +class CodeGeneratorImpl : public CodeGenerator { + + protected: + CodeGenModule *m_Builder; + aeb::lds::Module *m_Module; + // unique_ptr only available in c++11 + // std::unique_ptr m_Module2; + public: + CodeGeneratorImpl(AST::ASTContext &C,const std::string &_mn) { + m_Module = new aeb::lds::Module(_mn); + m_Builder = new CodeGenModule(C,m_Module); + } + + virtual ~CodeGeneratorImpl() { + delete m_Builder; + } + + aeb::lds::Module *GetModule() { + return m_Module; + } + aeb::lds::CodeGen::CodeGenModule *GetBuilder() { + return m_Builder; + } + + void HandleTopLevelEvents(AST::AutomatonDecl *aut) { + for (AST::AutomatonDecl::event_iterator it = aut->events_begin() ; + it != aut->events_end(); + ++it ) { + // std::cout<<"Have Event: "<<(*it)->getName()<< " TODO add in module"<EmitTopLevelDecl(*it); + } + } + + void HandleTopLevelEvents(AST::AgentTypeDecl *aut) { + for (AST::AgentTypeDecl::event_iterator it = aut->events_begin() ; + it != aut->events_end(); + ++it ) { + // std::cout<<"Have Event: "<<(*it)->getName()<< " TODO add in module"<EmitTopLevelDecl(*it); + } + } + /** + * + */ + void HandleTopLevelDecl(AST::Decl *_decl) { + AST::DeclContext *DC = dynamic_cast(_decl); + // Get All events first + if (AST::AutomatonDecl *aut = dynamic_cast(_decl)) { + HandleTopLevelEvents(aut); + } else if (AST::AutomatonTypeDecl *autt = dynamic_cast(_decl)) { + HandleTopLevelEvents(autt); + } + // Simply loop through + if (DC) { + for (AST::DeclContext::decl_iterator it = DC->begin(); it != DC->end() ; ++it ) { + if (! dynamic_cast(*it)) + m_Builder->EmitTopLevelDecl(*it); + } + } else { + std::cout<<"CodeGeneratorImpl::HandleTopLevelDecl:: WRONG Decl"< +#include +#include +#include +#include "IR/Value.h" +#include "IR/Type.h" +#include "IR/Transition.h" +#include "IR/Behavior.h" +#include "IR/Function.h" +#include "IR/Signal.h" +#include "IR/Argument.h" +#include "IR/BasicBlock.h" +#define FUNCTION_SYMTAB +// May be Create TraitsSigArgumentImpl.h +#include "IR/SymbolTableTraitsImpl.h" +#include "IR/LdsInstruction.h" +namespace aeb { + // Template instantiation + + typedef dlilist lst; + +template <> +void SymbolTableListTraits::addNodeToList(aeb::lds::SigArgument *s) +{ + ItemParent *p = getListOwner(); + if ( !p || s->getParent() != NULL) + { + std::cerr<<"SymbolTable::addNodeToList Big Problem Parent:"; + } + else + { + s->setParent(p); + std::cout<<"SymbolTableListTraits Signal "<getName()<<" before: "<getNbParams(); + std::cout<<" After:"<getNbParams()<args().push_back(this); + } + } + + SigArgument::SigArgument(const std::string &Ty,Signal *p) + : m_Parent(NULL), Value(Type::getPrimitiveType(Type::VoidTyID),ArgumentVal) + { + setName(Ty); + if (p) + { + p->args().push_back(this); + } + } + + +} +} diff --git a/IR/BasicBlock.cpp b/IR/BasicBlock.cpp new file mode 100644 index 0000000..3874bcf --- /dev/null +++ b/IR/BasicBlock.cpp @@ -0,0 +1,56 @@ +#include +#include +#include +#include +// #include "aeb/dlilist.h" +// #include "aeb/dlilist_node.h" +// #include "IR/SymbolTableTraits.h" +#include "IR/BasicBlock.h" +#include "IR/Transition.h" +#include "IR/Function.h" +#include "IR/Value.h" +#include "IR/Argument.h" +#include "IR/SymbolTableTraitsImpl.h" +#include "IR/LdsInstruction.h" +namespace aeb { + +template class SymbolTableListTraits; +namespace lds { + + + +BasicBlock::BasicBlock(const BasicBlock &p,const std::string &name , BasicBlock *parent ) + : Value(NULL,BasicBlockVal) ,m_Name(name) ,m_Instructions() ,m_Parent(NULL) +{ + //m_Instructions.test(); +}; + +BasicBlock::BasicBlock(const std::string &name,BasicBlock *parent ) + : Value(NULL,BasicBlockVal), m_Name(name) , m_Instructions() ,m_Parent(NULL) +{ + //std::cout<<"Build::BB ctor"<NbOpcode(); + return s; +} + +size_t BasicBlock::NbOpcode(iterator ¤t) const +{ + size_t s = 0; + for ( const_iterator i = begin() ; i != current ; ++i) + s+= (&(*i))->NbOpcode(); + return s; +} + + +} +} diff --git a/IR/CMakeLists.txt b/IR/CMakeLists.txt new file mode 100644 index 0000000..6dc44e5 --- /dev/null +++ b/IR/CMakeLists.txt @@ -0,0 +1,18 @@ +PROJECT(AST) + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../include/) +INCLUDE_DIRECTORIES(${aebutils_SOURCE_DIR}) + + +ADD_LIBRARY(commonIR + LdsInstruction.cpp + BasicBlock.cpp + Transition.cpp + Argument.cpp + GlobalVariable.cpp + Module.cpp + State.cpp + Value.cpp + Type.cpp + User.cpp + ) diff --git a/IR/GlobalVariable.cpp b/IR/GlobalVariable.cpp new file mode 100644 index 0000000..08b2b51 --- /dev/null +++ b/IR/GlobalVariable.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include "IR/Value.h" +#include "IR/Type.h" +#include "IR/Transition.h" +#include "IR/Behavior.h" +#include "IR/Function.h" +#include "IR/Signal.h" +#include "IR/Argument.h" +#include "IR/BasicBlock.h" +#define FUNCTION_SYMTAB +// May be Create TraitsSigArgumentImpl.h +#include "IR/GlobalVariable.h" +namespace aeb { + // Template instantiation +namespace lds { + +GlobalVariable::GlobalVariable(const std::string &flg , bool constant,Type *_Ty) + : m_IsConstant(constant) + , Constant(_Ty, GlobalVariableVal,OperandTraits::op_begin(this),1) + , m_Parent(NULL) +{ + Value::setName(flg); +} + +void +GlobalVariable::setInitializer(Constant *InitVal) +{ +} + +Constant * +GlobalVariable::getInitializer() +{ + return NULL; +} + +} +} diff --git a/IR/LdsInstruction.cpp b/IR/LdsInstruction.cpp new file mode 100644 index 0000000..2980090 --- /dev/null +++ b/IR/LdsInstruction.cpp @@ -0,0 +1,559 @@ +#include +#include +#include +#include +#include "aeb/dlilist.h" +#include "aeb/dlilist_node.h" +#include "IR/LdsInstruction.h" +#include "IR/SymbolTableTraits.h" +#include "IR/BasicBlock.h" +#include "IR/Type.h" +#include "IR/Value.h" +#include "IR/GlobalVariable.h" +#include "IR/Function.h" +#include "IR/Argument.h" +#include +#include +//#define DEBUG_OPCODE +//#define DEBUG_BRANCH +namespace aeb { +namespace lds { + +// Remove Instruction from BasicBlock. No delete +void Instruction::removeFromParent() +{ + std::cout<<"TOBE CODED removeFromParent"<::op_end(this) - 2 ,2) +{ +#ifdef DEBUG_BRANCH + std::cout<<"BranchInst::BranchInst "<() = IfTrue; + if (IfFalse) + { +#ifdef DEBUG_BRANCH + std::cout<<"\tBranchInst::BranchInst "<<&Op<-1>()<() = IfFalse; + } + setName("Br"); +} + +/** + * Too complicated think about something better + */ +int BranchInst::ThenLength() +{ + int length = 0; + aeb::lds::BasicBlock *b = NULL ,*pB=getParent(); + if (getParent() && getTrue()) + { + if ( ( (b = getParent()->getNextNode()) == getTrue()) && ! getFalse()) + { +#ifdef DEBUG_BRANCH + std::cout<<"BranchInst ThenLength parent == m_Block[BTRUE]"<<" "<size(); + } else if ((pB->getParent() != getTrue()->getParent() ) + || (getTrue()->getParent() == NULL) + ) + { +#ifdef DEBUG_BRANCH + std::cout<<"BranchInst::ThenLength Instruction ERROR and dest not in same function "<<" "<getParent()<getNextNode(); + while ( (b != getTrue()) && b!=NULL) + { + length += b->NbOpcode(); + b = b->getNextNode(); + } + length--; + } else { + int countb = 0; + b = pB->getNextNode(); + while ( (b != getTrue()) && b!=NULL) { + length += b->NbOpcode(); + b = b->getNextNode(); + countb++; + } +#ifdef DEBUG_BRANCH + std::cout<<"BranchInst::ThenLength parent->next != getTrue()"<<" b="<getPrevNode(); + while ( (b != getTrue()) && b!=NULL) { + length += b->NbOpcode(); + b = b->getPrevNode(); + } + if (b) + { + length += b->NbOpcode(); + setOpcode(AEL_JUMP_MOINSOpcode); + } + } else if ((b == NULL) && length) { + length--; + } + } + } +#ifdef DEBUG_BRANCH + std::cout<<"BranchInst::ThenLength before exit "<<" length="<getName(); + oss<<" ) True Direct Branch "; + oss<<" */"; +#endif + } else { + oss<getNextNode() == getTrue() )) + { + return 0; + } else { + return 2; + } +} + +/**============================================================================ + * BranchCondInst Implementation + */ +int BranchCondInst::ThenLength() +{ + int length = 0; + aeb::lds::BasicBlock *b = NULL ,*pB=getParent(); + if (getParent() && getTrue()) + { + if ( ( (b = getParent()->getNextNode()) == getTrue()) + && ! getFalse()) + { +#ifdef DEBUG_BRANCH + std::cout<<"BranchCondInst ThenLength parent->next == m_Block[BTRUE]"<<" length="<size()<size(); + } else if ((pB->getParent() != getFalse()->getParent() ) + || (getFalse()->getParent() == NULL) + ) + { +#ifdef DEBUG_BRANCH + std::cout<<"BranchCondInst::ThenLength Instruction ERROR and dest not in same function "<<" "<getParent()<NbOpcode(); + b = b->getNextNode(); + } + length--; + } + else + { + b = getTrue(); + while ( (b) && (b != getFalse())) + { + length += b->NbOpcode(); + b = b->getNextNode(); + } +#ifdef DEBUG_BRANCH + std::cout<<"BranchCondInst ThenLength parent->next != m_Block[BTRUE]"<<" len="<getName(); + oss<<" ) false Cond Branch getTrue = "; + oss<getName()<<" */"; +#endif + } else { + oss<getNextNode()) == getHash() ) { + length = b->size(); + } else { + b = p->getNextNode(); + while ( (b != getHash()) && b!=NULL) { + length += b->NbOpcode(); + b = b->getNextNode(); + } + if (b == NULL) { + BasicBlock::iterator it(this); + length = p->NbOpcode(it) + this->NbOpcode(); +#ifdef DEBUG_BRANCH + std::cout<<"SwitchInst::TheLength ERROR Find Destination node backwords length="<getPrevNode(); + while ( (b != getHash()) && b!=NULL) { + length += b->NbOpcode(); + b = b->getPrevNode(); + } + if (b) + length += b->NbOpcode(); + if (b) + setOpcode(AEL_JUMP_MOINSOpcode); + } + } + } + + return length; +} + +const char *SwitchInst::getOpcodeName() +{ + std::ostringstream oss; + std::string res = Instruction::getOpcodeName(); + static std::string s; + //std::cerr<<"SwitchInst::getOpcodeName "<getName();//<<" /* ("<getName()<<" ) */"; + } else { + oss<getName(); + //std::cout<<"CreateLoadInst From Value :"<isGlobalVariable()) + { + const aeb::lds::GlobalVariable *gv = dynamic_cast(v); + if (gv) + m_Constant = gv->isConstant(); + } +} + +const char *LoadInst::getOpcodeName() +{ + static std::string s; + s = ""; + if (m_Value) + { + // Most likely an Argument + if (m_Value->isGlobalVariable()) + { + s+= "LOADV("+m_Flag+")"; + } else + { + aeb::lds::Argument *arg = dynamic_cast(m_Value); + aeb::lds::Function *fct= arg->getParent(); + if (fct) + { + int d = std::distance(fct->arg_begin() + ,aeb::lds::Function::ArgumentIterator(arg)); + std::ostringstream os; + os.str(""); + os<<"LOADP("<getName()+")"; + } else + { + s = Instruction::getOpcodeName(m_Opcode) ; + s+= " ," ; s+=m_Flag ; + } + return s.c_str(); +} + + +/**============================================================================ + * CallInst + */ +const char *CallInst::getOpcodeName() +{ + int i = 1; + std::stringstream si; + std::string s("e"); // See gen_aac why. It's linked to External function defines + s += m_callee.c_str(); + for ( std::vector::iterator it = m_Params.begin() + ; it != m_Params.end(); ++it) + { + s+= " , "; + si.str(""); + si<isArgument()) + { + s+= "CALL_PARAM_PV("+si.str()+","+(*it)->getName()+")"; + } else if ((*it)->isGlobalVariable()) + { + s+= "CALL_PARAM_GV("+si.str()+","+(*it)->getName()+")"; + } else { + s+= "CALL_PARAM_LV("+si.str()+","+(*it)->getName()+")"; + } + } + m_ret = s; + return m_ret.c_str(); +} + +/**============================================================================ + * SendEvenyInst implementation + **/ +const char * +SendEventInst::getOpcodeName() +{ + static std::string s; + int i = 1; + std::stringstream si; + s = Instruction::getOpcodeName(m_Opcode) ; + s+= " ," ; s+=m_Event; + + for ( std::vector::iterator it = m_Params.begin() + ; it != m_Params.end() + ; ++it,i++) + { + s+= " , "; + si.str(""); + si<isArgument()) + { + s+= "CALL_PARAM_PV("+si.str()+","+(*it)->getName()+")"; + } else if ((*it)->isGlobalVariable()) + { + s+= "CALL_PARAM_GV("+si.str()+","+(*it)->getName()+")"; + } else { + s+= "CALL_PARAM_LV("+si.str()+","+(*it)->getName()+")"; + } + } + return s.c_str(); +}; + +/**============================================================================ + * ExtractValueInst implementation + **/ +ExtractValueInst::ExtractValueInst(Value *v,int idx) + : Instruction(AEL_EXTRACTOpcode), m_Value(v),m_Index(idx) +{ + std::cout<<"ExtractValue:: got v="<getName()<getName()<<","<getName()) + , m_CmpInst(s) + , m_LoadConstant(lc) + , Instruction(op) + , m_Value(v) +{ +} + +const char *CmpInst::getOpcodeName() +{ + static std::string s; + if (m_Value) + { + s = "CMP_"+m_CmpInst+"("+m_Flag+")"; + } else + { + s = Instruction::getOpcodeName(m_Opcode) ; + s+= " ," ; s+=m_Flag; + } + return s.c_str(); +} + +/**============================================================================ + * Binary Operation Generation + */ +BinaryOperator::BinaryOperator(unsigned int op,Value *V1,Value *V2,BasicBlock *insertAf ) + : Instruction(op),m_V1(V1),m_V2(V2) +{ + if (m_V1) + { + } + if (m_V2) + { + } +} +/// +const char *BinaryOperator::getOpcodeName() +{ + static std::string s; + s = Instruction::getOpcodeName(m_Opcode) ; + /// FLAG_GLOBAL Depends on Order. Might work well with and and or + if (! m_V1) + { + s+= " ,FLAG_GLOBAL ," ; s+=m_Flag ; + } else + { + s+= " , "+m_V1->getName()+",FLAG_GLOBAL " ; + } + if (m_V1) + m_V1->getName(); + std::cout<<"BinaryOperator::getOpcodeName "< +#include +#include + +namespace aeb { + namespace lds { + class Instruction; + class Transition; + class Function; + } +}; +#include "IR/BasicBlock.h" +#include "IR/Transition.h" +#include "IR/Argument.h" +#include "IR/Function.h" +#include "IR/SymbolTableTraitsImpl.h" +#include "IR/Module.h" + +namespace aeb { +// template class SymbolTableTraits; +template class SymbolTableListTraits; +template class SymbolTableListTraits; + +namespace lds { + + + Module::Module(const std::string &s) : m_Name(s) + { + } + + Module::~Module() + { + // May be try to loop over all States and erase them + std::cout<<"Module::~Module"<getName()); + // if not, insert + } + + // Simple Function when GlobalVariable is just a Flag + GlobalVariable *Module::insertGlobal(const std::string &_flag,bool constant,Type *_Ty) + { + global_iterator it = std::find(global_begin(),global_end(),_flag); + if (it == global_end() ) { + GlobalVariable *GV = new GlobalVariable(_flag,constant,_Ty); + m_Globals.insert(m_Globals.end(),GV); + return GV; + } else { + return &(*it); + } + } + +} +} diff --git a/IR/State.cpp b/IR/State.cpp new file mode 100644 index 0000000..582a860 --- /dev/null +++ b/IR/State.cpp @@ -0,0 +1,34 @@ +#include +#include + +#include "IR/State.h" +#include "IR/Signal.h" +#include "IR/Transition.h" +#include "IR/SymbolTableTraitsImpl.h" +#include "IR/LdsInstruction.h" + +namespace aeb { + + // Template instantiation + +template class SymbolTableListTraits; + +namespace lds { + + + Transition *State::getOrInsertTransition(const std::string &_name,Transition *t) + { + m_Transitions.insert(m_Transitions.end(),t); + return t; + } + + void State::insertTransition(Transition *t,Signal *_evt,Function *fct,const std::string &_st) + { + t->setTargetState(_st); + t->setEvent(_evt); + t->setFunction(fct); + m_Transitions.insert(m_Transitions.end(),t); + } + +} +} diff --git a/IR/Transition.cpp b/IR/Transition.cpp new file mode 100644 index 0000000..3d8fd2b --- /dev/null +++ b/IR/Transition.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include "IR/Transition.h" +#include "IR/Behavior.h" +#include "IR/Function.h" +#include "IR/Argument.h" +#include "IR/State.h" +#include "IR/Signal.h" +#include "IR/Type.h" +#include "IR/Value.h" +#include "IR/SymbolTableTraitsImpl.h" +#include "IR/LdsInstruction.h" +namespace aeb { + // Template instantiation + + //template class SymbolTableTraits; + + // template class SymbolTableTraits; + + typedef dlilist lst; + lst tb; +namespace lds { + + +Behavior::Behavior(const Behavior &p ) + : m_Name(p.m_Name) ,Value(p) +{ +// std::cout<<"Behavior:: copy "<getName(); + } else + return m_TargetState ; }; + + +const std::string &Transition::getEvent() const +{ + return m_Event->getName(); +} + + +Function::Function(const std::string &s,FctType fc) + : Behavior(s,NULL,Value::FunctionVal) + , m_Parent(NULL) + , m_FctType(fc) + , m_NbParam(0) +{ +} + + +Signal::Signal(const std::string &s,FctType fc) + : Behavior(s,NULL,Value::SignalVal) + , m_Parent(NULL) + , m_FctType(fc) + , m_NbParam(0) +{ +} + +} +} diff --git a/IR/Type.cpp b/IR/Type.cpp new file mode 100644 index 0000000..d9e9c80 --- /dev/null +++ b/IR/Type.cpp @@ -0,0 +1,126 @@ +#include +#include +#include +#include "IR/Type.h" + +namespace aeb +{ +namespace lds +{ + +Type::Type(TypeID tid) + : m_TypeID(tid) , m_ContainedTypes(NULL), m_NbContainedTys(0) +{ +} + +Type * +Type::getPrimitiveType(TypeID tid) +{ + static Type VoidTy(VoidTyID); + static Type FloatTy(FloatTyID); + static Type LabelTy(LabelTyID); + static Type PidTy(PidTyID); + // Derived static Type (ID);'s + static Type IntegerTy(IntegerTyID); + static Type NaturalTy(NaturalTyID); + static Type TimeTy(TimeTyID); + static Type DurationTy(DurationTyID); + static Type FunctionTy(FunctionTyID); + static Type ArrayTy(ArrayTyID); + static Type PointerTy(PointerTyID); + + switch (tid) + { + case FloatTyID: return &FloatTy; + case LabelTyID: return &LabelTy; + case PidTyID: return &PidTy; + // Derived case ID: return &;'s + case IntegerTyID: return &IntegerTy; + case NaturalTyID: return &NaturalTy; + case TimeTyID: return &TimeTy; + case DurationTyID: return &DurationTy; + case FunctionTyID: return &FunctionTy; + case ArrayTyID: return &ArrayTy; + case PointerTyID: return &PointerTy; + default: + return &VoidTy; + }; +} + +void Type::print(std::ostream &os) const +{ + switch (m_TypeID) + { + case FloatTyID: os<<"double "; break; + case LabelTyID: os<<"LabelTy "; break; + case PidTyID: os<<"Pid "; break; + // Derived case ID: os<<""; break;'s + case IntegerTyID: os<<"long "; break; + case NaturalTyID: os<<"double "; break; + case TimeTyID: os<<"Time "; break; + case DurationTyID: os<<"Duration"; break; + case FunctionTyID: os<<"Function"; break; + case ArrayTyID: os<<"char * "; break; + case PointerTyID: os<<"void * "; break; + default: + os<<"void "; + }; +} + +void Type::printNative(std::ostream &os) const +{ + switch (m_TypeID) + { + case FloatTyID: os<<"double "; break; + case LabelTyID: os<<"LabelTy "; break; + case PidTyID: os<<"Pid "; break; + // Derived case ID: os<<""; break;'s + case IntegerTyID: os<<"long "; break; + case NaturalTyID: os<<"double "; break; + case TimeTyID: os<<"Time "; break; + case DurationTyID: os<<"Duration"; break; + case FunctionTyID: os<<"Function"; break; + case ArrayTyID: os<<"char * "; break; + case PointerTyID: os<<"void * "; break; + default: + os<<"void "; + }; +} + +void Type::printLds(std::ostream &os) const +{ + switch (m_TypeID) + { + case FloatTyID: os<<"Float "; break; + case LabelTyID: os<<"LabelTy "; break; + case PidTyID: os<<"Integer "; break; + // Derived case ID: os<<""; break;'s + case IntegerTyID: os<<"Integer "; break; + case NaturalTyID: os<<"Integer "; break; + case TimeTyID: os<<"Time "; break; + case DurationTyID: os<<"Duration"; break; + case FunctionTyID: os<<"Function"; break; + case ArrayTyID: os<<"String "; break; + case PointerTyID: os<<"User "; break; + default: + os<<"Integer "; + }; +} + + +const Type * +CompositeType::getTypeAtIndex(unsigned i) const +{ + assert( i < m_NbContainedTys && "out of range !"); + if (m_ContainedTypes && (i < m_NbContainedTys)) + { + return &m_ContainedTypes[i]; + } + +} + +} +} +/** + * ex: set et sw=4 ts=4 list: + */ diff --git a/IR/User.cpp b/IR/User.cpp new file mode 100644 index 0000000..fd203be --- /dev/null +++ b/IR/User.cpp @@ -0,0 +1,41 @@ +#include +#include +#include + + +namespace aeb { +namespace lds { + + +/// new operator +void * +User::operator new(size_t s, unsigned Us) +{ + //std::cout<<"User::new s="< +#include +#include +#include +#include +#include +#include +#include + + +#include "AST/Stmt.h" +#include "AST/Expr.h" +#include "AST/Decl.h" + +#include "AST/ASTRecursiveVisitor.h" +#include "IR/Module.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "LDSBytecode/AutomatonBytecode.h" + +/** + * First Traversal to calculate sizes entry points and + * so on. + */ +struct BStatistics : public aeb::lds::InstrVisitor +{ + unsigned int m_Transitions; + unsigned int m_States; + unsigned int m_NbI,m_NbIl; + unsigned int m_NbGlobals; + unsigned int m_NbCFunction; + unsigned int m_NbLdsFunction; + unsigned int m_NbSignals; + unsigned int m_ConstantCounter; + + typedef std::map ConstantMap; + typedef ConstantMap::iterator constant_iterator; + ConstantMap m_Constants; + + BStatistics() : m_Transitions(0) + , m_States(0) + , m_NbI(0) + , m_NbIl(0) + , m_NbCFunction(0) + , m_NbLdsFunction(0) + , m_NbSignals(0) + , m_ConstantCounter(0) + , m_NbGlobals(0) {} + + int getConstantIndex(const std::string &s) + { + constant_iterator it = m_Constants.find(s); + if (it != m_Constants.end()) + { + return it->second; + } else + { + return 0; + } + } + void visitTransition(aeb::lds::Transition &T) + { + aeb::lds::Function *f = T.getFunction(); + std::cout<<"TRAN "< "<getName()<<")"< "; + for ( int i = 0 ; i < I.getNbParameters() ; ++i) + { + aeb::lds::Value *param = I.getParameter(i); + int ci = getConstantIndex(param->getName()); + std::cout< "; + } + std::cout<<")"< General header + * -> Constants .... string, ints + * -> Signals that can be triggered + * -> States (Should be represented as an object ) + * (contains an array of functions each event for a transition + * is a function entry point + * therefore, two or more function can point the same code. + * see how to implement this + * ) + * -> LDS Task Is a Function as well + * -> External Function table / To be filled when loading ... + * -> What about global variables ? + * + */ +void +AutomatonBytecode::Generate(aeb::lds::Module &m_Module) +{ + BStatistics stat; + stat.visit(&m_Module); + + std::cout<<" BStatistics :"<begin() + ; it !=DC->end(); ++it) + { + AST::AutomatonDecl *automat = dynamic_cast(*it); + if (automat) + { + BStatistics stat; + aeb::lds::CodeGen::CodeGenerator *CG = + aeb::lds::CodeGen::CreateLdsGenerator(DC->getASTContext(),automat->getName()); + + std::cout<<"gen_code: process: "<getName()<HandleTopLevelDecl(automat); + // Something Like, CG->GetModule, AACGenerator act( stream,Module) + //act.generate + // Or bc BCGenerator(stream,Module) + // bc.save + aeb::lds::Module *m = CG->GetModule(); + stat.visit(m); + std::cout<<"Stats Module "<getName()< +#include + +#include "LDSExecutionEngine/LdsObject.h" +#include "LDSExecutionEngine/LdsExecutionContext.h" + + +namespace lds +{ + +CallInformation::CallInformation() + : m_previous(NULL), m_next(NULL) + , m_func(NULL) + , m_pc(NULL) +{ +} + +/** + * Execution Context + */ +ExecutionContext::ExecutionContext() + : m_stack(m_ec_stack) , m_top(m_stack) , m_base_ci() + , m_ci(&m_base_ci) +{ + +} + +/** + * Check the kind of function to execute. + * Is it an LDS TASK or a C function + * + */ +int +ExecutionContext::precall(StackIdx func,int nresults) +{ + return 1; +} + +void +ExecutionContext::postcall(StackIdx func,int nresults) +{ +} + +void +ExecutionContext::Load(const std::string &file_name) +{ +} + +} diff --git a/LDSExecutionEngine/LdsExecutionEngine.cpp b/LDSExecutionEngine/LdsExecutionEngine.cpp new file mode 100644 index 0000000..b26b561 --- /dev/null +++ b/LDSExecutionEngine/LdsExecutionEngine.cpp @@ -0,0 +1,268 @@ +#include +#include + +#include "LDSExecutionEngine/LdsObject.h" +#include "LDSExecutionEngine/LdsExecutionContext.h" +#include "LDSExecutionEngine/LdsExecutionEngine.h" + +#if 0 +#define LDSVM_LOG_DEBUG_FMT(x,args...) printf(x "\n", args) +#define LDSVM_LOG_DEBUG(x,args...) printf(x) +#else +#define LDSVM_LOG_DEBUG_FMT(x,args...) +#define LDSVM_LOG_DEBUG(x,args...) +#endif + + +namespace lds { + + + +void ExecutionEngine::AEL_NOP(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG("AEL_NOP"); + _c.incIP(); +} + +void ExecutionEngine::AEL_RETURN(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG("AEL_RETURN"); +} + +/** + * Change State + */ +void ExecutionEngine::AEL_ETAT(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_ETAT %d",_c.getOpcode(_c.getIP()+1)); + _c.setState(_c.getOpcode(_c.getIP() + 1)); + _c.incIP(2); +} + +void ExecutionEngine::AEL_JUMP_PLUS(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_JUMP_PLUS %d",_c.getOpcode(_c.getIP()+1)); + _c.incIP(2 + _c.getOpcode(_c.getIP() + 1 )); +} + +void ExecutionEngine::AEL_JUMP_PLUS_IF(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_JUMP_PLUS_IF %d %d" + ,_c.getOpcode(_c.getIP()) + ,_c.getOpcode(_c.getIP()+1)); + if (_c.Accumulator()) + { + _c.incIP(2+_c.getOpcode(_c.getIP()+1)); + } else { + _c.incIP(2); + } +} + +void ExecutionEngine::AEL_JUMP_PLUS_IF_NOT(ExecutionContext &_c) +{ + if (! _c.Accumulator()) { + LDSVM_LOG_DEBUG_FMT("AEL_JUMP_PLUS_IF_NOT %d %d" + ,_c.getOpcode(_c.getIP()) + ,_c.getOpcode(_c.getIP()+1)); + _c.incIP(2+_c.getOpcode(_c.getIP()+1)); + } else { + LDSVM_LOG_DEBUG("AEL_JUMP_PLUS_IF 0"); + _c.incIP(2); + } +} + +void ExecutionEngine::AEL_JUMP_MOINS(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_JMP_MOINS %d",_c.getOpcode(_c.getIP()+1)); + _c.decIP(_c.getOpcode(_c.getIP()+1)); +} + +void ExecutionEngine::AEL_JUMP_IND(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_JMP_IND %d",_c.getOpcode(_c.getIP()+1)); +} + +void ExecutionEngine::AEL_JSR(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_JSR %d",_c.getOpcode(_c.getIP()+1)); +} + +/** + * Used to call TASK. That's where I need to create a + * new execution context and be able to come back + */ +void ExecutionEngine::AEL_JSR_IND(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_JSR_IND %d TODO",_c.getOpcode(_c.getIP()+1)); +} + +/** + * This instruction is the last on before return from + * execution .... + */ +void ExecutionEngine::AEL_RTS(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_RTS %d TODO",_c.getOpcode(_c.getIP()+1)); +} + +void ExecutionEngine::AEL_SET(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_SET %d",_c.getOpcode(_c.getIP()+1)); + _c.Register(_c.getOpcode(_c.getIP()+1)) = 1; + _c.incIP(2); +} + +void ExecutionEngine::AEL_RESET(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_RESET %d",_c.getOpcode(_c.getIP()+1)); + _c.Register(_c.getOpcode(_c.getIP()+1)) = 0; + _c.incIP(2); +} + +/** + * Save content of FLAG_GLOBAL into FLAG_XXX + */ +void ExecutionEngine::AEL_CHARGE(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_CHARGE %d",_c.getOpcode(_c.getIP()+1)); + _c.Register(_c.getOpcode(_c.getIP()+1)) = _c.Register(FLAG_GLOBAL); + _c.incIP(2); +} + +void ExecutionEngine::AEL_TEST(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_TEST %d",_c.getOpcode(_c.getIP()+1)); + _c.Accumulator() = _c.Register(_c.getOpcode(_c.getIP()+1)); + _c.incIP(2); +} + + +void ExecutionEngine::AEL_LOOP_MSG(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_LOOP_MSG %d",_c.getOpcode(_c.getIP()+1)); + + //_c.m_EventQueue.push(_c.getOpcode(_c.getIP()+1)); + _c.incIP(2); +} + +/** + * This Instruction calls a C function + */ +void ExecutionEngine::AEL_CALL(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_CALL %d",_c.getOpcode(_c.getIP()+1)); + // Next opcode is the Function index May be just call + // _c.precall(); need to find the function entry +} + + +void ExecutionEngine::AEL_COMPL(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_COMPL %d",_c.getOpcode(_c.getIP()+1)); + _c.Register(_c.getOpcode(_c.getIP()+1)) = + ! _c.Register(_c.getOpcode(_c.getIP()+1)) ; + _c.incIP(2); +} + + +void ExecutionEngine::AEL_AND(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_AND %d",_c.getOpcode(_c.getIP()+1)); + _c.Register(FLAG_GLOBAL) = + _c.Register(_c.getOpcode(_c.getIP()+1)) + && _c.Register(_c.getOpcode(_c.getIP()+2)) ; + _c.incIP(3); +} + +void ExecutionEngine::AEL_OR(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_OR %d",_c.getOpcode(_c.getIP()+1)); + _c.Register(FLAG_GLOBAL) = + _c.Register(_c.getOpcode(_c.getIP()+1)) + || _c.Register(_c.getOpcode(_c.getIP()+2)) ; + _c.incIP(3); +} + +void ExecutionEngine::AEL_PLUS(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_PLUS %d",_c.getOpcode(_c.getIP()+1)); + _c.incIP(3); +} + +void ExecutionEngine::AEL_MOIN(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_MOIN %d",_c.getOpcode(_c.getIP()+1)); + _c.incIP(3); +} + +void ExecutionEngine::AEL_MUL(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_MUL %d",_c.getOpcode(_c.getIP()+1)); + _c.incIP(3); +} + +void ExecutionEngine::AEL_EQU(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_EQU %d",_c.getOpcode(_c.getIP()+1)); + _c.incIP(3); +} + +void ExecutionEngine::AEL_END(ExecutionContext &_c) +{ + LDSVM_LOG_DEBUG_FMT("AEL_END SHOULD NEVER BE CALLED%d",_c.getOpcode(_c.getIP()+1)); +} + +void +ExecutionEngine::Load(const std::string &file_name,ExecutionContext &e) +{ +} + +void +ExecutionEngine::run(ExecutionContext &c) +{ + StackIdx base; + CallInformation *ci = c.get_ci(); + ci->m_call_status |= CIST_FRESH; + + newframe: + base = ci->m_base; + + // Now loop over instructions + for (;;) + { + Instruction i = *(ci->m_pc++); + if ( i >=0 && i < lds::AEL_END) + { + //std::cout<<"Execute OP "< + +#include +#include +#include + +#include "ADT/Adt.h" +#include "UNIT-TEST-adt-sdl.h" + +CPPUNIT_TEST_SUITE_REGISTRATION( TC_TEST_adt_sdl); + + +void TC_TEST_adt_sdl::setUp() +{ + +} + +void TC_TEST_adt_sdl::TEST_Struct() +{ + ADT::StructType *t = ADT::StructType::Create("testStruct"); + ADT::PrimitiveType *b1 = ADT::BooleanType::Create("B1"); + ADT::PrimitiveType *b2 = ADT::IntegerType::Create("I2"); + t->addField(ADT::Field::Create("namd1",b1)); + t->addField(ADT::Field::Create("namd2",b2)); + CPPUNIT_ASSERT( t->size() == 2); +} + +void TC_TEST_adt_sdl::TEST_Choice() +{ + ADT::ChoiceType *t = ADT::ChoiceType::Create("testChoice"); + ADT::PrimitiveType *b1 = ADT::BooleanType::Create("B1"); + ADT::PrimitiveType *b2 = ADT::IntegerType::Create("I2"); + t->addField(ADT::Field::Create("namd1",b1)); + t->addField(ADT::Field::Create("namd2",b2)); + CPPUNIT_ASSERT( t->size() == 2); +} + + +void TC_TEST_adt_sdl::TEST_Module() +{ + ADT::Module *m = ADT::Module::Create("m1"); + ADT::PrimitiveType *b1 = ADT::BooleanType::Create("B1"); + ADT::PrimitiveType *b2 = ADT::IntegerType::Create("B2"); + m->insert(b1); + m->insert(b2); + CPPUNIT_ASSERT(m->size() == 2); +} + +void TC_TEST_adt_sdl::TEST_Module_lookup_ok() +{ + ADT::Module *m = ADT::Module::Create("m1"); + ADT::PrimitiveType *b1 = ADT::BooleanType::Create("B1"); + m->insert(b1); + CPPUNIT_ASSERT(m->lookup("B1") != NULL); +} + +void TC_TEST_adt_sdl::TEST_Module_lookup_failed() +{ + ADT::Module *m = ADT::Module::Create("m1"); + ADT::PrimitiveType *b1 = ADT::BooleanType::Create("B1"); + m->insert(b1); + CPPUNIT_ASSERT(m->lookup("dede") == NULL); +} diff --git a/UnitTests/UNIT-TEST-adt-sdl.h b/UnitTests/UNIT-TEST-adt-sdl.h new file mode 100644 index 0000000..c96ae66 --- /dev/null +++ b/UnitTests/UNIT-TEST-adt-sdl.h @@ -0,0 +1,29 @@ +#ifndef TESTCASE_SIMPLETYPE_H +#define TESTCASE_SIMPLETYPE_H + +#include + +#include "ADT/Adt.h" + +class TC_TEST_adt_sdl : public CPPUNIT_NS::TestFixture +{ + CPPUNIT_TEST_SUITE( TC_TEST_adt_sdl ); + CPPUNIT_TEST(TEST_Struct); + CPPUNIT_TEST(TEST_Choice); + CPPUNIT_TEST(TEST_Module); + CPPUNIT_TEST(TEST_Module_lookup_ok); + CPPUNIT_TEST(TEST_Module_lookup_failed); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp(); + protected: + + void TEST_Struct(); + void TEST_Choice(); + void TEST_Module(); + void TEST_Module_lookup_ok(); + void TEST_Module_lookup_failed(); +}; + +#endif diff --git a/UnitTests/main_test.cpp b/UnitTests/main_test.cpp new file mode 100644 index 0000000..ebb6b4d --- /dev/null +++ b/UnitTests/main_test.cpp @@ -0,0 +1,46 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + + + +int main(int argc,char **argv) +{ + //asn1::types::debug_level = 9; + + // if ( (argc > 1) && strcmp(argv[1],"-r") == 0) + // asn1::types::debug_level = 1; + + // Create the event manager and test controller + CPPUNIT_NS::TestResult controller; + + // Add a listener that colllects test result + CPPUNIT_NS::TestResultCollector result; + controller.addListener( &result ); + + // Add a listener that print dots as test run. + CPPUNIT_NS::BriefTestProgressListener progress; + controller.addListener( &progress ); + + // Add the top suite to the test runner + CPPUNIT_NS::TestRunner runner; + runner.addTest( CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest() ); + runner.run( controller ); + + // Print test in a compiler compatible format. + CPPUNIT_NS::CompilerOutputter outputter( &result, CPPUNIT_NS::stdCOut() ); + outputter.write(); + + // Test xml output + std::ofstream xmlFile("Asn1TestResults.xml"); + CPPUNIT_NS::XmlOutputter xmlOutput(&result,xmlFile); + xmlOutput.write(); + return result.wasSuccessful() ? 0 : 1; + +} diff --git a/include/ADT/Adt.h b/include/ADT/Adt.h new file mode 100644 index 0000000..2a81ee7 --- /dev/null +++ b/include/ADT/Adt.h @@ -0,0 +1,70 @@ +#ifndef ADT_H__ +#define ADT_H__ +/* vim: et sw=2 ts=2 + */ +#include "aeb/dlilist.h" +#include "aeb/dlilist_node.h" +#include +namespace ADT { + +/** + * \brief Abstract data type base class. + */ +class Adt : public ::aeb::dlilist_node { + public: + enum AdtClass { + AdtNoClass = 0 +#define ADT(Cls,Parent) ,Cls##Class +#ifdef WITH_ADT_ASN1 +# define ASN1TYPE(Cls,Parent) ,Cls##Class +#endif +#ifdef WITH_ADT_GDMO +# define GDMO_DECL(Cls,Parent) ,Cls##Class +#endif +#include "ADT/Adt.h.inc" +#ifdef WITH_ADT_GDMO +#include "ADT/gdmo/Gdmo.h.inc" +#endif +#undef ADT + }; + /// Constructors + Adt(AdtClass c = AdtNoClass) : m_Class(c) {}; + + Adt(const std::string &_s,AdtClass c) : m_Class(c),m_Name(_s) {}; + virtual ~Adt() {}; + + ///Setter / Getter for Name + std::string getName() { return m_Name; } + + ///Setter / Getter for Name + std::string getName() const { return m_Name; } + + + /// Getter for Class + AdtClass getClass() const {return m_Class; }; + + protected: + AdtClass m_Class; + /// All Abstract Data Types should have a name. If not, it's an anonymous type and + /// size of m_Name is 0 + std::string m_Name; + private: +}; + +#include "ADT/AdtModule.h" +#include "ADT/AdtPrimitiveType.h" +#include "ADT/AdtTypeRefType.h" +#include "ADT/AdtField.h" +#include "ADT/AdtContainer.h" +#include "ADT/AdtChoice.h" +#include "ADT/AdtStruct.h" + +#ifdef WITH_ADT_ASN1 +#endif +#ifdef WITH_ADT_GDMO +#include "ADT/gdmo/Gdmo.h" +#endif +} + + +#endif diff --git a/include/ADT/Adt.h.inc b/include/ADT/Adt.h.inc new file mode 100644 index 0000000..a7a6a75 --- /dev/null +++ b/include/ADT/Adt.h.inc @@ -0,0 +1,105 @@ +/** + * SDL Abstract Data Types + */ +#ifndef ADT +# define ADT(Cls,Parent) +#endif +ADT(Container,Adt) +ADT(ChoiceType,Container) +ADT(StructType,Container) +ADT(BagType,Container) +ADT(PrimitiveType,Adt) +ADT(BooleanType,PrimitiveType) +ADT(IntegerType,PrimitiveType) +ADT(StringType,PrimitiveType) +ADT(TypeRefType,Adt) +ADT(ValueType,Adt) +ADT(Module,Adt) +ADT(Field,Adt) + + +/** + * ASN1 Abstract Data Types + */ +#ifndef ASN1TYPE +# define ASN1TYPE(Cls,Parent) +#endif + + +ASN1TYPE(REFERENCE,Adt) +ASN1TYPE(EXPORTVAR,Adt) +ASN1TYPE(UNIVERSAL,Adt) +ASN1TYPE(BITVECTOR,Adt) +ASN1TYPE(EXTENSIBLE,Adt) +ASN1TYPE(COMPONENTS_OF,Adt) +ASN1TYPE(VALUESET,Adt) +ASN1TYPE(CLASSDEF,Adt) +ASN1TYPE(INSTANCE,Adt) + +/** + * Class Field type + */ +ASN1TYPE(ClassFieldTF,Adt) /* Type Field */ +ASN1TYPE(ClassFieldFTVF,Adt) /* Fixed Type Value Field */ +ASN1TYPE(ClassFieldVTVF,Adt) /* Variable Type Value Field */ +ASN1TYPE(ClassFieldFTVSF,Adt) /* Fixed Type Value Set Field */ +ASN1TYPE(ClassFieldVTVSF,Adt) /* Variable Type Value Set Field*/ +ASN1TYPE(ClassFieldOF,Adt) /* Object Field */ +ASN1TYPE(ClassFieldOSF,Adt) /* Object Set Field */ +/* Constructed Types + */ +ASN1TYPE(Sequence,StructType) +ASN1TYPE(Choice,ChoiceType) +ASN1TYPE(Set,Adt) + +ASN1TYPE(SequenceOf,Adt) /* Should be a vector or an array */ +ASN1TYPE(SetOf,Bag) /* Comes from SDL specification */ +ASN1TYPE(Selection,Adt) /* */ + +/* Basic Types + */ +ASN1TYPE(Asn1Primitive,PrimitiveType) +ASN1TYPE(Any,Asn1Primitive) +ASN1TYPE(Boolean,Asn1Primitive) +ASN1TYPE(Integer,Asn1Primitive) +ASN1TYPE(BitString,Asn1Primitive) +ASN1TYPE(OctetString,Asn1Primitive) +ASN1TYPE(Null,Asn1Primitive) +ASN1TYPE(ObjectIdentifier,Asn1Primitive) +ASN1TYPE(ObjectDescriptor,Asn1Primitive) +ASN1TYPE(Real,Asn1Primitive) +ASN1TYPE(Enumerated,Asn1Primitive) +ASN1TYPE(RelativeOid,Asn1Primitive) +ASN1TYPE(External,Asn1Primitive) +ASN1TYPE(EmbeddedPdv,Asn1Primitive) +ASN1TYPE(CharString,Asn1Primitive) +ASN1TYPE(UTCTime,Asn1Primitive) +ASN1TYPE(GeneralizedTime,Asn1Primitive) + +ASN1TYPE(ObjectClass,Asn1Primitive) +ASN1TYPE(Object,Asn1Primitive) + +/* String Types + */ +ASN1TYPE(String,Asn1Primitive) +ASN1TYPE(IA5String,String) +ASN1TYPE(PrintableString,String) +ASN1TYPE(VisibleString,String) +ASN1TYPE(ISO646String,String) /* aka VisibleString */ +ASN1TYPE(NumericString,String) +ASN1TYPE(UniversalString,String) +ASN1TYPE(BMPString,String) +ASN1TYPE(UTF8String,String) +ASN1TYPE(GeneralString,String) +ASN1TYPE(GraphicString,String) +ASN1TYPE(TeletexString,String) +ASN1TYPE(T61String,String) +ASN1TYPE(VideotexString,String) +ASN1TYPE(ObjectDescriptor,String) + +/** + * XSD Abstract Data Types + */ +#ifndef XSDTYPE +# define XSDTYPE(Cls,Parent) +#endif diff --git a/include/ADT/AdtChoice.h b/include/ADT/AdtChoice.h new file mode 100644 index 0000000..4a14901 --- /dev/null +++ b/include/ADT/AdtChoice.h @@ -0,0 +1,37 @@ +#ifndef ADTCHOICE_H__ +#define ADTCHOICE_H__ +/* vim: et sw=2 ts=2 + */ + + +class ChoiceType : public Container { + public: + + virtual ~ChoiceType() {}; + + static ChoiceType *Create(const std::string &_s) { + return new ChoiceType(_s); + } + /// + bool addField(Field *d) { + if (d) { + if (lookup(d->getName())) { + // Already in structure don't add twice the same name + return false; + } else { + m_Fields.push_back(d); + return true; + } + } else + return false; + }; + + protected: + ChoiceType(const std::string &_s,AdtClass c=ChoiceTypeClass ) : Container(_s,c) {} ; + + protected: + + private: +}; + +#endif diff --git a/include/ADT/AdtContainer.h b/include/ADT/AdtContainer.h new file mode 100644 index 0000000..bc9621d --- /dev/null +++ b/include/ADT/AdtContainer.h @@ -0,0 +1,80 @@ +#ifndef ADTCONTAINER_H__ +#define ADTCONTAINER_H__ +/* vim: et sw=2 ts=2 + */ + + +class Container: public Adt { + public: + // Constains a list of Instruction .... + typedef aeb::dlilist FieldList; + + // Instruction Iterator + typedef FieldList::iterator iterator; + typedef FieldList::const_iterator const_iterator; + + protected: + explicit Container(const std::string &_s = "",AdtClass c=ContainerClass) : Adt(_s,c),m_Fields() {} ; + + struct searchByName { + searchByName(const std::string &n) : m_Name(n) {}; + int operator ()(Adt &l) { + return !m_Name.compare(l.getName()); + }; + std::string m_Name; + }; + public: + static Container *Create(const std::string &_s) { + return new Container(_s); + } + + virtual ~Container() {}; + + /// + bool addField(Field *d) { + if (d) { + if (lookup(d->getName())) { + // Already in structure don't add twice the same name + return false; + } else { + m_Fields.push_back(d); + return true; + } + } else + return false; + }; + + /// + bool add(Adt *d) { + if (d) { + if (lookup(d->getName())) { + // Already in structure don't add twice the same name + return false; + } else { + m_Fields.push_back(d); + return true; + } + } else + return false; + }; + + + /// Iterators + iterator begin() { return m_Fields.begin(); } + iterator end() { return m_Fields.end(); } + + size_t size() const { return m_Fields.size(); } + /// lookup field in current structure + Adt *lookup(const std::string &_s) { + iterator it = std::find_if(begin(),end(),searchByName(_s)); + if (it != end()) + return &*it; + return NULL; + + }; + protected: + FieldList m_Fields; + private: +}; + +#endif diff --git a/include/ADT/AdtField.h b/include/ADT/AdtField.h new file mode 100644 index 0000000..c9a7088 --- /dev/null +++ b/include/ADT/AdtField.h @@ -0,0 +1,31 @@ +#ifndef ADTFIELD_H__ +#define ADTFIELD_H__ +/* vim: et sw=2 ts=2 + */ + +/** + * \brief A field is contained in a Structure or a Bag. It references a Primary or contructed type. + * -- When added to a structure or Bag, the function getParent shoud return the Parent that owns the + * field. + */ +class Field : public Adt { + public: + virtual ~Field() {}; + protected: + Field(const std::string &_s ="", Adt *_typeref = NULL) : Adt(_s,FieldClass) , m_TypeRef(_typeref) {} ; + + public: + static Field *Create(const std::string &_s,Adt *_typeref = NULL) { + return new Field(_s,_typeref); + } + + Adt *getParent() { return NULL;}; + // Getter + Adt *getTypeRef() const { return m_TypeRef; }; + protected: + /// The field is contained in structs, Bags, Maybe I should use reference counting if to names point to the same type !!!! + Adt *m_TypeRef; + private: +}; + +#endif diff --git a/include/ADT/AdtModule.h b/include/ADT/AdtModule.h new file mode 100644 index 0000000..63eae6d --- /dev/null +++ b/include/ADT/AdtModule.h @@ -0,0 +1,59 @@ +#ifndef ADTMODULE_H__ +#define ADTMODULE_H__ + +// vim: et sw=2 ts=2 +/** + * + * \brief This class is a container. It keeps track of all Abstract datatypes defined + * in a module. Provides lockup functions , iterators and so one. + * + * As it contains a list of definition, this module shall inherit from something like a list + * container + */ +class Module : public Adt { + public: + // Constains a list of Instruction .... + typedef aeb::dlilist AdtList; + + // Instruction Iterator + typedef AdtList::iterator iterator; + typedef AdtList::const_iterator const_iterator; + + protected: + // Constructors + Module(Adt::AdtClass c,const std::string &name) : Adt(name,c) {}; + + struct searchByName { + searchByName(const std::string &n) : m_Name(n) {}; + int operator ()(Adt &l) { + return !m_Name.compare(l.getName()); + }; + std::string m_Name; + }; + public: + ~Module() {}; + static Module *Create(const std::string &_s) { return new Module(ModuleClass,_s); } + // Iterators + iterator begin() { return m_Types.begin(); } + iterator end() { return m_Types.end(); } + + size_t size() const { return m_Types.size(); } + /// Search for given type name in module + Adt *lookup(const std::string &_s) { + iterator it = std::find_if(begin(),end(),searchByName(_s)); + if (it != end()) + return &*it; + return NULL; + }; + + /// Insert new Abstract Data Type in Module. If Data Type already exists, return false and don't insert in + /// the list + bool insert(Adt *m) { if (m) { m_Types.push_back(m); return true;} else {return false;}}; + protected: + /// Types contained in module + AdtList m_Types; + private: + +}; + +#endif diff --git a/include/ADT/AdtPrimitiveType.h b/include/ADT/AdtPrimitiveType.h new file mode 100644 index 0000000..30b4762 --- /dev/null +++ b/include/ADT/AdtPrimitiveType.h @@ -0,0 +1,37 @@ +#ifndef ADTPRIMITIVETYPE_H__ +#define ADTPRIMITIVETYPE_H__ +/* vim: et sw=2 ts=2 + */ + +/** + * \brief Root class to handle primitive types like string,boolean,integer. + * All other types are constructed struct, vector, array bag + */ +class PrimitiveType : public Adt { + public: + PrimitiveType(const std::string &_s,AdtClass c=PrimitiveTypeClass) : Adt(_s,c) {} ; + virtual ~PrimitiveType() {}; + protected: + + private: +}; + + +/** + * + */ +#define PRIMITIVE(Cls) \ +class Cls : public PrimitiveType { \ + protected: \ + Cls (const std::string &_s,AdtClass c=Cls##Class) : PrimitiveType(_s,c) { } ; \ + public: \ + virtual ~Cls() {} ;\ + static Cls *Create(const std::string &_s) { return new Cls(_s); } \ + protected: \ +} + +PRIMITIVE(BooleanType); +PRIMITIVE(StringType); +PRIMITIVE(IntegerType); + +#endif diff --git a/include/ADT/AdtStruct.h b/include/ADT/AdtStruct.h new file mode 100644 index 0000000..cb8faf5 --- /dev/null +++ b/include/ADT/AdtStruct.h @@ -0,0 +1,37 @@ +#ifndef ADTSTRUCT_H__ +#define ADTSTRUCT_H__ +/* vim: et sw=2 ts=2 + */ + + +class StructType : public Container { + public: + + protected: + explicit StructType(const std::string &_s = "") : Container(_s,StructTypeClass) {} ; + + public: + static StructType *Create(const std::string &_s) { + return new StructType(_s); + } + + virtual ~StructType() {}; + + /// + bool addField(Field *d) { + if (d) { + if (lookup(d->getName())) { + // Already in structure don't add twice the same name + return false; + } else { + m_Fields.push_back(d); + return true; + } + } else + return false; + }; + protected: + private: +}; + +#endif diff --git a/include/ADT/AdtTypeRefType.h b/include/ADT/AdtTypeRefType.h new file mode 100644 index 0000000..3fcdb9f --- /dev/null +++ b/include/ADT/AdtTypeRefType.h @@ -0,0 +1,31 @@ +#ifndef ADTTYPEREF_H__ +#define ADTTYPEREF_H__ +/* vim: et sw=2 ts=2 + */ + +/** + * \brief A field is contained in a Structure or a Bag. It references a Primary or contructed type. + * -- When added to a structure or Bag, the function getParent shoud return the Parent that owns the + * field. + */ +class TypeRefType : public Adt { + public: + virtual ~TypeRefType() {}; + protected: + TypeRefType(const std::string &_s ="", Adt *_typeref = NULL) : Adt(_s,TypeRefTypeClass) , m_TypeRef(_typeref) {} ; + + public: + static TypeRefType *Create(const std::string &_s,Adt *_typeref = NULL) { + return new TypeRefType(_s,_typeref); + } + + Adt *getParent() { return NULL;}; + // Getter + Adt *getTypeRef() const { return m_TypeRef; }; + protected: + /// The field is contained in structs, Bags, Maybe I should use reference counting if to names point to the same type !!!! + Adt *m_TypeRef; + private: +}; + +#endif diff --git a/include/ADT/asn1/Asn1Boolean.h b/include/ADT/asn1/Asn1Boolean.h new file mode 100644 index 0000000..d764376 --- /dev/null +++ b/include/ADT/asn1/Asn1Boolean.h @@ -0,0 +1,14 @@ +#ifndef ASN1BOOLEAN_H +#define ASN1BOOLEAN_H + +class Asn1Boolean { + public: + // + Asn1Boolean() ; + // + Asn1Boolean(const Asn1Boolean &o) ; + // + ~Asn1Boolean() ; + protected: +}; +#endif /*ASN1BOOLEAN_H*/ diff --git a/include/ADT/asn1/Asn1Choice.h b/include/ADT/asn1/Asn1Choice.h new file mode 100644 index 0000000..7b92f37 --- /dev/null +++ b/include/ADT/asn1/Asn1Choice.h @@ -0,0 +1,17 @@ +#ifndef ASN1CHOICE_H +#define ASN1CHOICE_H + + +class Asn1Choice { + public: + // + Asn1Choice() ; + // + Asn1Choice(const Asn1Choice &o) ; + // + ~Asn1Choice() ; + protected: +}; + + +#endif /*ASN1CHOICE_H*/ diff --git a/include/ADT/asn1/Asn1Class.h b/include/ADT/asn1/Asn1Class.h new file mode 100644 index 0000000..295ba5c --- /dev/null +++ b/include/ADT/asn1/Asn1Class.h @@ -0,0 +1,22 @@ +#ifndef ASN1CLASS_H +#define ASN1CLASS_H + +/** + * class Asn1Class + * + * \brief + * \author + */ +class Asn1Class { + public: + // + Asn1Class() ; + // + Asn1Class(const Asn1Class &o) ; + // + ~Asn1Class() ; + protected: +}; + + +#endif /*ASN1CLASS_H*/ diff --git a/include/ADT/asn1/Asn1Constraint.h b/include/ADT/asn1/Asn1Constraint.h new file mode 100644 index 0000000..418e11a --- /dev/null +++ b/include/ADT/asn1/Asn1Constraint.h @@ -0,0 +1,22 @@ +#ifndef ASN1CONSTRAINT_H +#define ASN1CONSTRAINT_H + +/** + * class Asn1Constraint + * + * \brief + * \author + */ +class Asn1Constraint : public Asn1Decl { + public: + // + Asn1Constraint() ; + // + Asn1Constraint(const Asn1Constraint &o) ; + // + ~Asn1Constraint() ; + protected: +}; + + +#endif /*ASN1CONSTRAINT_H*/ diff --git a/include/ADT/asn1/Asn1Context.h b/include/ADT/asn1/Asn1Context.h new file mode 100644 index 0000000..1904c96 --- /dev/null +++ b/include/ADT/asn1/Asn1Context.h @@ -0,0 +1,26 @@ +#ifndef ASN1CONTEXT_H +#define ASN1CONTEXT_H + +class Asn1Decl; +/** + * class Asn1Context + * + * \brief + * \author + */ +class Asn1Context { + public: + // + Asn1Context() ; + // + Asn1Context(const Asn1Context &o) ; + // + ~Asn1Context() ; + protected: + Asn1Decl *m_First; + Asn1Decl *m_Last; +}; + + + +#endif /*ASN1CONTEXT_H*/ diff --git a/include/ADT/asn1/Asn1Decl.h b/include/ADT/asn1/Asn1Decl.h new file mode 100644 index 0000000..070a625 --- /dev/null +++ b/include/ADT/asn1/Asn1Decl.h @@ -0,0 +1,25 @@ +#ifndef ASN1DECL_H +#define ASN1DECL_H + + +/** + * class Asn1Decl + * + * \brief + * \author + */ +class Asn1Decl { + public: + // + Asn1Decl() ; + // + Asn1Decl(const Asn1Decl &o) ; + // + ~Asn1Decl() ; + protected: + Asn1Decl *m_Next; +}; + + + +#endif /*ASN1DECL_H*/ diff --git a/include/ADT/asn1/Asn1Field.h b/include/ADT/asn1/Asn1Field.h new file mode 100644 index 0000000..70b856b --- /dev/null +++ b/include/ADT/asn1/Asn1Field.h @@ -0,0 +1,22 @@ +#ifndef ASN1FIELD_H +#define ASN1FIELD_H + +/** + * class Asn1Field + * + * \brief + * \author + */ +class Asn1Field { + public: + // + Asn1Field() ; + // + Asn1Field(const Asn1Field &o) ; + // + ~Asn1Field() ; + protected: +}; + + +#endif /*ASN1FIELD_H*/ diff --git a/include/ADT/asn1/Asn1Integer.h b/include/ADT/asn1/Asn1Integer.h new file mode 100644 index 0000000..7ab6467 --- /dev/null +++ b/include/ADT/asn1/Asn1Integer.h @@ -0,0 +1,23 @@ +#ifndef ASN1INTEGER_H +#define ASN1INTEGER_H + + +/** + * class Asn1Intger + * + * \brief + * \author + */ +class Asn1Integer { + public: + // + Asn1Integer() ; + // + Asn1Integer(const Asn1Integer &o) ; + // + ~Asn1Integer() ; + protected: +}; + + +#endif /*ASN1INTEGER_H*/ diff --git a/include/ADT/asn1/Asn1Module.h b/include/ADT/asn1/Asn1Module.h new file mode 100644 index 0000000..ee9413d --- /dev/null +++ b/include/ADT/asn1/Asn1Module.h @@ -0,0 +1,23 @@ +#ifndef ASN1MODULE_H +#define ASN1MODULE_H + + +/** + * class Asn1Module + * + * \brief + * \author + */ +class Asn1Module { + public: + // + Asn1Module() ; + // + Asn1Module(const Asn1Module &o) ; + // + ~Asn1Module() ; + protected: +}; + + +#endif /*ASN1MODULE_H*/ diff --git a/include/ADT/asn1/Asn1Object.h b/include/ADT/asn1/Asn1Object.h new file mode 100644 index 0000000..4db0a5c --- /dev/null +++ b/include/ADT/asn1/Asn1Object.h @@ -0,0 +1,22 @@ +#ifndef ASN1OBJECT_H +#define ASN1OBJECT_H + +/** + * class Asn1Object + * + * \brief + * \author + */ +class Asn1Object { + public: + // + Asn1Object() ; + // + Asn1Object(const Asn1Object &o) ; + // + ~Asn1Object() ; + protected: +}; + + +#endif /*ASN1OBJECT_H*/ diff --git a/include/ADT/asn1/Asn1ObjectSet.h b/include/ADT/asn1/Asn1ObjectSet.h new file mode 100644 index 0000000..9626e40 --- /dev/null +++ b/include/ADT/asn1/Asn1ObjectSet.h @@ -0,0 +1,24 @@ +#ifndef ASN1OBJECTSET_H +#define ASN1OBJECTSET_H + + +/** + * class Asn1ObjectSet + * + * \brief + * \author + */ +class Asn1ObjectSet { + public: + // + Asn1ObjectSet() ; + // + Asn1ObjectSet(const Asn1ObjectSet &o) ; + // + ~Asn1ObjectSet() ; + protected: +}; + + + +#endif /*ASN1OBJECTSET_H*/ diff --git a/include/ADT/asn1/Asn1Oid.h b/include/ADT/asn1/Asn1Oid.h new file mode 100644 index 0000000..b533aeb --- /dev/null +++ b/include/ADT/asn1/Asn1Oid.h @@ -0,0 +1,23 @@ +#ifndef ASN1OID_H +#define ASN1OID_H + + +/** + * class Asn1ObjectIdentifier + * + * \brief + * \author + */ +class Asn1ObjectIdentifier : public Asn1Type { + public: + // + Asn1ObjectIdentifier() ; + // + Asn1ObjectIdentifier(const Asn1ObjectIdentifier &o) ; + // + ~Asn1ObjectIdentifier() ; + protected: +}; + + +#endif /*ASN1OID_H*/ diff --git a/include/ADT/asn1/Asn1Sequence.h b/include/ADT/asn1/Asn1Sequence.h new file mode 100644 index 0000000..9d8aa23 --- /dev/null +++ b/include/ADT/asn1/Asn1Sequence.h @@ -0,0 +1,23 @@ +#ifndef ASN1SEQUENCE_H +#define ASN1SEQUENCE_H + + +/** + * class Asn1Sequence + * + * \brief + * \author + */ +class Asn1Sequence { + public: + // + Asn1Sequence() ; + // + Asn1Sequence(const Asn1Sequence &o) ; + // + ~Asn1Sequence() ; + protected: +}; + + +#endif /*ASN1SEQUENCE_H*/ diff --git a/include/ADT/asn1/Asn1Set.h b/include/ADT/asn1/Asn1Set.h new file mode 100644 index 0000000..dc9162f --- /dev/null +++ b/include/ADT/asn1/Asn1Set.h @@ -0,0 +1,23 @@ +#ifndef ASN1SET_H +#define ASN1SET_H + +/** + * class Asn1Set + * + * \brief + * \author + */ +class Asn1Set { + public: + // + Asn1Set() ; + // + Asn1Set(const Asn1Set &o) ; + // + ~Asn1Set() ; + protected: +}; + + + +#endif /*ASN1SET_H*/ diff --git a/include/ADT/asn1/Asn1Type.h b/include/ADT/asn1/Asn1Type.h new file mode 100644 index 0000000..8ada6ad --- /dev/null +++ b/include/ADT/asn1/Asn1Type.h @@ -0,0 +1,24 @@ +#ifndef ASN1TYPE_H +#define ASN1TYPE_H + + +/** + * class Asn1Type + * + * \brief + * \author + */ +class Asn1Type { + public: + // + Asn1Type() ; + // + Asn1Type(const Asn1Type &o) ; + // + ~Asn1Type() ; + protected: +}; + + + +#endif /*ASN1TYPE_H*/ diff --git a/include/ADT/asn1/type.h.def b/include/ADT/asn1/type.h.def new file mode 100644 index 0000000..f99d882 --- /dev/null +++ b/include/ADT/asn1/type.h.def @@ -0,0 +1,86 @@ +#ifndef TYPE +# define TYPE(NAME,CLASS,MCLASS) +#endif +TYPE(REFERENCE,Asn1Typeref,Asn1Decl) +TYPE(EXPORTVAR,Asn1Type,Asn1Decl) +TYPE(UNIVERSAL) +TYPE(BITVECTOR) +TYPE(EXTENSIBLE) +TYPE(COMPONENTS_OF) +TYPE(VALUESET) +TYPE(CLASSDEF,Asn1Class,Asn1Type) +TYPE(INSTANCE) + +/** + * Class Field type + */ +#ifndef FIELD _TYPE +# define FIELD_TYPE(ID,CLASS,MCLASS) TYPE(ID,CLASS,MCLASS) +#endif +FIELD_TYPE(CLASSFIELD_TF,Asn1Field,Asn1Field) /* Type Field */ +FIELD_TYPE(CLASSFIELD_FTVF,Asn1Field,Asn1Field) /* Fixed Type Value Field */ +FIELD_TYPE(CLASSFIELD_VTVF,Asn1Field,Asn1Field) /* Variable Type Value Field */ +FIELD_TYPE(CLASSFIELD_FTVSF,Asn1Field,Asn1Field) /* Fixed Type Value Set Field */ +FIELD_TYPE(CLASSFIELD_VTVSF,Asn1Field,Asn1Field) /* Variable Type Value Set Field*/ +FIELD_TYPE(CLASSFIELD_OF,Asn1Field,Asn1Field) /* Object Field */ +FIELD_TYPE(CLASSFIELD_OSF,Asn1Field,Asn1Field) /* Object Set Field */ + +/* + * Constructed Types + */ +TYPE(SEQUENCE,Asn1Sequence,Asn1Decl) /* 17 */ +TYPE(CHOICE,Asn1Choice,Asn1Decl) +TYPE(SET,Asn1Choice,Asn1Decl) +TYPE(SEQUENCE_OF) +TYPE(SET_OF) +TYPE(SELECTION) + +/* + * Basic Types + */ +TYPE(ANY,Asn1Type,Asn1Type) +TYPE(BOOLEAN,Asn1Boolean,Asn1Type) +TYPE(INTEGER,Asn1Integer,Asn1Type) +TYPE(BIT_STRING) +TYPE(OCTET_STRING) +TYPE(NULL) +TYPE(OBJECT_IDENTIFIER,Asn1Oid,Asn1Decl) +TYPE(OBJECT_DESCRIPTOR) +TYPE(REAL,Asn1Type,Asn1Type) +TYPE(ENUMERATED,Ans1Integer,Asn1Integer) +TYPE(RELATIVE_OID,Asn1Oid,Asn1Decl) +TYPE(EXTERNAL) +TYPE(EMBEDDED_PDV) +TYPE(CHARACTER_STRING,Asn1String,Asn1Decl) +/* + * Time Types + */ +TYPE(Time,Asn1Time,Asn1Decl) +TYPE(UTCTime,Asn1UTCTime,Asn1Time) +TYPE(GeneralizedTime,Asn1GTime,Asn1Time) + +/* + * String Types + */ +#ifndef STRING_TYPE +# define STRING_TYPE(ID,CLASS,MCLASS) TYPE(ID,CLASS,MCLASS) +#endif +STRING_TYPE(STRING,Asn1String,Asn1String) +STRING_TYPE(STRING_IA5String,Asn1String,Asn1String) +STRING_TYPE(STRING_PrintableString,Asn1String,Asn1String) +STRING_TYPE(STRING_VisibleString,Asn1String,Asn1String) +STRING_TYPE(STRING_ISO646String,Asn1String,Asn1String) /* aka VisibleString */ +STRING_TYPE(STRING_NumericString,Asn1String,Asn1String) +STRING_TYPE(STRING_UniversalString,Asn1String,Asn1String) +STRING_TYPE(STRING_BMPString,Asn1String,Asn1String) +STRING_TYPE(STRING_UTF8String ,Asn1String,Asn1String) +STRING_TYPE(STRING_GeneralString,Asn1String,Asn1String) +STRING_TYPE(STRING_GraphicString,Asn1String,Asn1String) +STRING_TYPE(STRING_TeletexString,Asn1String,Asn1String) +STRING_TYPE(STRING_T61String,Asn1String,Asn1String) +STRING_TYPE(STRING_VideotexString,Asn1String,Asn1String) +STRING_TYPE(STRING_ObjectDescriptor,Asn1String,Asn1String) + +TYPE(TYPE_MAX) + +#undef TYPE diff --git a/include/ADT/gdmo/Gdmo.h b/include/ADT/gdmo/Gdmo.h new file mode 100644 index 0000000..2924610 --- /dev/null +++ b/include/ADT/gdmo/Gdmo.h @@ -0,0 +1,400 @@ +#ifndef GDMO_H +#define GDMO_H + +namespace GDMO +{ + + /** + * Base class + */ + class gdmo : public Adt + { + public: + gdmo(Adt::AdtClass c) + : Adt(c) + { + } + gdmo(Adt::AdtClass c,const std::string &n) + : Adt(n,c) + { + } + protected: + }; + + /** + * + */ + class decl : public gdmo + { + protected: + decl(Adt::AdtClass c,const std::string &n="") + : gdmo(c,n) + { + } + + public: + + static decl *Create(const std::string &name) + { + return new decl(Adt::declClass,name); + } + + const std::string get_name() const + { + std::string s = getName(); + return s; + } + protected: + }; + + + /** + * All labels in gdmo document + */ + class oid_item : public decl + { + oid_item(Adt::AdtClass c ,const std::string &s,const long v = -1) + : decl(c,s) ,m_value(v) + { } + public: + static oid_item *Create(const std::string &name = "",const long v = -1) + { + return new oid_item(Adt::oid_itemClass,name,v); + } + + /** + * + */ + const std::string get_name() + { + std::string s = getName(); + if ( s.size() < 1 ) + { + std::ostringstream ss; + ss< -1) + { + std::ostringstream ss; + ss<getName()) , m_container(cont) ,m_decl(NULL) + { + } + construct(Adt::AdtClass c,decl *cont) + : gdmo(c) , m_container(NULL) ,m_decl(cont) + { + } + + size_t size() const + { + if (m_container) + return m_container->size(); + return 0; + }; + iterator begin() + { + return m_container->begin(); + } + iterator end() + { + return m_container->end(); + } + decl *get_decl() const + { + return m_decl; + } + protected: + Container *m_container; + decl *m_decl; + }; + +#define GDMO_DECL(cls,parent) +#define GDMO_PROPLIST_DECL(cls,parent) \ + class cls : public parent \ + { \ + protected: \ + cls(Adt::AdtClass c,decl *_con) \ + : parent(c,_con) \ + { \ + } \ + public: \ + static cls *Create(decl *l) \ + { \ + return new cls(Adt::cls##Class,l); \ + } \ + }; + +#define GDMO_CONSTRUCT_DECL(cls,parent) \ + class cls : public parent \ + { \ + protected: \ + cls(Adt::AdtClass c,Container *_con) \ + : parent(c,_con) \ + { \ + } \ + cls(Adt::AdtClass c,decl *_con) \ + : parent(c,_con) \ + { \ + } \ + public: \ + static cls *Create(Container *l) \ + { \ + return new cls(Adt::cls##Class,l); \ + } \ + static cls *Create(decl *l) \ + { \ + return new cls(Adt::cls##Class,l); \ + } \ + }; \ + +#define GDMO_TPLT_DECL(x,y) + +#include "ADT/gdmo/Gdmo.h.inc" + +#include "ADT/gdmo/GdmoTemplates.h" + + class module : public Module + { + protected: + module(const std::string &s) + : Module(Adt::moduleClass,s) + { + } + public: + static module *Create(const std::string &s) + { + return new module(s); + } + }; + + + + /** + * All labels in gdmo document + */ + class pkg_attribute : public decl + { + +#define PKG_CONST(etype) \ + etype(vf,PROPL_REPLACE_DEFAULT,replace_default) \ + etype(vs,PROPL_DEFAULT,default) \ + etype(vs,PROPL_INITIAL,initial) \ + etype(vs,PROPL_PERMITTED,permitted) \ + etype(vs,PROPL_REQUIRED,required) \ + etype(vs,PROPL_GET_REPLACE,get_replace) \ + etype(vs,PROPL_ADD_REMOVE,add_remove) \ + etype(vs,PROPL_SET_BY_CREATED,set_by_created) \ + etype(vs,PROPL_NO_MODIFY,no_modify) \ + +#define vs , +#define vf +#define etype(COMMA,e,T) COMMA e + public: + enum eConstruct {PKG_CONST(etype) ,PROPL_END}; +#undef etype +#undef vs + protected: + property *m_properties[PROPL_END]; +/** + * Add setter and getters + */ + +#define vs +#define etype(v,e,T) \ + property_## T * get_##T() const { return dynamic_cast< property_##T*>(m_properties[e]);} \ + void set_##T(property_##T *c) { m_properties[ e ] = c;} \ + + public: + PKG_CONST(etype) +#undef etype +#undef vs +#undef vf +#undef PKG_CONST + protected: + pkg_attribute(Adt::AdtClass c ,const std::string &s,const std::string &n) + : decl(c,n) ,m_scope(s) + { + memset(m_properties,0x00,sizeof(property *)*PROPL_END); + } + public: + static pkg_attribute *Create(const std::string &name) + { + return new pkg_attribute(Adt::pkg_attributeClass,"",name); + } + static pkg_attribute *Create(const std::string &scope,const std::string &name) + { + return new pkg_attribute(Adt::pkg_attributeClass,scope,name); + } + + /** + * + */ + void set_scope(const std::string &s) + { + m_scope = s; + } + + std::string get_scope() const + { + return m_scope; + } + protected: + std::string m_scope; + }; + + + +} +#endif /*GDMO_H*/ diff --git a/include/ADT/gdmo/Gdmo.h.inc b/include/ADT/gdmo/Gdmo.h.inc new file mode 100644 index 0000000..d61707e --- /dev/null +++ b/include/ADT/gdmo/Gdmo.h.inc @@ -0,0 +1,108 @@ +#ifndef GDMO_DECL +# define GDMO_DECL(cls,parent) +#endif + +GDMO_DECL(module,Module) +GDMO_DECL(decl,gdmo) +//GDMO_DECL(container,gdmo) +/** + * typereferences + */ +GDMO_DECL(label,decl) +GDMO_DECL(pkg_attribute,decl) +GDMO_DECL(property,decl) +GDMO_DECL(oid_item,decl) +GDMO_DECL(reference,decl) +GDMO_DECL(typeref,reference) +GDMO_DECL(valueref,reference) + +/** + * templates + */ +#ifndef GDMO_TPLT_DECL +# define GDMO_TPLT_DECL(cls,parent) GDMO_DECL(cls,parent) +#endif +GDMO_DECL(templates,decl) + +GDMO_TPLT_DECL(mo_tplt,templates) +GDMO_TPLT_DECL(package_tplt,templates) +GDMO_TPLT_DECL(name_binding_tplt,templates) +GDMO_TPLT_DECL(attribute_tplt,templates) +GDMO_TPLT_DECL(attribute_group_tplt,templates) +GDMO_TPLT_DECL(behaviour_tplt,templates) +GDMO_TPLT_DECL(action_tplt,templates) +GDMO_TPLT_DECL(parameter_tplt,templates) +GDMO_TPLT_DECL(notification_tplt,templates) + +#ifndef GDMO_CONSTRUCT_DECL +# define GDMO_CONSTRUCT_DECL(cls,parent) GDMO_DECL(cls,parent) +#endif + +GDMO_CONSTRUCT_DECL(mo_derived_from,construct) +GDMO_CONSTRUCT_DECL(mo_characterized_by,construct) +GDMO_CONSTRUCT_DECL(mo_cond_packages,construct) +GDMO_CONSTRUCT_DECL(mo_registered,construct) + +GDMO_CONSTRUCT_DECL(pkg_behaviour,construct) +GDMO_CONSTRUCT_DECL(pkg_attributes,construct) +GDMO_CONSTRUCT_DECL(pkg_attribute_group,construct) +GDMO_CONSTRUCT_DECL(pkg_actions,construct) +GDMO_CONSTRUCT_DECL(pkg_notifications,construct) +GDMO_CONSTRUCT_DECL(pkg_registered,construct) + + +GDMO_CONSTRUCT_DECL(attr_syntax,construct) +GDMO_CONSTRUCT_DECL(attr_match_for,construct) +GDMO_CONSTRUCT_DECL(attr_behaviour,construct) +GDMO_CONSTRUCT_DECL(attr_parameters,construct) +GDMO_CONSTRUCT_DECL(attr_registered,construct) + +GDMO_CONSTRUCT_DECL(parameter_context,construct) +GDMO_CONSTRUCT_DECL(parameter_syntax,construct) +GDMO_CONSTRUCT_DECL(parameter_attribute,construct) +GDMO_CONSTRUCT_DECL(parameter_behaviour,construct) +GDMO_CONSTRUCT_DECL(parameter_registered,construct) + +GDMO_CONSTRUCT_DECL(name_binding_subordinate,construct) +GDMO_CONSTRUCT_DECL(name_binding_named_by_superior,construct) +GDMO_CONSTRUCT_DECL(name_binding_with_attribute,construct) +GDMO_CONSTRUCT_DECL(name_binding_behaviour,construct) +GDMO_CONSTRUCT_DECL(name_binding_create,construct) +GDMO_CONSTRUCT_DECL(name_binding_delete,construct) +GDMO_CONSTRUCT_DECL(name_binding_registered,construct) + +GDMO_CONSTRUCT_DECL(action_behaviour,construct) +GDMO_CONSTRUCT_DECL(action_mode,construct) +GDMO_CONSTRUCT_DECL(action_parameters,construct) +GDMO_CONSTRUCT_DECL(action_with_information,construct) +GDMO_CONSTRUCT_DECL(action_with_reply,construct) +GDMO_CONSTRUCT_DECL(action_registered,construct) + +GDMO_CONSTRUCT_DECL(notification_mode,construct) +GDMO_CONSTRUCT_DECL(notification_behaviour,construct) +GDMO_CONSTRUCT_DECL(notification_parameters,construct) +GDMO_CONSTRUCT_DECL(notification_with_information,construct) +GDMO_CONSTRUCT_DECL(notification_with_reply,construct) +GDMO_CONSTRUCT_DECL(notification_registered,construct) + +GDMO_CONSTRUCT_DECL(attribute_group_group_elements,construct) + +GDMO_CONSTRUCT_DECL(behaviour_defined_as,construct) + +#ifndef GDMO_PROPLIST_DECL +# define GDMO_PROPLIST_DECL(cls,parent) GDMO_DECL(cls,parent) +#endif +GDMO_PROPLIST_DECL(property_replace_default,property) +GDMO_PROPLIST_DECL(property_default,property) +GDMO_PROPLIST_DECL(property_initial,property) +GDMO_PROPLIST_DECL(property_permitted,property) +GDMO_PROPLIST_DECL(property_required,property) +GDMO_PROPLIST_DECL(property_get_replace,property) +GDMO_PROPLIST_DECL(property_add_remove,property) +GDMO_PROPLIST_DECL(property_set_by_created,property) +GDMO_PROPLIST_DECL(property_no_modify,property) + +#undef GDMO_DECL +#undef GDMO_TPLT_DECL +#undef GDMO_CONSTRUCT_DECL +#undef GDMO_PROPLIST_DECL diff --git a/include/ADT/gdmo/GdmoTemplates.h b/include/ADT/gdmo/GdmoTemplates.h new file mode 100644 index 0000000..749460c --- /dev/null +++ b/include/ADT/gdmo/GdmoTemplates.h @@ -0,0 +1,450 @@ + + +/** + * mo_tplt + */ +class mo_tplt : public templates +{ + protected: +#define MO_CONST(etype) \ + etype(vf,MO_DERIRVED_FROM,derived_from) \ + etype(vs,MO_CHARACTERIZED_BY,characterized_by) \ + etype(vs,MO_COND_PACKAGES,cond_packages) \ + etype(vs,MO_REGISTERED,registered) \ + +#define vs , +#define vf +#define etype(COMMA,e,T) COMMA e + public: + enum eConstruct {MO_CONST(etype) ,MO_END}; +#undef etype +#undef vs +#undef vf + protected: + construct *m_constructs[MO_END]; +/** + * Add setter and getters + */ + +#define vs +#define vf +#define etype(v,e,T) \ + mo_## T * get_##T() const { return dynamic_cast< mo_##T*>(m_constructs[e]);} \ + void set_##T(mo_##T *c) { m_constructs[ e ] = c;} \ + + public: + MO_CONST(etype) +#undef etype +#undef vs +#undef vf + protected: + mo_tplt(Adt::AdtClass c,const label &l) + : templates(c,l) + { + memset(m_constructs,0x00,sizeof( construct *) * MO_END); + } + public: + static mo_tplt *Create(const label &l) + { + return new mo_tplt(Adt::mo_tpltClass,l); + } +}; + +/** + * package_tplt + */ +class package_tplt : public templates +{ +#define PKG_CONST(etype) \ + etype(vf,PKG_BEHAVIOUR,behaviour) \ + etype(vs,PKG_ATTRIBUTES,attributes) \ + etype(vs,PKG_ATTR_GROUP,attribute_group) \ + etype(vs,PKG_ACTIONS,actions) \ + etype(vs,PKG_NOTIFICATIONS,notifications) \ + etype(vs,PKG_REGISTERED,registered) + +#define vs , +#define vf +#define etype(COMMA,e,T) COMMA e + public: + enum eConstruct {PKG_CONST(etype) ,PKG_END}; +#undef etype +#undef vs +#undef vf + protected: + construct *m_constructs[PKG_END]; +/** + * Add setter and getters + */ + +#define vs +#define vf +#define etype(v,e,T) \ + pkg_## T * get_##T() const { return dynamic_cast< pkg_##T*>(m_constructs[e]);} \ + void set_##T(pkg_##T *c) { m_constructs[ e ] = c;} \ + + public: + PKG_CONST(etype) +#undef etype +#undef vs +#undef vf +#undef PKG_CONST + protected: + package_tplt(Adt::AdtClass c,const label &l) + : templates(c,l) + { + memset(m_constructs,0x00,sizeof( construct *) * PKG_END); + } + public: + static package_tplt *Create(const label &l) + { + return new package_tplt(Adt::package_tpltClass,l); + } +}; + +/** + * name_binding_tplt + */ +class name_binding_tplt : public templates +{ +#define NBIND_CONST(etype) \ + etype(vf,NBIND_SUBORDINATE,subordinate) \ + etype(vs,NBIND_NAMED_BY_SUPERIOR,named_by_superior) \ + etype(vs,NBIND_WITH_ATTRIBUTE,with_attribute) \ + etype(vs,NBIND_BEHAVIOUR,behaviour) \ + etype(vs,NBIND_CREATE,create) \ + etype(vs,NBIND_DELETE,delete) \ + etype(vs,NBIND_REGISTERED,registered) + +#define vs , +#define vf +#define etype(COMMA,e,T) COMMA e + public: + enum eConstruct {NBIND_CONST(etype) ,NBIND_END}; +#undef etype +#undef vs +#undef vf + protected: + construct *m_constructs[NBIND_END]; +/** + * Add setter and getters + */ + +#define vs +#define vf +#define etype(v,e,T) \ + name_binding_## T * get_##T() const { return dynamic_cast< name_binding_##T*>(m_constructs[e]);} \ + void set_##T(name_binding_##T *c) { m_constructs[ e ] = c;} \ + + public: + NBIND_CONST(etype) +#undef etype +#undef vs +#undef vf + protected: + name_binding_tplt(Adt::AdtClass c,const label &l) + : templates(c,l) + { + memset(m_constructs,0x00,sizeof( construct *) * NBIND_END); + } + public: + static name_binding_tplt *Create(const label &l) + { + return new name_binding_tplt(Adt::name_binding_tpltClass,l); + } +}; + +/** + * attributes_tplt + */ +class attribute_tplt : public templates +{ +#define ATTR_CONST(etype) \ + etype(vf,ATTR_SYNTAX,syntax) \ + etype(vs,ATTR_MATCH_FOR,match_for) \ + etype(vs,ATTR_BEHAVIOUR,behaviour) \ + etype(vs,ATTR_PARAMETERS,parameters) \ + etype(vs,ATTR_REGISTERED,registered) + +#define vs , +#define vf +#define etype(COMMA,e,T) COMMA e + public: + enum eConstruct {ATTR_CONST(etype) ,ATTR_END}; +#undef etype +#undef vs +#undef vf + protected: + construct *m_constructs[ATTR_END]; +/** + * Add setter and getters + */ + +#define vs +#define vf +#define etype(v,e,T) \ + attr_## T * get_##T() const { return dynamic_cast< attr_##T*>(m_constructs[e]);} \ + void set_##T(attr_##T *c) { m_constructs[ e ] = c;} \ + + public: + ATTR_CONST(etype) +#undef etype +#undef vs +#undef vf + protected: + attribute_tplt(Adt::AdtClass c,const label &l) + : templates(c,l) + { + memset(m_constructs,0x00,sizeof( construct *) * ATTR_END); + } + public: + static attribute_tplt *Create(const label &l) + { + return new attribute_tplt(Adt::attribute_tpltClass,l); + } +}; + +/** + * attribute_group_tplt + */ +class attribute_group_tplt : public templates +{ +#define ATTRG_CONST(etype) \ + etype(vf,ATTRG_GROUP_ELEMENTS,group_elements) + +#define vs , +#define vf +#define etype(COMMA,e,T) COMMA e + public: + enum eConstruct {ATTRG_CONST(etype) ,ATTRG_END}; +#undef etype +#undef vs +#undef vf + protected: + construct *m_constructs[ATTRG_END]; +/** + * Add setter and getters + */ + +#define vs +#define vf +#define etype(v,e,T) \ + attribute_group_## T * get_##T() const { return dynamic_cast(m_constructs[e]);} \ + void set_##T(attribute_group_##T *c) { m_constructs[ e ] = c;} \ + + public: + ATTRG_CONST(etype) +#undef etype +#undef vs + protected: + attribute_group_tplt(Adt::AdtClass c,const label &l) + : templates(c,l) + { + memset(m_constructs,0x00,sizeof( construct *) * ATTRG_END); + } + public: + static attribute_group_tplt *Create(const label &l) + { + return new attribute_group_tplt(Adt::attribute_group_tpltClass,l); + } +}; + +/** + * behaviour_tplt + */ +class behaviour_tplt : public templates +{ +#define BEH_CONST(etype) \ + etype(vf,BEH_DEFINED_AS,defined_as) + +#define vs , +#define vf +#define etype(COMMA,e,T) COMMA e + public: + enum eConstruct {BEH_CONST(etype) ,BEH_END}; +#undef etype +#undef vs +#undef vf + protected: + construct *m_constructs[BEH_END]; +/** + * Add setter and getters + */ + +#define vs +#define vf +#define etype(v,e,T) \ + behaviour_## T * get_##T() const { return dynamic_cast< behaviour_##T*>(m_constructs[e]);} \ + void set_##T(behaviour_##T *c) { m_constructs[ e ] = c;} \ + + public: + BEH_CONST(etype) +#undef etype +#undef vs +#undef vf + protected: + behaviour_tplt(Adt::AdtClass c,const label &l) + : templates(c,l) + { + memset(m_constructs,0x00,sizeof( construct *) * BEH_END); + } + + public: + static behaviour_tplt *Create(const label &l) + { + return new behaviour_tplt(Adt::behaviour_tpltClass,l); + } +}; + +/** + * action_tplt + */ +class action_tplt : public templates +{ +#define ACTION_CONST(etype) \ + etype(vf,ACTION_BEHAVIOUR,behaviour) \ + etype(vs,ACTION_MODE,mode) \ + etype(vs,ACTION_PARAMETERS,parameters) \ + etype(vs,ACTION_WITH_INFORMATION,with_information) \ + etype(vs,ACTION_WITH_REPLY,with_reply) \ + etype(vs,ACTION_REGISTERED,registered) + +#define vs , +#define vf +#define etype(COMMA,e,T) COMMA e + public: + enum eConstruct {ACTION_CONST(etype) ,ACTION_END}; +#undef etype +#undef vs +#undef vf + protected: + construct *m_constructs[ACTION_END]; +/** + * Add setter and getters + */ + +#define vs +#define vf +#define etype(v,e,T) \ + action_## T * get_##T() const { return dynamic_cast< action_##T*>(m_constructs[e]);} \ + void set_##T(action_##T *c) { m_constructs[ e ] = c;} \ + + public: + ACTION_CONST(etype) +#undef etype +#undef vs +#undef vf + protected: + action_tplt(Adt::AdtClass c,const label &l) + : templates(c,l) + { + memset(m_constructs,0x00,sizeof( construct *) * ACTION_END); + } + public: + static action_tplt *Create(const label &l) + { + return new action_tplt(Adt::action_tpltClass,l); + } +}; + +/** + * parameter_tplt + */ +class parameter_tplt : public templates +{ +#define PARAMETER_CONST(etype) \ + etype(vf,PARAMETER_CONTEXT,context) \ + etype(vs,PARAMETER_SYNTAX,syntax) \ + etype(vs,PARAMETER_ATTRIBUTE,attribute) \ + etype(vs,PARAMETER_BEHAVIOUR,behaviour) \ + etype(vs,PARAMETER_REGISTERED,registered) + +#define vs , +#define vf +#define etype(COMMA,e,T) COMMA e + public: + enum eConstruct {PARAMETER_CONST(etype) ,PARAMETER_END}; +#undef etype +#undef vs +#undef vf + protected: + construct *m_constructs[PARAMETER_END]; +/** + * Add setter and getters + */ + +#define vs +#define vf +#define etype(v,e,T) \ + parameter_## T * get_##T() const { return dynamic_cast< parameter_##T*>(m_constructs[e]);} \ + void set_##T(parameter_##T *c) { m_constructs[ e ] = c;} \ + + public: + PARAMETER_CONST(etype) +#undef etype +#undef vs +#undef vf + protected: + parameter_tplt(Adt::AdtClass c,const label &l) + : templates(c,l) + { + memset(m_constructs,0x00,sizeof( construct *) * PARAMETER_END); + } + public: + static parameter_tplt *Create(const label &l) + { + return new parameter_tplt(Adt::parameter_tpltClass,l); + } +}; + +/** + * notification_tplt + */ +class notification_tplt : public templates +{ +#define NOTIFICATION_CONST(etype) \ + etype(vf,NOTIFICATION_BEHAVIOUR,behaviour) \ + etype(vs,NOTIFICATION_MODE,mode) \ + etype(vs,NOTIFICATION_PARAMETERS,parameters) \ + etype(vs,NOTIFICATION_WITH_INFORMATION,with_information) \ + etype(vs,NOTIFICATION_WITH_REPLY,with_reply) \ + etype(vs,NOTIFICATION_REGISTERED,registered) + +#define vs , +#define vf +#define etype(COMMA,e,T) COMMA e + public: + enum eConstruct {NOTIFICATION_CONST(etype) ,NOTIFICATION_END}; +#undef etype +#undef vs +#undef vf + protected: + construct *m_constructs[NOTIFICATION_END]; +/** + * Add setter and getters + */ + +#define vs +#define vf +#define etype(v,e,T) \ + notification_## T * get_##T() const { return dynamic_cast< notification_##T*>(m_constructs[e]);} \ + void set_##T(notification_##T *c) { m_constructs[ e ] = c;} \ + + public: + NOTIFICATION_CONST(etype) +#undef etype +#undef vs +#undef vf + protected: + notification_tplt(Adt::AdtClass c,const label &l) + : templates(c,l) + { + memset(m_constructs,0x00,sizeof( construct *) * NOTIFICATION_END); + } + public: + static notification_tplt *Create(const label &l) + { + return new notification_tplt(Adt::notification_tpltClass,l); + } +}; + diff --git a/include/AST/ASTConsumer.h b/include/AST/ASTConsumer.h new file mode 100644 index 0000000..3a65295 --- /dev/null +++ b/include/AST/ASTConsumer.h @@ -0,0 +1,20 @@ +#ifndef ASTCONSUMER_H__ +#define ASTCONSUMER_H__ + +/** + * Abstract Class to be implemented to traverse the tree + * Ideas of consumers : + * - graphical view + * - regenerate source in sdl form from lds form + * - c++ strategy pattern for automaton + * - cm automaton files aac aaa eta ptr tra + * - and of course a multiplex consumer which is able to launch multiple consumer on one declaration + */ +class ASTConsumer { + public: + ASTConsumer() ; + /// Called by ASTParser .... + bool HandleToplevelDecl(const ASTContext &c,std::string &decls); +}; + +#endif diff --git a/include/AST/ASTContext.h b/include/AST/ASTContext.h new file mode 100644 index 0000000..93ef8e5 --- /dev/null +++ b/include/AST/ASTContext.h @@ -0,0 +1,64 @@ +#ifndef ASTCONTEXT_H +#define ASTCONTEXT_H + +namespace AST { +class Type; +class ConstantArrayType; +class TranslationUnitDecl; +/** + * ASTContext is a placeholder class that contains all defined types and function. + * Datatypes are created through this class. + * Aligned Memory allocation should be handled by this class to. + * + */ +class ASTContext +{ + public: + typedef std::map Typelist; + typedef typename Typelist::const_iterator TypelistConstIterator; + typedef typename Typelist::iterator TypelistIterator; + private: + protected: + TranslationUnitDecl *m_TranslationUnitDecl; + Typelist m_Types; + std::vector m_ConstantArrays; + public: + + // BuiltinTypes ... +#define BUILTIN_TYPE(Id,Cls) BuiltinType Cls; +#include "AST/BuiltinTypes.h.def" + // Functions that Return Type for various declarations + // eg Variable, Pointer, Structure, Parameter variable, Function and so on + Type &getRecordType(const RecordDecl *); + + Type &getValueTypeType(const ValueTypeDecl *D); + + Type &getTypedefType(const TypedefDecl *D); + + Type &getFunctionType(Type *RetTy,std::vectorParma,const std::string &fn); + + Type &getConstantArrayType(Type *EltTy,long length); + + const Typelist &getTypes() const { return m_Types;}; + /** + * Initialize all builtin types. + */ + void InitBuiltinTypes(); + + Type &getTypeDeclType(TypeDecl *Decl,TypeDecl *prevDecl = NULL); + /** + * + */ + TranslationUnitDecl *getTranslationUnitDecl() const { return m_TranslationUnitDecl; }; + /** + * Create an ASTContext Object. + * This object will be used in various places where datatype creation is necessary. + */ + ASTContext() ; + ~ASTContext() ; +}; + +} + + +#endif /*ASTCONTEXT_H*/ diff --git a/include/AST/ASTRecursiveVisitor.h b/include/AST/ASTRecursiveVisitor.h new file mode 100644 index 0000000..25c48db --- /dev/null +++ b/include/AST/ASTRecursiveVisitor.h @@ -0,0 +1,354 @@ +#ifndef ASTRECURSIVEVISITOR_H__ +#define ASTRECURSIVEVISITOR_H__ + + +#define UNARYOP_LIST() \ + OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) \ + OPERATOR(PreDec) OPERATOR(Plus) OPERATOR(Minus) \ + OPERATOR(Nor) OPERATOR(LNot) + +#define BINOP_LIST() \ + OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) \ + OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) OPERATOR(LT) \ + OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) \ + OPERATOR(NE) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \ + OPERATOR(LAnd) OPERATOR(LOr) OPERATOR(Assign) + +namespace AST { + +#define TRY_TO(f) do { \ + if (! getDerived().f ) { \ + std::cout<<"TRY_TO FAILED calling "<< #f< +class RecursiveVisitor { + public: + Derived &getDerived() { + return *static_cast(this); + }; + + bool TraverseStmt(Stmt *); + bool TraverseDecl(Decl *); + + bool TraverseDeclContextHelper(DeclContext *DC); + bool TraverseStmtHelper(Stmt *DC); + // WalkupFrom Category + // + // -- Methods of Stmt + +#define STMT(CLASS,PARENT) bool Traverse##CLASS(CLASS *S); +#include "Stmt.h.inc" + +#undef STMT + + bool WalkupFromStmt(Stmt *s) { return getDerived().VisitStmt(s);} + + bool VisitStmt(Stmt *s) {return true;} + +#define STMT(CLASS,PARENT) \ + bool WalkupFrom##CLASS(CLASS *S) { \ + TRY_TO(WalkupFrom##PARENT(S)); \ + TRY_TO(Visit##CLASS(S)); \ + return true; \ + } \ + bool Visit##CLASS(CLASS *S) {return true; } + +#include "Stmt.h.inc" + +#undef STMT + + // --- Unary Operators are Opcodes in UnaryOperator class +#define OPERATOR(OP) \ + bool TraverseUnary##OP(UnaryOperator *S) { \ + TRY_TO(WalkupFromUnary##OP(S) ); \ + TRY_TO(TraverseStmt(S->getSubExpr(S) ); \ + return true; \ + } \ + bool WalkupUnaryFrom##OP(UnaryOperator *S) { \ + TRY_TO(WalkupFromUnaryOperator(S)); \ + TRY_TO(VisitUnary##OP(S)); \ + return true; \ + } \ + bool VisitUnary##OP(UnayOperator *S) { \ + return true; \ + } \ + UNARYOP_LIST() +#undef OPERATOR + + // -- Binary Operators +#define OPERATOR(OP) \ + bool TraverseBin##OP(BinaryOperator *S) { \ + TRY_TO(WalkupFromBin##OP(S) ); \ + TRY_TO(TraverseStmt(S->getLHS(S) ); \ + TRY_TO(TraverseStmt(S->getLHS(S) ); \ + return true; \ + } \ + bool WalkupFromBin##OP(UnaryOperator *S) { \ + TRY_TO(WalkupFromBinaryOperator(S)); \ + TRY_TO(VisitBin##OP(S)); \ + return true; \ + } \ + bool VisitBin##OP(BinaryOperator *S) { \ + return true; \ + } \ + BINOP_LIST() +#undef OPERATOR + + + // --- Methods on DECL + bool WalkupFromDecl(Decl *s) { return getDerived().VisitDecl(s);} + bool VisitDecl(Decl *s) {return true;} + +#define DECL(CLASS,BASE) \ + bool Traverse##CLASS (CLASS *d); +#include "Decl.h.inc" + +#define DECL(CLASS,PARENT) \ + bool WalkupFrom##CLASS(CLASS *S) { \ + TRY_TO(WalkupFrom##PARENT(S)); \ + TRY_TO(Visit##CLASS(S)); \ + return true; \ + } \ + bool Visit##CLASS(CLASS *S) {return true; } +#include "Decl.h.inc" + + +}; + +/** + * Implementation part + */ +template +bool RecursiveVisitor::TraverseStmtHelper(Stmt *S) { +#if 1 + if (! S) + return true; + + Stmt::range_iterator c = S->children(); + for ( ; c.first != c.second ; ++c.first) { + TRY_TO( TraverseStmt(*(c.first) ) ); + } + return true; +#endif +} +// -- Stmt Traversal + +#define DEF_TRAVERSE_STMT(STAMT,CODE) \ + template \ + bool RecursiveVisitor::Traverse##STAMT(STAMT *S) { \ + TRY_TO(WalkupFrom##STAMT(S)); \ + { CODE ; } \ + /* Traverse Children to be done*/ \ + return TraverseStmtHelper(S); \ + /*return true; */ \ + } \ + + +DEF_TRAVERSE_STMT(SwitchStmt, {}) +DEF_TRAVERSE_STMT(IfStmt, {}) +DEF_TRAVERSE_STMT(WhileStmt, {}) +DEF_TRAVERSE_STMT(GotoStmt, {}) +DEF_TRAVERSE_STMT(ForStmt, {}) +DEF_TRAVERSE_STMT(CompoundStmt, { + // std::cout<<"TraverCompoundStmt"<begin() ; it != S->end() ; ++it) { + TraverseStmt(*it); + } +}) +DEF_TRAVERSE_STMT(DeclStmt, {}) +DEF_TRAVERSE_STMT(ReturnStmt, {}) +DEF_TRAVERSE_STMT(LabelStmt, {}) +DEF_TRAVERSE_STMT(BreakStmt, {}) +DEF_TRAVERSE_STMT(SwitchCaseStmt, { + TraverseStmt(S->getSubStmt()); + }) + +DEF_TRAVERSE_STMT(AsmStmt, {}) +DEF_TRAVERSE_STMT(LdsAsmStmt, {}) +DEF_TRAVERSE_STMT(OutputStmt, {}) + +DEF_TRAVERSE_STMT(Expr,{ +}) +DEF_TRAVERSE_STMT(ParenExpr, { }) +DEF_TRAVERSE_STMT(ParenListExpr, { }) +DEF_TRAVERSE_STMT(MemberExpr, { + TraverseStmt(S->getBase()); + // TraverseStmt(S->getMember()); + }) +DEF_TRAVERSE_STMT(ArraySubscriptExpr, { + TraverseStmt(S->getBase()); + TraverseStmt(S->getIndex()); + }) +DEF_TRAVERSE_STMT(LdsThisExpr, { }) +DEF_TRAVERSE_STMT(CreateExpr, { }) +DEF_TRAVERSE_STMT(PidExpr, { }) + +DEF_TRAVERSE_STMT(DeclRefExpr, {}) +DEF_TRAVERSE_STMT(CallExpr, { + // std::cout<<"Traverse CallExpr"<(VAR)) + + +template +bool RecursiveVisitor::TraverseStmt(Stmt *S) { + if (!S) + return true; + // std::cout<<"RecursiveVisitor<>::TraverseStmt "<getStmtClass()<(S) ) { + // Hey Dispatch according to OpCode + + } else if(UnaryOperator *BinOp = dynamic_cast(S) ) { + // Hey Dispatch according to OpCode + + } + + // Dispatch according to statement + switch (S->getStmtClass()) { + case Stmt::NoStmtClass: + break; +#define STMT(CLASS,PARENT) \ + case Stmt::CLASS##Class : \ + DISPATCH_STMT(CLASS,CLASS,S); +#include "Stmt.h.inc" + } + return true; +} + +// -- Decl Traversal + +template < typename Derived> +bool RecursiveVisitor::TraverseDeclContextHelper(DeclContext *DC) +{ + int i=0; + if ( !DC ) + return true; + //std::cout<<" TraverseDeclContextHelper begin "<<(long)(DC)<begin(); it != DC->end() ; ++it ) + { + //std::cout<<" TraverseDeclContextHelper count "<getKind()< +bool RecursiveVisitor::TraverseDecl(Decl *D) { + + if (!D) + return true; +#define DECL(CLASS,BASE) \ + case DeclBase::CLASS : \ + if (! getDerived().Traverse##CLASS(static_cast< CLASS *>(D)) ) { \ + std::cout<<"RecursiveVisitor::TraverseDecl Failed Traverse"<< #CLASS<::TraverseDecl kind:"<getKind()<getKind()) + { +#include "Decl.h.inc" + default: + std::cout<<"TraverseDecl default:"< \ + bool RecursiveVisitor::Traverse##DECL(DECL *d) { \ + TRY_TO(WalkupFrom##DECL(d)); \ + { CODE;} \ + TRY_TO(TraverseDeclContextHelper(dynamic_cast(d))); \ + return true; \ + } \ + +DEF_TRAVERSE_DECL(TranslationUnitDecl, { + }) + +DEF_TRAVERSE_DECL(NamedDecl, { }) + +DEF_TRAVERSE_DECL(GateDecl, { }) +DEF_TRAVERSE_DECL(ChannelEndPointDecl, { }) +DEF_TRAVERSE_DECL(ChannelPathDecl, { }) +DEF_TRAVERSE_DECL(ChannelDecl, { }) + +DEF_TRAVERSE_DECL(TypeDecl, { }) +DEF_TRAVERSE_DECL(TypedefDecl, { }) +DEF_TRAVERSE_DECL(ValueTypeDecl, { }) +DEF_TRAVERSE_DECL(EnumDecl, { }) + + +DEF_TRAVERSE_DECL(AgentTypeDecl, { }) +DEF_TRAVERSE_DECL(AutomatonTypeDecl, { }) +DEF_TRAVERSE_DECL(BlockTypeDecl, { }) +DEF_TRAVERSE_DECL(SystemTypeDecl, { }) + +DEF_TRAVERSE_DECL(PackageUseDecl, { }) +DEF_TRAVERSE_DECL(ValueDecl, { }) +DEF_TRAVERSE_DECL(EnumConstantDecl, { }) +DEF_TRAVERSE_DECL(VarDecl, { }) +DEF_TRAVERSE_DECL(TimerDecl, { }) +DEF_TRAVERSE_DECL(ParmVarDecl, { }) + +DEF_TRAVERSE_DECL(FunctionDecl, { + for (FunctionDecl::param_iterator it = d->param_begin(); it != d->param_end() ; ++it) { + TRY_TO(TraverseDecl(*it)); + } + if (d->getBody() != NULL) { + TRY_TO(TraverseStmt(d->getBody())) ; + } + return true; // Avoid call TraverseDeclContextHelp +}) + +DEF_TRAVERSE_DECL(TransitionDecl, { + if (d->getBody() != NULL) { + TRY_TO(TraverseStmt(d->getBody())) ; + } + return true; // Avoid call TraverseDeclContextHelp +}) + +DEF_TRAVERSE_DECL(StateDecl, { + //std::cout<<"RecursiveVisitor::TraverseStateDecl"<::iterator iterator; + typedef std::vector::const_iterator const_iterator; + + + private: + Context(const std::string &_name,Context *_p = NULL) : m_Parent(_p),m_Name(_name) {}; + virtual ~Context() {}; + + public: + + static Context &getRootContext() { + static Context *m_Context = NULL; + if (m_Context == NULL) { + m_Context = new Context(""); + } + return *m_Context; + }; + + Context &NewContext(const std::string &_name) { + m_Contexts.push_back(new Context(_name,this)); + return * m_Contexts.back(); + }; + + Context &getParent() const {return *m_Parent;}; + void addExpr(Expr *_e) { m_Exprs.push_back(_e); } ; + void addDecl(Decl *_e) { m_Decls.push_back(_e); } ; + void addStmt(Stmt *_e) { m_Stmts.push_back(_e); } ; + + protected: + std::vector m_Contexts; + + std::vector m_Decls; + std::vector m_Stmts; + std::vector m_Exprs; + Context *m_Parent; + std::string m_Name; +}; + +} +#endif diff --git a/include/AST/Decl.h b/include/AST/Decl.h new file mode 100644 index 0000000..0ed47d1 --- /dev/null +++ b/include/AST/Decl.h @@ -0,0 +1,62 @@ +#ifndef DECL_H__ +#define DECL_H__ + +#include "DeclBase.h" + +typedef std::string SignatureNodeID; + +namespace AST { +class DeclContext; +class TranslationUnitDecl; + +class Decl : public DeclBase +{ + public: + /// Construtor + Decl(Kind KD,DeclContext *_ctx) : DeclBase(KD,_ctx) , m_NextDecl(NULL) {}; + /// + virtual Stmt *getBody() { return NULL;}; + /// + virtual void setBody(Stmt *s) { ;}; + /// + void setNextDeclInContext(Decl *d) { m_NextDecl = d;}; + /// + + Decl *getNextDeclInContext() { return m_NextDecl ;}; + + AST::TranslationUnitDecl *getTranslationUnitDecl() ; + + protected: + Decl *m_NextDecl; +}; + +class NamedDecl; +typedef std::vector DeclContextLookupResult; + +} + +#include "DeclContext.h" + +#include "Type.h" +namespace AST { +#include "DeclNamedDecl.h" +#include "DeclTypeDecl.h" +#include "DeclPackageUseDecl.h" +#include "DeclLabelDecl.h" +#include "DeclValueDecl.h" +#include "DeclVarDecl.h" +#include "DeclParmVarDecl.h" +#include "DeclFunctionDecl.h" +#include "DeclRefStateDecl.h" +#include "DeclFieldDecl.h" +#include "DeclRecordDecl.h" +#include "DeclTransitionDecl.h" +#include "DeclTranslationUnitDecl.h" +#include "DeclStateDecl.h" +#include "DeclEventDecl.h" +#include "DeclAutomatonDecl.h" + +} +#include "TemplateBase.h" + +#endif diff --git a/include/AST/Decl.h.inc b/include/AST/Decl.h.inc new file mode 100644 index 0000000..f6d2686 --- /dev/null +++ b/include/AST/Decl.h.inc @@ -0,0 +1,37 @@ +#ifndef DECL + #define DECL +#endif +DECL(TranslationUnitDecl,Decl) +DECL(PackageUseDecl,Decl) +DECL(NamedDecl,Decl) +DECL(TypeDecl,Decl) +DECL(ValueTypeDecl,TypeDecl) +DECL(TypedefDecl,TypeDecl) +DECL(RecordDecl,NamedDecl) +DECL(EnumDecl,TypeDecl) +DECL(AgentTypeDecl,TypeDecl) +DECL(AutomatonTypeDecl,AgentTypeDecl) +DECL(BlockTypeDecl,AgentTypeDecl) +DECL(SystemTypeDecl,AgentTypeDecl) +DECL(RefStateDecl,Decl) +DECL(LabelDecl,NamedDecl) +DECL(ValueDecl,NamedDecl) +DECL(EnumConstantDecl,ValueDecl) +DECL(FieldDecl,ValueDecl) +DECL(FunctionDecl,ValueDecl) +DECL(TransitionDecl,ValueDecl) +DECL(EventDecl,ValueDecl) +DECL(TimerDecl,ValueDecl) +DECL(VarDecl,ValueDecl) +DECL(ParmVarDecl,VarDecl) +DECL(StateDecl,NamedDecl) +DECL(AgentDecl,NamedDecl) +DECL(GateDecl,NamedDecl) +DECL(ChannelDecl,NamedDecl) +DECL(ChannelPathDecl,NamedDecl) +DECL(ChannelEndPointDecl,NamedDecl) +DECL(AutomatonDecl,AgentDecl) +DECL(PackageDecl,AgentDecl) +DECL(SystemDecl,AgentDecl) +DECL(BlockDecl,AgentDecl) +#undef DECL diff --git a/include/AST/DeclAutomatonDecl.h b/include/AST/DeclAutomatonDecl.h new file mode 100644 index 0000000..4e71b7c --- /dev/null +++ b/include/AST/DeclAutomatonDecl.h @@ -0,0 +1,115 @@ +#ifndef DECLAUTOMATONDECL_H__ +#define DECLAUTOMATONDECL_H__ + + + +/** + * AgentDecl is a generic class for all kind of agents that can be found in an lds + * description. + * AutomatonDecl,BlockDecl,PackageDecl,SystemDecl + */ +class AgentDecl : public NamedDecl , public DeclContext { + public: + typedef specific_decl_iterator event_iterator; + protected: + AgentDecl(Kind KD,DeclContext *DC,const std::string &l) : NamedDecl(KD,DC,l) ,DeclContext() { + + }; + + public: + + event_iterator events_begin() { return event_iterator(begin()) ; }; + event_iterator events_end() { return event_iterator() ; }; + +}; + + +/** + * + */ +class AutomatonDecl : public AgentDecl { + public: + typedef specific_decl_iterator event_iterator; + protected: + AutomatonDecl(DeclContext *DC,const std::string &l) : AgentDecl(DeclBase::AutomatonDecl,DC,l) { + + }; + + public: + static AutomatonDecl *Create(DeclContext *DC,const std::string &name) { + return new AutomatonDecl(DC,name); + }; + + event_iterator events_begin() { return event_iterator(begin()) ; }; + event_iterator events_end() { return event_iterator() ; }; + +}; + +/** + * In System description languages there are three kind of agents. + * and Packages + * + */ +class PackageDecl : public AgentDecl { + public: + typedef specific_decl_iterator event_iterator; + protected: + PackageDecl(DeclContext *DC,const std::string &l) : AgentDecl(DeclBase::PackageDecl,DC,l) { + + }; + + public: + static PackageDecl *Create(DeclContext *DC,const std::string &name) { + return new PackageDecl(DC,name); + }; + + event_iterator events_begin() { return event_iterator(begin()) ; }; + event_iterator events_end() { return event_iterator() ; }; + +}; + +/** + * This Class repesents an LDS system + * + */ +class SystemDecl : public AgentDecl { + public: + typedef specific_decl_iterator event_iterator; + protected: + SystemDecl(DeclContext *DC,const std::string &l) : AgentDecl(DeclBase::SystemDecl,DC,l) { + + }; + + public: + static SystemDecl *Create(DeclContext *DC,const std::string &name) { + return new SystemDecl(DC,name); + }; + + event_iterator events_begin() { return event_iterator(begin()) ; }; + event_iterator events_end() { return event_iterator() ; }; + +}; + +/** + * Represents and LDS Block + */ +class BlockDecl : public AgentDecl { + public: + typedef specific_decl_iterator event_iterator; + protected: + BlockDecl(DeclContext *DC,const std::string &l) : AgentDecl(DeclBase::BlockDecl,DC,l) { + + }; + + public: + static BlockDecl *Create(DeclContext *DC,const std::string &name) { + return new BlockDecl(DC,name); + }; + + event_iterator events_begin() { return event_iterator(begin()) ; }; + event_iterator events_end() { return event_iterator() ; }; + +}; + + +#endif diff --git a/include/AST/DeclBase.h b/include/AST/DeclBase.h new file mode 100644 index 0000000..ae2a79f --- /dev/null +++ b/include/AST/DeclBase.h @@ -0,0 +1,38 @@ +#ifndef DECLBASE_H__ +#define DECLBASE_H__ + +namespace AST { + +class DeclContext; + +class DeclBase { + public: + enum Kind { + DECL_EMPTY + ,DECL_CONST + ,DECL_PROTOTYPE + ,DECL_BLOCK + ,DECL_TYPE +#define DECL(Class,Base) ,Class +#include "Decl.h.inc" +#undef DECL + }; + + public: + DeclBase(Kind KD,DeclContext *_ctx=NULL) : m_DeclContext(_ctx) , m_Kind(KD) {}; + virtual ~DeclBase() {}; + + /// + DeclContext *getDeclContext() {return m_DeclContext; } ; + /// + const DeclContext *getDeclContext() const {return const_cast(m_DeclContext); } ; + + Kind getKind() { return m_Kind; }; + protected: + DeclContext *m_DeclContext; + Kind m_Kind; +}; + +} + +#endif diff --git a/include/AST/DeclBlockDecl.h b/include/AST/DeclBlockDecl.h new file mode 100644 index 0000000..2a58a4e --- /dev/null +++ b/include/AST/DeclBlockDecl.h @@ -0,0 +1,11 @@ +#ifndef BLOCKDECL_H__ +#define BLOCKDECL_H__ + + +class BlockDecl : public Decl { + + public: + BlockDecl() {}; + ~BlockDecl() {}; +}; +#endif diff --git a/include/AST/DeclContext.h b/include/AST/DeclContext.h new file mode 100644 index 0000000..c5f8e7a --- /dev/null +++ b/include/AST/DeclContext.h @@ -0,0 +1,201 @@ +#ifndef DECLCONTEXT_H__ +#define DECLCONTEXT_H__ + +namespace AST { + +class Decl; +/** + * + * + */ +class DeclContext { + public: + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + + typedef DeclContextLookupResult lookup_result; + + public: + DeclContext() : m_FirstDecl(NULL),m_LastDecl(NULL) {}; + virtual ~DeclContext() {}; + /// + void addHiddenDecl(Decl *d) ; + /// + void addDecl(Decl *_d) + { + addHiddenDecl(_d); + }; + /// TOBe coded + DeclContext *getParentLookupContext() { return getParent() ; } ; + + /// + DeclContext *getParent(); + /// + const DeclContext *getParent() const; + /** + * Alright, Decl iterator will be a copy of the one from clang. + */ + class decl_iterator { + Decl *m_Current; + + public: + typedef Decl *value_type; + typedef const value_type &reference; + typedef const value_type *pointer; + typedef ptrdiff_t difference_type; + + typedef std::forward_iterator_tag iterator_category; + decl_iterator() : m_Current(NULL) {} + + explicit decl_iterator(Decl *d) : m_Current(d) {} + + reference operator *() const {return m_Current; } + value_type operator ->() const { return m_Current; } + + decl_iterator & operator++() { + m_Current = m_Current->getNextDeclInContext(); + return *this; + } + + friend bool operator ==(decl_iterator x,decl_iterator y ) { + return x.m_Current == y.m_Current; + } + + friend bool operator !=(decl_iterator x,decl_iterator y ) { + return x.m_Current != y.m_Current; + } + }; + + // + // Implemented this to travel only through transitions and events .... + // That very usefull iterator + // + template + class specific_decl_iterator { + DeclContext::decl_iterator Current; + + void SkipToNext() { + while (*Current && ! dynamic_cast(*Current)) + ++Current; + } + public: + typedef SpecificDecl *value_type; + typedef void reference; + typedef void pointer; + typedef std::iterator_traits::difference_type difference_type; + typedef std::forward_iterator_tag iterator_category; + + specific_decl_iterator() : Current() {} + specific_decl_iterator(const AST::DeclContext::decl_iterator &_c) : Current(_c) { + SkipToNext(); + } + + // Access operators + value_type operator *() { return dynamic_cast(*Current) ; }; + // Is there a bug here ? + value_type operator ->() { return dynamic_cast(*Current) ; }; + + // incr operators + specific_decl_iterator & operator ++() { + ++Current; + SkipToNext(); + return *this; + } + + specific_decl_iterator operator ++(int) { + specific_decl_iterator tmp (*this); + ++(*this); + return tmp; + } + + // Comparison functions + friend bool operator ==(const specific_decl_iterator &x, const specific_decl_iterator &y) { + return (x.Current == y.Current ); + } + friend bool operator !=(const specific_decl_iterator &x, const specific_decl_iterator &y) { + return (x.Current != y.Current ); + } + }; + /** + * From Clang DeclContext + * I finally added that iterator as well to retrieve DeclRefExpr that reference + * events for instance. + */ + template + class filtered_decl_iterator { + DeclContext::decl_iterator Current; + + void SkipToNext() { + SpecificDecl *sd = dynamic_cast(*Current); + while (*Current && (!(sd) || + (Acceptable && !(sd->*Acceptable())) )) + ++Current; + } + public: + typedef SpecificDecl *value_type; + typedef void reference; + typedef void pointer; + typedef std::iterator_traits::difference_type difference_type; + typedef std::forward_iterator_tag iterator_category; + + filtered_decl_iterator() : Current() {} + filtered_decl_iterator(const AST::DeclContext::decl_iterator &_c) : Current(_c) { + SkipToNext(); + } + + // Access operators + value_type operator *() { return dynamic_cast(*Current) ; }; + // Is there a bug here ? + value_type operator ->() { return dynamic_cast(*Current) ; }; + + // incr operators + filtered_decl_iterator & operator ++() { + ++Current; + SkipToNext(); + return *this; + } + + filtered_decl_iterator operator ++(int) { + filtered_decl_iterator tmp (*this); + ++(*this); + return tmp; + } + + // Comparison functions + friend bool operator ==(const filtered_decl_iterator &x, const filtered_decl_iterator &y) { + return (x.Current == y.Current ); + } + friend bool operator !=(const filtered_decl_iterator &x, const filtered_decl_iterator &y) { + return (x.Current != y.Current ); + } + }; + + // + decl_iterator begin() {return decl_iterator(m_FirstDecl) ;}; + decl_iterator end() {return decl_iterator() ;}; + + lookup_result lookup(const std::string &_n) ; + /// + bool isTranslationUnit() const ; + /// + bool isRecord() const ; + /// + bool isFunction() const ; + /// + bool isState() const ; + /// + bool isTransition() const ; + /// + bool isAutomaton() const ; + /// + bool isBlock() const ; + /// + bool isPackage() const ; + + protected: + Decl *m_FirstDecl,*m_LastDecl; + // Next is contained in Decl. and parent is Decl as well. +}; + +} +#endif diff --git a/include/AST/DeclEventDecl.h b/include/AST/DeclEventDecl.h new file mode 100644 index 0000000..d8c7f1f --- /dev/null +++ b/include/AST/DeclEventDecl.h @@ -0,0 +1,40 @@ +#ifndef EVENTDECL_H__ +#define EVENTDECL_H__ + +/** + * \brief EventDecl is a signal which can be typed. If the signal + * has parameters The event is a method of each State that receives as parameter + * the types in the signal. + * TODO: To be completed to take into account + */ +class EventDecl : public ValueDecl,public DeclContext { + public: + typedef ::std::vector parameter_array; + typedef std::vector::iterator param_iterator; + typedef std::vector::const_iterator const_param_iterator; + protected: + EventDecl(DeclContext *DC,const std::string &n,Type *T) : ValueDecl(DeclBase::EventDecl,DC,n,T),DeclContext() { + } + public: + static EventDecl *Create(DeclContext *DC,const std::string &n,Type *T) {return new EventDecl(DC,n,T); }; + + unsigned int param_size() const { return m_Parameters.size(); } + param_iterator param_begin() { return m_Parameters.begin(); } + param_iterator param_end() { return m_Parameters.end(); } + + void add_param(AST::ParmVarDecl *p) { m_Parameters.push_back(p); }; + + void set_parameters(const parameter_array &a) + { m_Parameters.resize(a.size()); std::copy (a.begin(),a.end(),m_Parameters.begin()); } ; + + AST::ParmVarDecl * get_Parameter(int i) const + { return m_Parameters[i]; } + const parameter_array ¶meters() const { return m_Parameters; }; + /// Build Signature of EventDecl. It is Used to store Types + void Signature(SignatureNodeID &id); + protected: + std::vector m_Parameters; + +}; + +#endif diff --git a/include/AST/DeclFieldDecl.h b/include/AST/DeclFieldDecl.h new file mode 100644 index 0000000..f03823b --- /dev/null +++ b/include/AST/DeclFieldDecl.h @@ -0,0 +1,27 @@ +#ifndef DECLFIELDDECL_H__ +#define DECLFIELDDECL_H__ +/** + * \brief represents the declaration of a : + * - variable < in this case it's a lvalue > + * - function < in this case it's the function designator > + * - enum < a constant> + * + * Missing the Type argument. A value has a type + * and something like QualType (plagia of clang) + */ +class FieldDecl : public ValueDecl +{ + protected: + bool m_Optional; + FieldDecl(Kind K,DeclContext *DC,const std::string &DeclName,Type *T,bool opt) + : m_Optional(opt), ValueDecl(K,DC,DeclName,T) {}; + public: + + /// Some Static functions... + static FieldDecl *Create(DeclContext *DC,const std::string &name,Type *T,bool opt=false) { + return new FieldDecl(DeclBase::FieldDecl,DC,name,T,opt); + }; + bool isOptional() const { return m_Optional; } +}; + +#endif diff --git a/include/AST/DeclFunctionDecl.h b/include/AST/DeclFunctionDecl.h new file mode 100644 index 0000000..a0d695d --- /dev/null +++ b/include/AST/DeclFunctionDecl.h @@ -0,0 +1,42 @@ +#ifndef DECLFUNCTIONDECL_H__ +#define DECLFUNCTIONDECL_H__ + + +class ParmVarDecl; + +class FunctionDecl : public ValueDecl , public DeclContext { + public: + typedef ::std::vector parameter_array; + typedef std::vector::iterator param_iterator; + typedef std::vector::const_iterator const_param_iterator; + + protected: + Stmt *m_Body; + /// Missing parmaters + FunctionDecl (DeclContext *DC,const std::string &n,Type *T) : m_New(true), ValueDecl(DeclBase::FunctionDecl,DC,n,T), DeclContext() , m_Body(NULL) { + }; + bool m_New; // Because of poor declartion, We check if the seen function call is new or not. + public: + Stmt *getBody() const { return m_Body; }; + void setBody(Stmt *b) { m_Body = b; }; + /// Some Static functions... + static FunctionDecl *Create(DeclContext *DC,const std::string &name,Type *T) { + return new FunctionDecl(DC,name,T); + }; + + inline bool isNew() { return m_New; } + + unsigned int param_size() const { return m_Parameters.size(); } + param_iterator param_begin() { return m_Parameters.begin(); } + param_iterator param_end() { return m_Parameters.end(); } + + void add_param(AST::ParmVarDecl *p) { m_New = false; m_Parameters.push_back(p); }; + + bool hasDefinition() { return m_Body != NULL; }; + // + void Signature(SignatureNodeID &id); + protected: + std::vector m_Parameters; +}; + +#endif diff --git a/include/AST/DeclLabelDecl.h b/include/AST/DeclLabelDecl.h new file mode 100644 index 0000000..e819f0c --- /dev/null +++ b/include/AST/DeclLabelDecl.h @@ -0,0 +1,21 @@ +#ifndef LABELDECL_H__ +#define LABELDECL_H__ + +/** + * + */ +class LabelDecl : public NamedDecl { + + LabelDecl(Kind K,DeclContext *DC,const std::string &_n) : NamedDecl(DeclBase::LabelDecl,DC,_n) {}; + + LabelDecl(DeclContext *DC,const std::string &_n) : NamedDecl(DeclBase::LabelDecl,DC,_n) {}; + public: + static LabelDecl *Create(DeclContext *DC,const std::string &_n) { + return new LabelDecl(DC,_n); + } + + + +}; + +#endif diff --git a/include/AST/DeclNamedDecl.h b/include/AST/DeclNamedDecl.h new file mode 100644 index 0000000..7bc53ac --- /dev/null +++ b/include/AST/DeclNamedDecl.h @@ -0,0 +1,121 @@ +#ifndef NAMEDDECL_H__ +#define NAMEDDECL_H__ + +class NamedDecl : public Decl { + std::string m_Name; + public: + NamedDecl(Kind KD,DeclContext *DC,const std::string &_name) : Decl(KD,DC) + ,m_Name(_name) + { + m_DeclContext = DC; + }; + /// + void setName(const std::string &s) {m_Name = s ; }; + /// + //std::string getName() const {return m_Name; } ; + const std::string &getName() const {return m_Name; } ; +}; + + +/** + * \brief Gate Declaration + * It' a Named Declaration that Holds a list a signalsDecl . + */ +class GateDecl : public NamedDecl +{ + protected: + Expr *m_Signals; + GateDecl(Kind K,DeclContext *DC,const std::string &DeclName) : NamedDecl(K,DC,DeclName) + , m_Signals(NULL) + {}; + + public: + + /// Some Static functions... Missing Init Expression and Type should be integer I think + static GateDecl *Create(ASTContext &C,AST::DeclContext *DC,const std::string &name) + { + return new GateDecl(DeclBase::GateDecl,DC,name); + }; + +}; + + +/** + * \brief ChannelEndPoint Declaration + * It' a Named Declaration that Holds a list a signalsDecl . + */ +class ChannelEndPointDecl : public NamedDecl +{ + public: + enum ChannelKind {eAGENT,eENV,eTHIS}; + protected: + ChannelEndPointDecl(Kind K,DeclContext *DC,const std::string &DeclName,ChannelKind k) + : m_ChannelKind(k), NamedDecl(K,DC,DeclName) + {}; + + ChannelKind m_ChannelKind; + public: + /// Some Static functions... Missing Init Expression and Type should be integer I think + static ChannelEndPointDecl *Create(ASTContext &C,AST::DeclContext *DC,const std::string &name,ChannelKind k) + { + return new ChannelEndPointDecl(DeclBase::ChannelEndPointDecl,DC,name,k); + }; + + bool isAgent() const { return m_ChannelKind == eAGENT; }; + bool isThis() const { return m_ChannelKind == eTHIS; }; + bool isEnv() const { return m_ChannelKind == eENV; }; + /* Missing getVia () return gateName if present */ +}; + + +/** + * \brief ChannelPath Declaration + * It' a Named Declaration that Holds a list a signalsDecl . + */ +class ChannelPathDecl : public NamedDecl +{ + protected: + AST::ChannelEndPointDecl *m_From,*m_To; + + ChannelPathDecl(Kind K,DeclContext *DC,const std::string &DeclName) : NamedDecl(K,DC,DeclName) + , m_From(NULL) + , m_To(NULL) + {}; + + public: + + /// Some Static functions... Missing Init Expression and Type should be integer I think + static ChannelPathDecl *Create(ASTContext &C,AST::DeclContext *DC,const std::string &name) + { + return new ChannelPathDecl(DeclBase::ChannelPathDecl,DC,name); + }; + + void setFrom(AST::ChannelEndPointDecl *d ) { m_From = d; } + void setTo(AST::ChannelEndPointDecl *d ) { m_To = d; } + + AST::ChannelEndPointDecl * getFrom() const { return m_From; } + AST::ChannelEndPointDecl * getTo() const { return m_To; } +}; + +/** + * \brief Channel Declaration + * It' a Named Declaration that Holds a list a signalsDecl . + */ +class ChannelDecl : public NamedDecl , public DeclContext +{ + protected: + ChannelDecl(Kind K,DeclContext *DC,const std::string &DeclName) : DeclContext(), NamedDecl(K,DC,DeclName) + {}; + + public: + + /// Some Static functions... Missing Init Expression and Type should be integer I think + static ChannelDecl *Create(ASTContext &C,AST::DeclContext *DC,const std::string &name) + { + return new ChannelDecl(DeclBase::ChannelDecl,DC,name); + }; + +}; + + +#endif diff --git a/include/AST/DeclPackageUseDecl.h b/include/AST/DeclPackageUseDecl.h new file mode 100644 index 0000000..5ef8e87 --- /dev/null +++ b/include/AST/DeclPackageUseDecl.h @@ -0,0 +1,24 @@ +#ifndef PACKAGEUSEDECL_H__ +#define PACKAGEUSEDECL_H__ + +class PackageUseDecl : public Decl { + std::string m_Name; + protected: + PackageUseDecl(ASTContext &AC,DeclContext *DC,std::string _name) : Decl(DeclBase::PackageUseDecl,DC) + ,m_Name(_name) + { + m_DeclContext = DC; + }; + public: + + static PackageUseDecl * Create(ASTContext &AC,DeclContext *DC,std::string _name) + { + return new PackageUseDecl(AC,DC,_name); + } + /// + void setName(const std::string &s) {m_Name = s ; }; + /// + std::string getName() const {return m_Name; } ; +}; + +#endif diff --git a/include/AST/DeclParmVarDecl.h b/include/AST/DeclParmVarDecl.h new file mode 100644 index 0000000..eeb2fa2 --- /dev/null +++ b/include/AST/DeclParmVarDecl.h @@ -0,0 +1,18 @@ +#ifndef DECLPARMVARDECL_H__ +#define DECLPARMVARDECL_H__ + +class ParmVarDecl : public VarDecl +{ + protected: + ParmVarDecl(Kind K,DeclContext *DC,const std::string &DeclName,Type *T) : VarDecl(K,DC,DeclName,T) {}; + + // ParmVarDecl(DeclContext *DC,const std::string &DeclName) : VarDecl(DeclBase::ParmVarDecl,DC,DeclName) {}; + public: + + /// Some Static functions... + static ParmVarDecl *Create(DeclContext *DC,const std::string &name,Type *T) { + return new ParmVarDecl(DeclBase::ParmVarDecl,DC,name,T); + }; +}; + +#endif diff --git a/include/AST/DeclRecordDecl.h b/include/AST/DeclRecordDecl.h new file mode 100644 index 0000000..911fbe2 --- /dev/null +++ b/include/AST/DeclRecordDecl.h @@ -0,0 +1,54 @@ +#ifndef DECLRECORDDECL_H +#define DECLRECORDDECL_H + + +/** + * \brief represents the declaration of a : + * - variable < in this case it's a lvalue > + * - function < in this case it's the function designator > + * - enum < a constant> + * + * Missing the Type argument. A value has a type + * and something like QualType (plagia of clang) + * + * A Record is either an Union or a Struct type. + * + */ +class RecordDecl : public TypeDecl , public DeclContext +{ + public: + enum RecordType {RT_Struct ,RT_Union}; + + protected: + RecordDecl(Kind K,RecordType _rt,DeclContext *DC,const std::string &DeclName) + : TypeDecl(K,DC,DeclName) + , DeclContext() + , m_RType(_rt) + {}; + RecordType m_RType; + public: + + /// Some Static functions... + static RecordDecl *CreateStruct(DeclContext *DC,const std::string &name) { + return new RecordDecl(DeclBase::RecordDecl,RT_Struct,DC,name); + }; + static RecordDecl *CreateUnion(DeclContext *DC,const std::string &name) { + return new RecordDecl(DeclBase::RecordDecl,RT_Union,DC,name); + }; + + inline bool isStruct() const { return m_RType == RT_Struct ; } + + inline bool isUnion() const { return m_RType == RT_Union; } + // + void Signature(SignatureNodeID &id); + + typedef specific_decl_iterator field_iterator; + + field_iterator field_begin() const; + field_iterator field_end() const; + + bool fields_empty() const { return field_begin() == field_end() ; } +}; + + +#endif /*DECLRECORDDECL_H*/ diff --git a/include/AST/DeclRefStateDecl.h b/include/AST/DeclRefStateDecl.h new file mode 100644 index 0000000..0fe244b --- /dev/null +++ b/include/AST/DeclRefStateDecl.h @@ -0,0 +1,22 @@ +#ifndef DECLREFSTATEDECL_H__ +#define DECLREFSTATEDECL_H__ + +class Decl; +class StateDecl; +/** + * Stores a reference to a Value Declaration + * Somehow, this makes the connection between Declarations and statement expressions + */ +class RefStateDecl : public Decl +{ + AST::StateDecl *m_value; + public: + + RefStateDecl(AST::StateDecl *v ) : Decl(DeclBase::RefStateDecl,NULL) ,m_value(v) {}; + + ~RefStateDecl() {}; + + AST::StateDecl *getDecl() const { return m_value ;}; +}; + +#endif diff --git a/include/AST/DeclStateDecl.h b/include/AST/DeclStateDecl.h new file mode 100644 index 0000000..d5fc5c6 --- /dev/null +++ b/include/AST/DeclStateDecl.h @@ -0,0 +1,22 @@ +#ifndef STATEDECL_H__ +#define STATEDECL_H__ + +/** + * \brief StateDecl The body shall probably contain Transitions + * The events the State Reponds to as well. + * Maybe, this class should inherit from LabelDecl, in order to be able to retrieve the statement + */ +class StateDecl : public NamedDecl, public DeclContext { + protected: + + StateDecl(DeclContext *DC,const std::string &n) : NamedDecl(DeclBase::StateDecl,DC,n) , DeclContext() { + } + + public: + static StateDecl *Create(DeclContext *DC,const std::string &n) {return new StateDecl(DC,n); }; + + protected: + +}; + +#endif diff --git a/include/AST/DeclTransitionDecl.h b/include/AST/DeclTransitionDecl.h new file mode 100644 index 0000000..8a0df84 --- /dev/null +++ b/include/AST/DeclTransitionDecl.h @@ -0,0 +1,66 @@ +#ifndef DECLTRANSITIONDECL_H__ +#define DECLTRANSITIONDECL_H__ + + +class ParmVarDecl; +class EventDecl; +class RefStateDecl; +class StateDecl; +/** + * \brief a transition is owned by a state. + * A transition should react on an event list + * A transition know the default destination state that can be SAME + * I should complete the interface of the TransitionDecl to reflect the statement above. + * + */ +class TransitionDecl : public ValueDecl , public DeclContext { + public: + typedef ::std::vector parameter_array; + typedef std::vector::iterator param_iterator; + typedef std::vector::const_iterator const_param_iterator; + + typedef DeclContext::specific_decl_iterator event_iterator; + + protected: +#define MAX_PARAMETERS 10 + // AST::ParmVarDecl *m_Parameters[MAX_PARAMETERS]; + Stmt *m_Body; + std::vector m_Parameters; + /// Missing parmaters + TransitionDecl (DeclContext *DC,const std::string &n,AST::RefStateDecl *_rf = NULL,Type *T = NULL) : ValueDecl(DeclBase::TransitionDecl,DC,n,T) + , DeclContext() + , m_Body(NULL) + , m_State(_rf) + { + }; + + std::string m_TargetState; + AST::RefStateDecl *m_State; + public: + Stmt *getBody() const { return m_Body; }; + void setBody(Stmt *b) { m_Body = b; }; + /// Some Static functions... + static TransitionDecl *Create(DeclContext *DC,const std::string &name,AST::RefStateDecl *_rs = NULL,Type *T =NULL) { + return new TransitionDecl(DC,name,_rs,T); + }; + + // TargetState on Events + void setTargetState(const std::string &s) { m_TargetState = s; }; + std::string getTargetState() const { return m_TargetState ; }; + inline AST::StateDecl *getState() const { return m_State->getDecl(); }; + // Iterators + unsigned int param_size() const { return m_Parameters.size(); } + param_iterator param_begin() { return m_Parameters.begin(); } + param_iterator param_end() { return m_Parameters.end(); } + + event_iterator events_begin() { return event_iterator(begin()) ; }; + event_iterator events_end() { return event_iterator() ; }; + + + void add_param(AST::ParmVarDecl *p) { m_Parameters.push_back(p); }; + + bool hasDefinition() { return m_Body != NULL; }; + protected: +}; + +#endif diff --git a/include/AST/DeclTranslationUnitDecl.h b/include/AST/DeclTranslationUnitDecl.h new file mode 100644 index 0000000..3cca9b4 --- /dev/null +++ b/include/AST/DeclTranslationUnitDecl.h @@ -0,0 +1,23 @@ +#ifndef DECLTRANSLATIONUNITDECL_H__ +#define DECLTRANSLATIONUNITDECL_H__ + +class ASTContext; + +class TranslationUnitDecl : public Decl , public DeclContext { + + protected: + ASTContext &m_ASTContext; + TranslationUnitDecl(ASTContext &AC,DeclContext *DC) + : Decl(DeclBase::TranslationUnitDecl,DC) ,DeclContext(),m_ASTContext(AC) { + + }; + + public: + static TranslationUnitDecl *Create(ASTContext &AC,DeclContext *DC,const std::string &name) { + return new TranslationUnitDecl(AC,DC); + }; + ASTContext &getASTContext() const { return m_ASTContext;} + +}; + +#endif diff --git a/include/AST/DeclTypeDecl.h b/include/AST/DeclTypeDecl.h new file mode 100644 index 0000000..6d3d374 --- /dev/null +++ b/include/AST/DeclTypeDecl.h @@ -0,0 +1,181 @@ +#ifndef DECLTYPEDECL_H +#define DECLTYPEDECL_H + +class ASTContext; +class EventDecl; + +/** + * TypeDeclaration base class. + */ +class TypeDecl : public NamedDecl +{ + friend class ASTContext; + protected: + TypeDecl(Kind K,DeclContext *DC,const std::string &DeclName) + : NamedDecl(K,DC,DeclName) , m_Init(NULL), m_TypeForDecl(NULL) + {}; + Type *m_TypeForDecl; + Stmt *m_Init; // Init Expression for global variables and so on + public: + /// + void setInit(Expr *e) + { m_Init = e; } ; + /// + Expr *getInit(Expr *e) + { return dynamic_cast(m_Init); }; + + /// + Type *getTypeForDecl() const { return m_TypeForDecl; }; + /// + void setTypeForDecl(Type *T) { m_TypeForDecl = T; }; +} ; + +/** + * Typedef acutally for LDS it's more something like syntype + */ +class TypedefDecl : public TypeDecl +{ + protected: + TypedefDecl(DeclContext *DC,const std::string _n) + : TypeDecl(DeclBase::TypedefDecl,DC,_n ) + , m_Constraint(NULL) + , m_BaseType(NULL) + {} + Type *m_BaseType; + Stmt *m_Constraint; // Init Expression for global variables and so on + public: + static TypedefDecl *Create(ASTContext &AC,DeclContext *DC,const std::string &_name) + { + return new TypedefDecl(DC,_name); + } + bool hasConstraint() const { return m_Constraint != NULL; } + void setConstraint(Stmt *s) { m_Constraint = s ; }; + + void setBaseType(AST::Type *bt) { m_BaseType = bt; }; + AST::Type *getBaseType() const { return m_BaseType ; }; + + Expr *getContraint() + { return dynamic_cast(m_Init); }; + /// Missing function to get Canonical Type + + Type *getCanonicalType() const { return NULL; }; +}; + +/** + * LDS it's more something like datatype definition + * constructed + * or + */ +class ValueTypeDecl : public TypeDecl , public DeclContext +{ + protected: + ValueTypeDecl(DeclContext *DC,const std::string _n) + : TypeDecl(DeclBase::ValueTypeDecl,DC,_n ) + , DeclContext() + , m_Specialization(NULL) + {} + + Stmt *m_Init; // Init Expression for global variables and so on + Type *m_Specialization; // + public: + static ValueTypeDecl *Create(ASTContext &AC,DeclContext *DC,const std::string &_name) + { + return new ValueTypeDecl(DC,_name); + } + /// Some test functions + bool isStruct() const ; + + bool isUnion() const ; + + bool isEnum() const ; + + bool isArray() const ; + + void setSpecialization(Type *_t) { m_Specialization = _t ; } ; + /// Missing function to get Canonical Type +}; + +/** + * Enum acutally for LDS it's more something like synon + */ +class EnumDecl : public TypeDecl , public DeclContext +{ + protected: + EnumDecl(DeclContext *DC,const std::string &_n) : TypeDecl(DeclBase::EnumDecl,DC,_n ) , DeclContext() {} + public: + static EnumDecl *Create(ASTContext &AC,DeclContext *DC,const std::string &_name) + { + return new EnumDecl(DC,_name); + } + /// Missing function to get Canonical Type +}; + + +/** + * + */ +class AgentTypeDecl : public TypeDecl , public DeclContext +{ + protected: + AgentTypeDecl(Kind K,DeclContext *DC,const std::string &_n) : TypeDecl(K,DC,_n ) , DeclContext() {} + public: + typedef specific_decl_iterator event_iterator; + /// Missing function Like isAbstract if Parameterized Agent + public: + + event_iterator events_begin() { return event_iterator(begin()) ; }; + event_iterator events_end() { return event_iterator() ; }; + +}; + +/** + * An AutomatonType is a class that implementes the behavior of the automaton. + * An AutomatonDecl is an instance of an automatonTypeDecl. + */ +class AutomatonTypeDecl : public AgentTypeDecl +{ + protected: + AutomatonTypeDecl(DeclContext *DC,const std::string &_n) : AgentTypeDecl(DeclBase::AutomatonTypeDecl,DC,_n ) {} + public: + static AutomatonTypeDecl *Create(ASTContext &AC,DeclContext *DC,const std::string &_name) + { + return new AutomatonTypeDecl(DC,_name); + } +}; + +/** + * + * + */ +class BlockTypeDecl : public AgentTypeDecl +{ + protected: + BlockTypeDecl(DeclContext *DC,const std::string &_n) : AgentTypeDecl(DeclBase::BlockTypeDecl,DC,_n ) {} + public: + static BlockTypeDecl *Create(ASTContext &AC,DeclContext *DC,const std::string &_name) + { + return new BlockTypeDecl(DC,_name); + } + /// Missing function to +}; + +/** + * A System Type is the toplevel type description of a system. + * + */ +class SystemTypeDecl : public AgentTypeDecl +{ + protected: + SystemTypeDecl(DeclContext *DC,const std::string &_n) : AgentTypeDecl(DeclBase::SystemTypeDecl,DC,_n ) {} + public: + static SystemTypeDecl *Create(ASTContext &AC,DeclContext *DC,const std::string &_name) + { + return new SystemTypeDecl(DC,_name); + } +}; + +/* + * vim: et sw=2 ts=2 list: + */ + +#endif diff --git a/include/AST/DeclValueDecl.h b/include/AST/DeclValueDecl.h new file mode 100644 index 0000000..8a2ffb4 --- /dev/null +++ b/include/AST/DeclValueDecl.h @@ -0,0 +1,78 @@ +#ifndef DECLVALUEDECL_H__ +#define DECLVALUEDECL_H__ +/** + * \brief represents the declaration of a : + * - variable < in this case it's a lvalue > + * - function < in this case it's the function designator > + * - enum < a constant> + * + * Missing the Type argument. A value has a type + */ +class ValueDecl : public NamedDecl +{ + protected: + Type *m_Type; + ValueDecl(Kind K,DeclContext *DC,const std::string &DeclName, Type *T) : NamedDecl(K,DC,DeclName),m_Type(T) {}; + + public: + + /// Some Static functions... + static ValueDecl *Create(DeclContext *DC,const std::string &name,Type *T) { + return new ValueDecl(DeclBase::ValueDecl,DC,name,T); + }; + + Type *getType() const { return m_Type;} + +}; + +/** + * \brief Constants declared in an enum are of type EnumConstantDecl + * It' a value. + */ +class EnumConstantDecl : public ValueDecl +{ + protected: + Expr *m_InitExpr; + EnumConstantDecl(Kind K,DeclContext *DC,const std::string &DeclName, Type *T) : ValueDecl(K,DC,DeclName,T) + , m_InitExpr(NULL) + {}; + + public: + + /// Some Static functions... Missing Init Expression and Type should be integer I think + static EnumConstantDecl *Create(ASTContext &C,AST::EnumDecl *DC,const std::string &name,Type *T = NULL) { + return new EnumConstantDecl(DeclBase::EnumConstantDecl,DC,name,T); + }; + + void setInitExpr(Expr *e) { m_InitExpr =e ; } +}; + + +/** + * \brief Timer Declaration + * It' a value. + */ +class TimerDecl : public ValueDecl +{ + protected: + Expr *m_InitExpr; + TimerDecl(Kind K,DeclContext *DC,const std::string &DeclName, Type *T) : ValueDecl(K,DC,DeclName,T) + , m_InitExpr(NULL) + {}; + + public: + + /// Some Static functions... Missing Init Expression and Type should be integer I think + static TimerDecl *Create(ASTContext &C,AST::DeclContext *DC,const std::string &name,Type *T = NULL) { + return new TimerDecl(DeclBase::TimerDecl,DC,name,T); + }; + + void setInitExpr(Expr *e) { m_InitExpr =e ; } +}; + + + +/* + * vim: et sw=2 ts=2 list: + */ +#endif diff --git a/include/AST/DeclVarDecl.h b/include/AST/DeclVarDecl.h new file mode 100644 index 0000000..db5d67f --- /dev/null +++ b/include/AST/DeclVarDecl.h @@ -0,0 +1,40 @@ +#ifndef DECLVARDECL_H__ +#define DECLVARDECL_H__ + +/** + * TODO: Complete the class so that the type will be associated + * with the variable. + */ +class VarDecl : public ValueDecl +{ + protected: + VarDecl(Kind K,DeclContext *DC,const std::string &DeclName,Type *T,Stmt *_init = NULL) + : m_Init(_init), ValueDecl(K,DC,DeclName,T) , m_Constant(false) { + }; + //VarDecl(DeclContext *DC,const std::string &DeclName) : ValueDecl(DeclBase::VarDecl,DC,DeclName) {}; + Stmt *m_Init; // Init Expression for global variables and so on + bool m_Constant; + public: + + /// Some Static functions... + static VarDecl *Create(DeclContext *DC,const std::string &name,Type *T,Stmt *_init = NULL) { + return new VarDecl(DeclBase::VarDecl,DC,name,T,_init); + }; + /** */ + inline bool isConstant() const { return m_Constant; } + /// + bool hasInit() const + { return m_Init != NULL; }; + /// + inline void setConstant(bool _flag) { m_Constant = _flag; }; + /// + void setInit(Expr *e) + { m_Init = e; } ; + /// + Expr *getInit(Expr *e) + { return dynamic_cast(m_Init); }; +}; +/* + * vim: et sw=2 ts=2 list: + */ +#endif diff --git a/include/AST/Expr.h b/include/AST/Expr.h new file mode 100644 index 0000000..bb47fe9 --- /dev/null +++ b/include/AST/Expr.h @@ -0,0 +1,223 @@ +#ifndef EXPR_H__ +#define EXPR_H__ + +#include "OperationKinds.h" +#include "Type.h" +namespace AST { + +class ASTContext; +class ValueDecl; +/** + * An expression has a type. + * An expression can be evaluated or not. + * An expression can be a constant result. The result be be evaluated. + * The state of the evaluation must be kept (avoid to evaluate the same expression several times). + * + * I should be able to check if the expression is an (enum VK_...) RValue or LValue + * + */ +class Expr : public Stmt { + protected: + Type *m_Type; + public: + Expr(StmtClass SC,Type *_t = NULL) : Stmt(SC) , m_Type(_t) {}; + virtual ~Expr() {}; + /** + * Result + */ + struct EvalResult { + union { + long l; + bool b; + }u; + bool m_Error; // Error during evaluation + }; + + inline void setType( Type *t) { m_Type = t; }; + + inline Type *getType( ) { return m_Type ; }; + + /** + * May be set this function virtual. It might need more + * memory + */ + bool evalute(EvalResult &result) ; + /** + * evaluate constant expression should exist too + */ + + /** */ + bool isConstantExpression(); +}; + + +/** + * Expresssion that reflects an expression in parentheses. + * + */ +class ParenExpr : public Expr { + Stmt *m_Stmt; + + public: + ParenExpr(Stmt *s) : Expr(ParenExprClass) , m_Stmt(s) { + } + + Stmt *getStmt() const { return m_Stmt; }; +}; + +/** + * Expresssion that reflects a list of expression in parentheses. + * + */ +class ParenListExpr : public Expr { + enum { MAX = 10 }; + Stmt *m_Stmts[MAX]; + int m_NbExprs; + public: + ParenListExpr() ; + + void addExpr(Expr *e) { + if (m_NbExprs < MAX && e) + m_Stmts[m_NbExprs++] = e; + }; + + int getNumExprs() {return m_NbExprs; }; + + Expr *getExpr(int idx) { + return dynamic_cast(m_Stmts[idx]); + } + + Expr** getExprs() { + return reinterpret_cast(m_Stmts); + } + + virtual range_iterator children() ; + +}; + +/** + * Expresssion that reflects + * a structure or record member access. + * M.x M is base and x mem + */ +class MemberExpr : public Expr { + Stmt *m_Base; + ValueDecl *m_Member; + protected: + /** + * + * Misssing Value Kind which LValue or RValue + */ + MemberExpr(Expr *base,ValueDecl *mem,Type *Ty) ; + + public: + + static MemberExpr *Create(ASTContext &AC,Expr *base,ValueDecl *_member,Type *Ty); + + Expr* getBase() const + { + return reinterpret_cast(m_Base); + } + + ValueDecl *getMember() const + { + return (m_Member); + } +}; + + +/** + * LdsThis represents this is LDS record operators. + * + */ +class LdsThisExpr : public Expr { + public: + LdsThisExpr(Type *Ty) : Expr(LdsThisExprClass,Ty) + { + } + +}; + + +/** + * We need an expression to store array Subcription Eg A[4] for instance + */ +class ArraySubscriptExpr : public Expr { + Expr *m_Base; + Expr *m_Index; + protected: + /** + * + * Misssing Value Kind which LValue or RValue + */ + ArraySubscriptExpr(Expr *base,Expr *idx,Type *Ty) ; + + public: + + static ArraySubscriptExpr *Create(ASTContext &AC,Expr *base,Expr *_idx,Type *Ty); + + Expr* getBase() const + { + return reinterpret_cast(m_Base); + } + + Expr *getIndex() const + { + return (m_Index); + } +}; + + +/** + * CREATE expression for an Agent + * This shall be Pid + * + */ +class CreateExpr : public Expr { + Expr *m_Agent; + public: + CreateExpr(Expr *agent,Type *Ty) : m_Agent(agent), Expr(CreateExprClass,Ty) + { + } + + Expr *getAgent() const { return m_Agent; }; +}; + +/** + * CREATE expression for an Agent + * This shall be Pid + * + */ +class PidExpr : public Expr { + Expr *m_Agent; + public: + enum Pid { + Self + , OffSpring + , Parent + , Sender + , Referenced /* User Identified Pid*/ + }; + + PidExpr(Pid p,Expr *agent,Type *Ty) : m_PidKind(p) , m_Agent(agent), Expr(PidExprClass,Ty) + { + } + + Pid getKind() const { return m_PidKind; }; + + Expr *getAgent() const { return m_Agent; }; + protected: + Pid m_PidKind; +}; + + +#include "ExprIntegerLiteral.h" +#include "ExprDeclRefExpr.h" +#include "ExprCallExpr.h" +// Missing Member Expression example : X.y or X->y +#include "ExprStringLiteral.h" +#include "ExprFloatLiteral.h" +#include "ExprBinaryOperatorExpr.h" +#include "ExprConditionalOperator.h" +} +#endif diff --git a/include/AST/ExprBinaryOperatorExpr.h b/include/AST/ExprBinaryOperatorExpr.h new file mode 100644 index 0000000..6c1fa84 --- /dev/null +++ b/include/AST/ExprBinaryOperatorExpr.h @@ -0,0 +1,54 @@ +#ifndef BINARYOPERATION_H__ +#define BINARYOPERATION_H__ + +class BinaryOperator : public Expr { + + public: + typedef BinaryOperatorKind OpCode; + protected: + + enum {LHS,RHS,END_EXPR}; + Stmt *SubExprs[END_EXPR]; + + OpCode m_OpCode; + public: + BinaryOperator(Expr *lhs,Expr *rhs,OpCode op) : Expr(Stmt::BinaryOperatorClass), m_OpCode(op) { + SubExprs[LHS] = lhs; + SubExprs[RHS] = rhs; + } + + Expr *getLHS() const {return dynamic_cast(SubExprs[LHS]);} + + Expr *getRHS() const {return dynamic_cast(SubExprs[RHS]);} + + OpCode getOpcode() const {return m_OpCode;}; + + const char * getOpcodeStr() const; +}; + +/** + * + * + */ +class UnaryOperator : public Expr { + public: + typedef UnaryOperatorKind OpCode; + protected: + enum {RHS,END_EXPR}; + Stmt *SubExprs[END_EXPR]; + + OpCode m_OpCode; + public: + UnaryOperator(Expr *rhs,OpCode op) : Expr(Stmt::UnaryOperatorClass),m_OpCode(op) { + SubExprs[RHS] = rhs; + } + + Expr *getSubExpr() const {return dynamic_cast(SubExprs[RHS]);} + + OpCode getOpcode() const {return m_OpCode;}; +}; + +/** + :vim:et:sw=4:ts=4 + */ +#endif diff --git a/include/AST/ExprCallExpr.h b/include/AST/ExprCallExpr.h new file mode 100644 index 0000000..5b40b6a --- /dev/null +++ b/include/AST/ExprCallExpr.h @@ -0,0 +1,53 @@ +#ifndef CALLEXPR_H__ +#define CALLEXPR_H__ + + +/** + * Is there a type associated to a class expression ? + * maybe the result of the call. + */ +class CallExpr : public Expr +{ + enum {MAX_ARGS = 20} ; + enum {FN,ARGS}; + Stmt *m_Args[MAX_ARGS]; + int m_NumArgs; + public: + /** + * fn should be a DeclRefExpr. A reference to the function Declation. + * The declared function can be undefined, referenced and so on. + */ + CallExpr(const DeclContext *ctx,Expr *fn,std::vector args); + + CallExpr(const DeclContext *DC,Expr *fn) : Expr(CallExprClass) , m_NumArgs(0) { + m_Args[FN] = fn; + m_Args[1] = NULL; + } + ~CallExpr() {}; + + int getNumArgs() {return m_NumArgs; }; + + Expr *getCallee( ) { return dynamic_cast(m_Args[FN]); } ; + + FunctionDecl *getCalleeDecl() const ; + + Expr *getArg(unsigned i) + { + return static_cast(m_Args[i +1]); + } + const Expr *getArg(unsigned i) const + { + return static_cast(m_Args[i +1]); + } + range_iterator arguments() + { + return range_iterator(&m_Args[1],&m_Args[getNumArgs()+1]); + } + + range_iterator children() { + return range_iterator(&m_Args[1],&m_Args[getNumArgs()+1]); + } + protected: +}; + +#endif diff --git a/include/AST/ExprConditionalOperator.h b/include/AST/ExprConditionalOperator.h new file mode 100644 index 0000000..403aac1 --- /dev/null +++ b/include/AST/ExprConditionalOperator.h @@ -0,0 +1,8 @@ +#ifndef CONDITIONALOPERATOR_H__ +#define CONDITIONALOPERATOR_H__ + +class ConditionalOperator : public Expr +{ +}; + +#endif diff --git a/include/AST/ExprDeclRefExpr.h b/include/AST/ExprDeclRefExpr.h new file mode 100644 index 0000000..2ebb267 --- /dev/null +++ b/include/AST/ExprDeclRefExpr.h @@ -0,0 +1,29 @@ +#ifndef DECLREFEXPR_H__ +#define DECLREFEXPR_H__ + +class Decl; +class ValueDecl; +class FunctionDecl; +class VarDecl; +/** + * Stores a reference to a Value Declaration + * Somehow, this makes the connection between Declarations and statement expressions + */ +class DeclRefExpr : public Expr +{ + ValueDecl *m_value; + public: + DeclRefExpr(ValueDecl *v ) : Expr(Stmt::DeclRefExprClass) ,m_value(v) {}; + ~DeclRefExpr() {}; + /// Return The reference declaration + AST::Decl *getDecl() const ; + /// + bool isRefFunctionDecl() const ; + + bool isRefVarDecl() const ; + + bool isRefParmVarDecl() const ; + +}; + +#endif diff --git a/include/AST/ExprFloatLiteral.h b/include/AST/ExprFloatLiteral.h new file mode 100644 index 0000000..f1ee61e --- /dev/null +++ b/include/AST/ExprFloatLiteral.h @@ -0,0 +1,7 @@ +#ifndef FLOATLITERALEXPR_H__ +#define FLOATLITERALEXPR_H__ + +class FloatLiteral : public Expr { +}; + +#endif diff --git a/include/AST/ExprIntegerLiteral.h b/include/AST/ExprIntegerLiteral.h new file mode 100644 index 0000000..6ac26ff --- /dev/null +++ b/include/AST/ExprIntegerLiteral.h @@ -0,0 +1,20 @@ +#ifndef INTEGERLITERAL_H__ +#define INTEGERLITERAL_H__ + +class IntegerLiteral : public Expr { + public: + IntegerLiteral(StmtClass SC,unsigned int value) : Expr(SC) ,m_value(value) { + } + IntegerLiteral(unsigned int value,Type *_t = NULL) : Expr(IntegerLiteralClass,_t) ,m_value(value) { + } + + /** + * In term should return an APValue or Value type + */ + unsigned int get_value() const { return m_value; }; + + protected: + unsigned int m_value; +}; + +#endif diff --git a/include/AST/ExprStringLiteral.h b/include/AST/ExprStringLiteral.h new file mode 100644 index 0000000..f8dad6f --- /dev/null +++ b/include/AST/ExprStringLiteral.h @@ -0,0 +1,23 @@ +#ifndef STRINGLITERALEXPR_H__ +#define STRINGLITERALEXPR_H__ + +/** + * This is a constant array of characters + * As long as operand5 makes conversions of StringLiterals into + * call expressions, I will use the isConstantArray Flag + */ +class StringLiteral : public Expr +{ + std::string m_string; + public: + bool isConstantArray; + StringLiteral(const std::string &s,Type *_t) + : isConstantArray(false), Expr(StringLiteralClass,_t),m_string(s) { + } + + std::string getString() const {return m_string; } ; + + void print(std::ostream &os) { os<() const; + // Comparison + bool operator ==(const ExprIterator &R) { return I == R.I; } ; + bool operator !=(const ExprIterator &R) { return I != R.I; } ; + bool operator >(const ExprIterator &R) { return I > R.I; } ; + bool operator >=(const ExprIterator &R) { return I >= R.I; } ; +}; + +/** + * + */ +class Stmt { + public: + enum StmtClass { + NoStmtClass = 0 +#define STMT(CLASS,PARENT) , CLASS##Class +#include "AST/Stmt.h.inc" +#undef STMT + }; + + typedef StmtIterator child_iterator; + typedef StmtRange range_iterator; + public: + Stmt(StmtClass SC) : m_StmtClass(SC) {}; + virtual ~Stmt() {}; + + StmtClass getStmtClass() const { return m_StmtClass;}; + + virtual range_iterator children() {return range_iterator();} + + child_iterator child_begin() {return children().first; } + + child_iterator child_end() {return children().second; } + + protected: + StmtClass m_StmtClass; +}; + +#include "StmtCompoundStmt.h" +#include "StmtSwitchCaseStmt.h" +#include "StmtBreakStmt.h" +#include "StmtReturnStmt.h" +#include "StmtDeclStmt.h" +#include "StmtLabelStmt.h" +#include "StmtGotoStmt.h" +#include "StmtForStmt.h" +#include "StmtWhileStmt.h" +#include "StmtSwitchStmt.h" +#include "StmtIfStmt.h" +#include "StmtAsmStmt.h" +#include "StmtOutputStmt.h" +} +#endif diff --git a/include/AST/Stmt.h.inc b/include/AST/Stmt.h.inc new file mode 100644 index 0000000..cd3a0ee --- /dev/null +++ b/include/AST/Stmt.h.inc @@ -0,0 +1,40 @@ +#ifndef STMT +# define STMT(Type,Base) +#endif + +STMT(SwitchCaseStmt,Stmt) +STMT(BreakStmt,Stmt) +STMT(ReturnStmt,Stmt) +STMT(DeclStmt,Stmt) +STMT(LabelStmt,Stmt) +STMT(GotoStmt,Stmt) +STMT(ForStmt,Stmt) +STMT(WhileStmt,Stmt) +STMT(SwitchStmt,Stmt) +STMT(IfStmt,Stmt) +STMT(OutputStmt,Stmt) +STMT(AsmStmt,Stmt) +STMT(LdsAsmStmt,AsmStmt) +STMT(CompoundStmt,Stmt) + +STMT(Expr,Stmt) +#ifndef EXPR +# define EXPR(Type,Base) STMT(Type,Base) +#endif + +EXPR(ParenExpr,Expr) +EXPR(ParenListExpr,Expr) +EXPR(CallExpr,Expr) +EXPR(DeclRefExpr,Expr) +EXPR(MemberExpr,Expr) +EXPR(ArraySubscriptExpr,Expr) +EXPR(LdsThisExpr,Expr) +EXPR(CreateExpr,Expr) +EXPR(PidExpr,Expr) +EXPR(StringLiteral,Expr) +EXPR(IntegerLiteral,Expr) +EXPR(FloatLiteral,Expr) +EXPR(BinaryOperator,Expr) +EXPR(UnaryOperator,Expr) +EXPR(ConditionalOperator,Expr) +#undef STMT diff --git a/include/AST/StmtAsmStmt.h b/include/AST/StmtAsmStmt.h new file mode 100644 index 0000000..5cae5dc --- /dev/null +++ b/include/AST/StmtAsmStmt.h @@ -0,0 +1,64 @@ +#ifndef ASMSTMT_H__ +#define ASMSTMT_H__ + +class StringLiteral ; +class TimerDecl; +class VarDecl; +/** + * + */ +class AsmStmt : public Stmt { + + enum {LIT,EXPR,END} ; + + Stmt *m_Stmts[END]; + std::string m_Op; + public: + AsmStmt(DeclContext *DC,StmtClass KD,const std::string &op) ; + + StringLiteral *getLiteral() const ; + + VarDecl *getVarDecl() const; + + TimerDecl *getTimerDecl() const; + + void setLiteral(Expr *S) ; + /* For set timer. time expression to be evaluated */ + void setExpr(Expr *S) ; + + /// For SET and RESET Statements + bool isArgVariable() const; + + bool isArgTimer() const; +}; + + +/* + * Possible ASM opcodes in lds language .... + * AEL_RETURN + * AEL_RESET FLG + * AEL_SET FLG + * AEL_JSR_IND FLG + */ +class LdsAsmStmt : public AsmStmt { + + public: + enum LdsAslOpcodes { + AEL_RETURN + ,AEL_NOP + ,AEL_LOOP_MSG + ,AEL_RESET + ,AEL_SET + ,AEL_JSR_IND + ,AEL_RTS + }; + protected: + long m_Opcode; + public: + + LdsAsmStmt(DeclContext *DC,const std::string &op ); + + long getOpcode() const { return m_Opcode ; }; +}; + +#endif diff --git a/include/AST/StmtBreakStmt.h b/include/AST/StmtBreakStmt.h new file mode 100644 index 0000000..e166223 --- /dev/null +++ b/include/AST/StmtBreakStmt.h @@ -0,0 +1,18 @@ +#ifndef BREAKSTMT_H__ +#define BREAKSTMT_H__ + +/** + * + */ +class BreakStmt : public Stmt +{ + Stmt *m_Cond; + + public: + BreakStmt(DeclContext *DC,Expr *cond); + + Expr *getCond(); + +}; + +#endif diff --git a/include/AST/StmtCompoundStmt.h b/include/AST/StmtCompoundStmt.h new file mode 100644 index 0000000..6faab55 --- /dev/null +++ b/include/AST/StmtCompoundStmt.h @@ -0,0 +1,31 @@ +#ifndef COMPOUNDSTMT_H__ +#define COMPOUNDSTMT_H__ + +/** + * \brief This class contains a list og Statement. {Stmt Stmt ....} + * Can represent a Block + */ +class CompoundStmt : public Stmt +{ + public: + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + public: + + + CompoundStmt() : Stmt(Stmt::CompoundStmtClass) {} + /// + void addStmt(Stmt *_s) { m_Stmts.push_back(_s); } ; + /// + iterator begin() {return m_Stmts.begin();}; + /// + const_iterator begin() const {return m_Stmts.begin();}; + /// + iterator end() {return m_Stmts.end();}; + /// + const_iterator end() const {return m_Stmts.end();}; + protected: + + std::vector m_Stmts; +}; +#endif diff --git a/include/AST/StmtDeclStmt.h b/include/AST/StmtDeclStmt.h new file mode 100644 index 0000000..676e750 --- /dev/null +++ b/include/AST/StmtDeclStmt.h @@ -0,0 +1,12 @@ +#ifndef DECLSTMT_H__ +#define DECLSTMT_H__ + +class DeclStmt : public Stmt { + protected: + + public: + + +}; + +#endif diff --git a/include/AST/StmtForStmt.h b/include/AST/StmtForStmt.h new file mode 100644 index 0000000..4e33291 --- /dev/null +++ b/include/AST/StmtForStmt.h @@ -0,0 +1,7 @@ +#ifndef FORSTMT_H__ +#define FORSTMT_H__ + +class ForStmt : public Stmt { +}; + +#endif diff --git a/include/AST/StmtGotoStmt.h b/include/AST/StmtGotoStmt.h new file mode 100644 index 0000000..96476f4 --- /dev/null +++ b/include/AST/StmtGotoStmt.h @@ -0,0 +1,15 @@ +#ifndef GOTOSTMT_H__ +#define GOTOSTMT_H__ + +class GotoStmt : public Stmt { + LabelDecl *m_Label; + + public: + GotoStmt(LabelDecl *_l) : Stmt(Stmt::GotoStmtClass) , m_Label(_l) { + } + LabelDecl *getLabel() const {return m_Label;}; + + void setLabel(LabelDecl *_l) {m_Label = _l;}; +}; + +#endif diff --git a/include/AST/StmtIfStmt.h b/include/AST/StmtIfStmt.h new file mode 100644 index 0000000..2236640 --- /dev/null +++ b/include/AST/StmtIfStmt.h @@ -0,0 +1,22 @@ +#ifndef IFSTMT_H__ +#define IFSTMT_H__ + + +class IfStmt : public Stmt { + enum {COND,THEN,ELSE,END} ; + Stmt *m_Stmts[END]; + public: + IfStmt(DeclContext *DC,Expr *cond,Stmt *_then,Stmt *_else = NULL) ; + + range_iterator children() ; + + Expr *getCond() const ; + + Stmt *getThen() const { return m_Stmts[THEN]; }; + + Stmt *getElse() const { return m_Stmts[ELSE]; }; + + void setElse(Stmt *s) { m_Stmts[ELSE] = s;}; +}; + +#endif diff --git a/include/AST/StmtIterator.h b/include/AST/StmtIterator.h new file mode 100644 index 0000000..b2d5641 --- /dev/null +++ b/include/AST/StmtIterator.h @@ -0,0 +1,149 @@ +#ifndef STMTITERATOR_H__ +#define STMTITERATOR_H__ +#include +#include +#include + + +namespace AST { + +class Stmt; +/** + * + * + */ +template +class StmtIteratorImpl : public std::iterator +{ + protected: + Stmt **m_Stmt; + public: + StmtIteratorImpl() : m_Stmt(NULL) {} + + StmtIteratorImpl(Stmt **s) : m_Stmt(s) {} + + Derived &operator ++() { + ++m_Stmt; + return static_cast(*this); + } + + Derived operator ++(int) { + Derived tmp = static_cast(*this); + ++m_Stmt; + return tmp; + } + + bool operator ==(const Derived &RHS) const { + return m_Stmt == RHS.m_Stmt; + } + + bool operator !=(const Derived &RHS) const { + return m_Stmt != RHS.m_Stmt; + } + + Reference operator *() const { return *m_Stmt; }; + Reference operator ->() const { return operator *(); }; +}; + + +/** + * + * + */ +struct StmtIterator : public StmtIteratorImpl +{ + explicit StmtIterator() : StmtIteratorImpl() {} + + StmtIterator(Stmt **s) : StmtIteratorImpl(s) {} +}; + + +struct ConstStmtIterator : public StmtIteratorImpl +{ + explicit ConstStmtIterator() : StmtIteratorImpl() {} + + ConstStmtIterator(Stmt **s) : StmtIteratorImpl(s) {} +}; + +/** + * + * + */ +struct StmtRange : std::pair { + + public: + StmtRange() {} + StmtRange(const StmtIterator &begin,const StmtIterator &end) : + std::pair(begin,end) {}; + + bool empty() const { return first == second ; } + + Stmt *operator->() const { return first.operator->();} + + Stmt *&operator*() const { return first.operator*();} + + StmtRange &operator++() { + assert(!empty()); + ++first; + return *this; + } + StmtRange operator++(int) { + assert(!empty()); + StmtRange copy = *this; + ++first; + return copy; + } + + friend const StmtIterator &begin(const StmtRange &range) { + return range.first; + } + + friend const StmtIterator &end(const StmtRange &range) { + return range.second; + } +}; + + +/** + * + * + */ +struct ConstStmtRange : std::pair { + + public: + ConstStmtRange() {} + ConstStmtRange(const ConstStmtIterator &begin,const ConstStmtIterator &end) : + std::pair(begin,end) {}; + + bool empty() const { return first == second ; } + + Stmt *operator->() const { return first.operator->();} + + Stmt *operator*() const { return first.operator*();} + + ConstStmtRange &operator++() { + assert(!empty()); + ++first; + return *this; + } + ConstStmtRange operator++(int) { + assert(!empty()); + ConstStmtRange copy = *this; + ++first; + return copy; + } + + friend const ConstStmtIterator &begin(const ConstStmtRange &range) { + return range.first; + } + + friend const ConstStmtIterator &end(const ConstStmtRange &range) { + return range.second; + } +}; + + + +} +#endif diff --git a/include/AST/StmtLabelStmt.h b/include/AST/StmtLabelStmt.h new file mode 100644 index 0000000..d706378 --- /dev/null +++ b/include/AST/StmtLabelStmt.h @@ -0,0 +1,8 @@ +#ifndef LABELSTMT_H__ +#define LABELSTMT_H__ + + +class LabelStmt : public Stmt { +}; + +#endif diff --git a/include/AST/StmtNullStmt.h b/include/AST/StmtNullStmt.h new file mode 100644 index 0000000..e69de29 diff --git a/include/AST/StmtOutputStmt.h b/include/AST/StmtOutputStmt.h new file mode 100644 index 0000000..032cca6 --- /dev/null +++ b/include/AST/StmtOutputStmt.h @@ -0,0 +1,56 @@ +#ifndef STMTOUTPUT_H_ +#define STMTOUTPUT_H_ + + +class StringLiteral ; +class TimerDecl; +class VarDecl; +class EventDecl; +class DeclRefExpr; + +/** + * An output Statment sends a signal to a destination. + * The destination is a Pid expression0, agent or channel + * A signal can have parameters + * Buy default signals are sent to THIS + */ +class OutputStmt : public Stmt { + + enum { SIG,DEST,END} ; + enum { MAX_ARGS = 20} ; + Stmt *m_Args[MAX_ARGS]; + int m_NumArgs; + public: + + Stmt *m_Stmts[END]; + std::string m_Op; + public: + /* Sig should be a DeclRefExpr */ + OutputStmt(DeclContext *DC,const std::string &op,DeclRefExpr *sig,Expr *dest) ; + + inline int getNumArgs() const { return m_NumArgs ; }; + + void setArgs(std::vector &_args); + + EventDecl *getEventDecl() const ; + + void setDestination(Expr *dest); + + Expr *getArg(unsigned i); + + const Expr *getArg(unsigned i) const ; + + range_iterator arguments() + { + return range_iterator(&m_Args[0],&m_Args[getNumArgs()]); + } + + range_iterator children() { + return range_iterator(&m_Args[0],&m_Args[getNumArgs()]); + } +}; + +/** + * vim: et sw=2 ts=2 list: + */ +#endif diff --git a/include/AST/StmtReturnStmt.h b/include/AST/StmtReturnStmt.h new file mode 100644 index 0000000..77c1281 --- /dev/null +++ b/include/AST/StmtReturnStmt.h @@ -0,0 +1,17 @@ +#ifndef RETURNSTMT_H__ +#define RETURNSTMT_H__ + + +class ReturnStmt : public Stmt { + Stmt *m_RetExpr; + bool m_Indirect; + public: + ReturnStmt(Expr *RetVal,bool ind = false) : Stmt(ReturnStmtClass) , m_RetExpr((Stmt *)RetVal) ,m_Indirect(ind) { + } + + // If the function was reach through an indirect JUMP, this flag shoud be set to TRUE + bool getIndirect() const { return m_Indirect; }; + +}; + +#endif diff --git a/include/AST/StmtSwitchCaseStmt.h b/include/AST/StmtSwitchCaseStmt.h new file mode 100644 index 0000000..9288da5 --- /dev/null +++ b/include/AST/StmtSwitchCaseStmt.h @@ -0,0 +1,20 @@ +#ifndef SWITCHCASESTMT_H__ +#define SWITCHCASESTMT_H__ + +class SwitchCaseStmt : public Stmt { + Stmt *m_SubStmt; + Expr *m_Cond; + public: + + SwitchCaseStmt(Expr *_cond,Stmt *stmt) : Stmt(Stmt::SwitchCaseStmtClass) , m_Cond(_cond) , m_SubStmt(stmt) { + }; + + + + Stmt *getSubStmt() const { return m_SubStmt; }; + + Expr *getCond() const { return m_Cond; }; + /* Iterator access */ +}; + +#endif diff --git a/include/AST/StmtSwitchStmt.h b/include/AST/StmtSwitchStmt.h new file mode 100644 index 0000000..25d2706 --- /dev/null +++ b/include/AST/StmtSwitchStmt.h @@ -0,0 +1,31 @@ +#ifndef SWITCHSTMT_H__ +#define SWITCHSTMT_H__ + + + +class SwitchStmt : public Stmt { + std::vector m_CaseStmts; + Expr *m_Cond; + public: + typedef std::vector::iterator case_iterator; + typedef std::vector::const_iterator const_case_iterator; + + SwitchStmt(Expr *_cond) : Stmt(Stmt::SwitchStmtClass) , m_Cond(_cond) { + }; + + size_t NbCases() const { return m_CaseStmts.size(); }; + + void addCaseStmt(Stmt *_s) { m_CaseStmts.push_back(_s); }; + + Stmt *getStmt(int i) const { return m_CaseStmts[i]; }; + + Expr *getCond() const { return m_Cond; }; + /* Iterator access */ + case_iterator case_begin() { return m_CaseStmts.begin() ; }; + case_iterator case_end() { return m_CaseStmts.end() ; }; + + const_case_iterator case_begin() const { return m_CaseStmts.begin() ; }; + const_case_iterator case_end() const { return m_CaseStmts.end() ; }; +}; + +#endif diff --git a/include/AST/StmtVisitor.h b/include/AST/StmtVisitor.h new file mode 100644 index 0000000..26408c2 --- /dev/null +++ b/include/AST/StmtVisitor.h @@ -0,0 +1,136 @@ +#ifndef STMTVISITOR_H__ +#define STMTVISITOR_H__ + +/** + * Got the example for clang AST. I really like there way of doing things + */ + +namespace AST { + +template +class StmtVisitorBase { + public: + StmtVisitorBase() {} + virtual ~StmtVisitorBase() {} + + public: +#define PTR(x) x * +#if 0 + std::cout<<"Visit: DISPATCH "<< # NAME <<" "<getStmtClass()<(this)->Visit ## NAME( static_cast(S)); + + RetTy Visit(AST::Stmt *S) { + if ( PTR(AST::BinaryOperator) BinOp = dynamic_cast(S) ) { + switch (BinOp->getOpcode()) { + case BO_Mul : DISPATCH (BinMul, AST::BinaryOperator); + case BO_Div : DISPATCH (BinDiv, AST::BinaryOperator); + case BO_Rem : DISPATCH (BinRem, AST::BinaryOperator); + case BO_Add : DISPATCH (BinAdd, AST::BinaryOperator); + case BO_Sub : DISPATCH (BinSub, AST::BinaryOperator); + case BO_Shl : DISPATCH (BinShl, AST::BinaryOperator); + case BO_Shr : DISPATCH (BinShr, AST::BinaryOperator); + case BO_LT : DISPATCH (BinLT, AST::BinaryOperator); + case BO_GT : DISPATCH (BinGT, AST::BinaryOperator); + case BO_LE : DISPATCH (BinLE, AST::BinaryOperator); + case BO_GE : DISPATCH (BinGE, AST::BinaryOperator); + case BO_EQ : DISPATCH (BinEQ, AST::BinaryOperator); + case BO_NE : DISPATCH (BinNE, AST::BinaryOperator); + case BO_And : DISPATCH (BinAnd, AST::BinaryOperator); + case BO_Xor : DISPATCH (BinXor, AST::BinaryOperator); + case BO_Or : DISPATCH (BinOr, AST::BinaryOperator); + case BO_LAnd : DISPATCH (BinLAnd, AST::BinaryOperator); + case BO_LOr : DISPATCH (BinLOr, AST::BinaryOperator); + case BO_Assign : DISPATCH (BinAssign , AST::BinaryOperator); + }; + + } else if (PTR(AST::UnaryOperator) UnOp = dynamic_cast(S)) { + switch (UnOp->getOpcode()) { + case UO_PostInc : DISPATCH (UnaryPostInc, AST::UnaryOperator); + case UO_PostDec : DISPATCH (UnaryPostDec, AST::UnaryOperator); + case UO_PreInc : DISPATCH (UnaryPreInc, AST::UnaryOperator); + case UO_PreDec : DISPATCH (UnaryPreDec, AST::UnaryOperator); + case UO_Plus : DISPATCH (UnaryPlus, AST::UnaryOperator); + case UO_Minus : DISPATCH (UnaryMinus, AST::UnaryOperator); + case UO_Not : DISPATCH (UnaryNot, AST::UnaryOperator); + case UO_LNot : DISPATCH (UnaryLNot, AST::UnaryOperator); + case UO_Test : DISPATCH (UnaryTest, AST::UnaryOperator); + default: + ; + } + } + // Maybe if it's not of Type BinOperator nor Unary Operator, Vistit Stamtement TO be done +#define STMT(CLASS,PARENT) \ + case AST::Stmt::CLASS ## Class : DISPATCH(CLASS,CLASS); + + switch (S->getStmtClass() ) { +#include "AST/Stmt.h.inc" + default: + ; + }; + std::cout<<"ERROR TODO Visit .... "<getStmtClass()< +class StmtVisitor : public StmtVisitorBase {}; + + + +} +#endif diff --git a/include/AST/StmtWhileStmt.h b/include/AST/StmtWhileStmt.h new file mode 100644 index 0000000..c5c3706 --- /dev/null +++ b/include/AST/StmtWhileStmt.h @@ -0,0 +1,16 @@ +#ifndef WHILESTMT_H__ +#define WHILESTMT_H__ + +class WhileStmt : public Stmt { + enum {COND,BODY,ELSE,END} ; + Stmt *m_Stmts[END]; + public: + WhileStmt(DeclContext *DC,Expr *cond,Stmt *_body) ; + + Expr *getCond() const ; + + Stmt *getBody() const { return m_Stmts[BODY]; }; + +}; + +#endif diff --git a/include/AST/TemplateBase.h b/include/AST/TemplateBase.h new file mode 100644 index 0000000..d5fd064 --- /dev/null +++ b/include/AST/TemplateBase.h @@ -0,0 +1,74 @@ +#ifndef TEMPLATE_BASE_H +#define TEMPLATE_BASE_H + +namespace AST { +class ASTContext; +class RecordDecl; +class Expr; +class TypedefDecl; + +/** + * @brief for syntype and so on, there is a need + * to collect the actual context parameters that are + * somehome similar to template arguments. For that + * I created this class to store either Types, Literals, + * Expressions that can be given as acual parameters. + * With this class I hope I'll be able to solve the issue + * with InfoArray, Vectors and strings. + */ +class TemplateArgument +{ + protected: + + union TV { + Expr *m_Expression; + Type *m_Type; + } m_TV; + + enum eKind { + eNull + ,eType + ,eExpression + } m_Kind; + + TemplateArgument(ASTContext *C,Expr *_a) + : m_Kind(eExpression) + { + m_TV.m_Expression=_a; + }; + TemplateArgument(ASTContext *C,Type *_a) + : m_Kind(eType) + { + m_TV.m_Type=_a; + }; + public: + + + static TemplateArgument * + Create(ASTContext &c,AST::Type *TD ) + { return new TemplateArgument(&c,TD); }; + + static TemplateArgument * + Create(ASTContext &c,Expr *E ) + { return new TemplateArgument(&c,E); }; + + bool isExpression() const + { return m_Kind == eExpression; } + + bool isType() const + { return m_Kind == eType; } + + Type *getType() const + { return m_TV.m_Type; } + + Expr *getExpression() const + { return m_TV.m_Expression; } +}; + +/// Array +typedef std::vector TemplateArgumentArray; +typedef TemplateArgumentArray::iterator TemplateArgIterator; +typedef TemplateArgumentArray::const_iterator TemplateArgConstIterator; + +} +#endif diff --git a/include/AST/Type.h b/include/AST/Type.h new file mode 100644 index 0000000..b5e80b1 --- /dev/null +++ b/include/AST/Type.h @@ -0,0 +1,216 @@ +#ifndef AST_TYPE_H +#define AST_TYPE_H + + +namespace AST { +class ASTContext; +class RecordDecl; +class TypedefDecl; +class ValueTypeDecl; + +/** + * This class represents an AST Type. There are different kind of types! + * Typedef types, Function prototype types, Structures, Builtin Types, Enumerated types, + * function pointer types, reference types + */ +class Type { + public: + enum TypeClass { + #define TYPE(Class,Base) Class, + #define ABSTRACT_TYPE(Class,Base) +#include "AST/Types.h.inc" + }; + protected: + unsigned int TC; + /** + * + */ + Type(TypeClass Cls); + Type(const Type &) {}; + virtual ~Type() {}; + friend class AST::ASTContext; + public: + /** + * + */ + TypeClass getClass() const + { return static_cast(TC); }; + + const char *getTypeClassName() const { + switch (TC) { +#define ABSTRACT_TYPE(Derived,Base) +#define TYPE(Derived,Base) case Derived: return #Derived; +#include "AST/Types.h.inc" + default: return "unknown class"; + } + }; +}; + +/** + * Declare the specific type of Types as well + */ +class BuiltinType : public Type +{ + public: + enum Kind { +#define BUILTIN_TYPE(Id,SigletonId) Id , +#include "AST/BuiltinTypes.h.def" + noKind + } m_Kind; + protected: + BuiltinType(Kind K) :m_Kind(K), Type(Builtin) {}; + friend class ASTContext; + public: + const char *getNameAsStr() const; + + Kind getKind() const { return m_Kind ; } +}; + +/** + * Function type does not have name. It as a signature + * composed of Return Type, Parameter Types, expections + * Several Functions can have the same type + */ +class FunctionType : public Type +{ + protected: + /** + * + */ + FunctionType(TypeClass tc) : Type(tc) {}; + friend class ASTContext; + public: +}; + +/** + * + */ +class FunctionProtoType : public FunctionType +{ + protected: + FunctionProtoType() : FunctionType(FunctionProto) {}; + friend class ASTContext; + public: +}; + + +/** + * + */ +class ReferenceType : public Type +{ + protected: + ReferenceType(TypeClass tc) : Type(tc) {}; + public: +}; + +/** + * + */ +class LValueReferenceType : public ReferenceType +{ + protected: + LValueReferenceType() : ReferenceType(LValueReference) {}; + friend class ASTContext; + public: +}; + +/** + * + */ +class RValueReferenceType : public ReferenceType +{ + protected: + RValueReferenceType() : ReferenceType(RValueReference) {}; + friend class ASTContext; + public: +}; + +/** + * A array containes + */ +class ArrayType : public Type +{ + protected: + Type *m_ElementType; + ArrayType(TypeClass tc,Type *e) + : Type(tc) + , m_ElementType(e) + {}; + friend class ASTContext; + public: + const Type *getElementType() const { return m_ElementType; }; +}; + +/** + * + */ +class ConstantArrayType : public ArrayType +{ + protected: + size_t m_Size; + ConstantArrayType(Type *et,size_t s) + : ArrayType(ConstantArray,et) + , m_Size(s) + {}; + friend class ASTContext; + public: +}; + +/** + * + */ +class TypedefType : public Type +{ + TypedefDecl *m_Decl; + protected: + TypedefType(const AST::TypedefDecl *td) + : m_Decl(const_cast(td)), Type(Typedef) {}; + friend class ASTContext; + public: + TypedefDecl *getDecl() const { return m_Decl ; } +}; + +/** + * @brief I'm not sure if I want to use this. + */ +class ValueType : public Type +{ + ValueTypeDecl *m_Decl; + protected: + ValueType(const AST::ValueTypeDecl *vt) + : m_Decl(const_cast(vt)), Type(Value) {}; + friend class ASTContext; + public: + ValueTypeDecl *getDecl() const { return m_Decl ; } +}; + + +/** + * + */ +class EnumType : public Type +{ + protected: + EnumType() : Type(Enum) {}; + public: +}; + +/** + * I think this can be used for Structure and so on + */ +class RecordType : public Type +{ + RecordDecl *m_Decl; + protected: + RecordType(const AST::RecordDecl *decl) + : m_Decl(const_cast(decl)),Type(Record) {}; + friend class ASTContext; + public: + RecordDecl *getDecl() const { return m_Decl ; } +}; + + +} + +#endif /*AST_TYPE_H*/ diff --git a/include/AST/Types.h.inc b/include/AST/Types.h.inc new file mode 100644 index 0000000..e814de0 --- /dev/null +++ b/include/AST/Types.h.inc @@ -0,0 +1,37 @@ +#ifndef ABSTRACT_TYPE +# define ABSTRACT_TYPE(Class,Base) TYPE(Class,Base) +#endif + +#ifndef NON_CANONICAL_TYPE +# define NON_CANONICAL_TYPE(Class,Base) TYPE(Class,Base) +#endif + + +TYPE(Builtin , Type) +ABSTRACT_TYPE(Reference , Type) +TYPE(LValueReference , ReferenceType) +TYPE(RValueReference , ReferenceType) + +TYPE(Array,Type) +TYPE(ConstantArray,ArrayType) + +ABSTRACT_TYPE(Function , Type) +TYPE(FunctionProto ,FunctionType) +/* K&R function declaration */ +/* TYPE(FunctionNoProto , FunctionType) */ +/** +May be those are Builtin Types +Natural +Time +Duration +*/ + +NON_CANONICAL_TYPE(Typedef,Type) +NON_CANONICAL_TYPE(Value,Type) + +TYPE(Enum,Type) +TYPE(Record,Type) + +#undef TYPE +#undef ABSTRACT_TYPE +#undef NON_CANONICAL_TYPE diff --git a/include/CodeGen/ASTMuliplexConsumer.h b/include/CodeGen/ASTMuliplexConsumer.h new file mode 100644 index 0000000..695be75 --- /dev/null +++ b/include/CodeGen/ASTMuliplexConsumer.h @@ -0,0 +1,17 @@ +#ifndef ASTMULTIPLEXCONSUMER_H__ +#define ASTMULTIPLEXCONSUMER_H__ + +/** + * Simple class that should call Handler.... on each consumer. + * + */ +class ASTMultiplexConsumer : public ASTConsumer +{ + public: + ASTMultiplexConsumer(std::vector &consumers); + + protected: + std::vector m_consumers; +}; + +#endif diff --git a/include/CodeGen/CGDebug.h b/include/CodeGen/CGDebug.h new file mode 100644 index 0000000..a9c7c62 --- /dev/null +++ b/include/CodeGen/CGDebug.h @@ -0,0 +1,33 @@ +#ifndef __CGDEBUG_H__ +#define __CGDEBUG_H__ + +#if defined(DEBUG) + +#define CGDBG(fmt) do { fprintf(stderr,fmt "\n"); } while(0) +#define CGDBG_ARGS(fmt,args...) do { fprintf(stderr,fmt "\n",args); } while(0) + +#define CGDBG_EXPR(fmt) do { fprintf(stderr,fmt "\n"); } while(0) +#define CGDBG_EXPR_ARGS(fmt,args...) do { fprintf(stderr,fmt "\n",args); } while(0) + +#if defined(CG_DEBUG_IF) +#define CGDBG_IF(fmt) do { fprintf(stderr,fmt "\n"); } while(0) +#define CGDBG_IF_ARGS(fmt,args...) do { fprintf(stderr,fmt "\n",args); } while(0) +#else +#define CGDBG_IF(fmt) +#define CGDBG_IF_ARGS(fmt,args...) +#endif + +#else + +#define CGDBG(fmt) +#define CGDBG_ARGS(fmt,args...) + +#define CGDBG_IF(fmt) +#define CGDBG_IF_ARGS(fmt,args...) + +#define CGDBG_EXPR(fmt) +#define CGDBG_EXPR_ARGS(fmt,args...) + +#endif + +#endif diff --git a/include/CodeGen/CMConsumer.h b/include/CodeGen/CMConsumer.h new file mode 100644 index 0000000..4ff4ba5 --- /dev/null +++ b/include/CodeGen/CMConsumer.h @@ -0,0 +1,11 @@ +#ifndef CM_CONSUMER_H__ +#define CM_CONSUMER_H__ + +class CMConsumer : public ASTConsumer +{ + public: + CMConsumer: + protected: + // should own a RecursiveVisitor +} +#endif diff --git a/include/CodeGen/CodeGenFunction.h b/include/CodeGen/CodeGenFunction.h new file mode 100644 index 0000000..5b246fe --- /dev/null +++ b/include/CodeGen/CodeGenFunction.h @@ -0,0 +1,104 @@ +#ifndef CODEGENFUNCTION_H__ +#define CODEGENFUNCTION_H__ +#include +namespace aeb { +namespace lds { + class SwitchInst; +namespace CodeGen { + class CodGenModule; + /** + * This class is responsible for IR code generation. + * Actually, I would like to be able to generate llvm IR + * or LDS IR. LDS is an inhouse VM Very basic with few instructions. + * + */ + class CodeGenFunction { + + public: + //typedef aeb::dlilist BlockList; + // What is needed ? + // A Builder that provide Blocks and set + Behavior *m_CurFn; + AST::FunctionDecl *m_DnDecl; + aeb::lds::Builder m_Builder; + CodeGenModule &m_CGM; + protected: + struct BreakContinue { + BreakContinue( aeb::lds::BasicBlock *_break + , aeb::lds::BasicBlock *_cont + , BasicBlock *h) + : m_Break(_break), + m_Continue(_cont) , m_Hash(h) {} ; + ~BreakContinue() {}; + aeb::lds::BasicBlock *m_Break; + aeb::lds::BasicBlock *m_Hash; + aeb::lds::BasicBlock *m_Continue; + }; + std::stack m_BreakContinueStack; + + // Keep trac of current switch context + SwitchInst *m_SwitchInst; + BasicBlock *m_SwitchHashBlock; + public: + CodeGenFunction(aeb::lds::CodeGen::CodeGenModule &_CGM,const aeb::lds::Builder &builder) ; + + aeb::lds::Builder &getBuilder() { return m_Builder; }; + + CodeGenModule &getModule() { return m_CGM; }; + + aeb::lds::Function *getCurrentFunction() { return dynamic_cast(m_CurFn) ;}; + void GenerateCode(const AST::FunctionDecl *FnDecl, Function *); + // This must disapear + //void GenerateCode(const AST::TransitionDecl *FnDecl, Transition *); + + void GenerateCode(const AST::TransitionDecl *FnDecl, Function *); + + void EmitGotoStmt( AST::GotoStmt *S); + + void EmitSwitchStmt( AST::SwitchStmt *S); + + void EmitBreakStmt( AST::BreakStmt *S); + + void EmitSwitchCaseStmt( AST::SwitchCaseStmt *S); + + void EmitWhileStmt( AST::WhileStmt *S); + + void EmitIfStmt(AST::IfStmt *S); + // Main entry point + void EmitStmt(AST::Stmt *s); + // + bool EmitSimpleStmt(AST::Stmt *s); + // + void EmitLdsAsmStmt(AST::LdsAsmStmt *s); + + void EmitOutputStmt(AST::OutputStmt *s); + + void EmitCompoundStmt( AST::CompoundStmt *S); + // Function Call + void EmitCallExpr( AST::CallExpr *S); + + void EmitVarDecl(const AST::Decl &D); + + void EmitBlock(aeb::lds::BasicBlock *,bool isFinished = false); + + void EmitBranch(aeb::lds::BasicBlock *); + + void EmitCallExpr(AST::Expr *E) {std::cout<<"EmitCallExpr tobe coded"< StructMap; + protected: + CodeGenModule &m_Module; + AST::ASTContext &m_Context; + public: + CodeGenType(CodeGenModule &CGM); + + aeb::lds::Type *ConvertBuiltinType(AST::BuiltinType *Ty); + + aeb::lds::Type *ConvertType(AST::Type *Ty); + /** + * @brief lds structures are encapsulated into ValueType type + * Maybe I should do the same with Union and Enums. + */ + aeb::lds::StructType *addStructTypeDecl(AST::ValueTypeDecl *_decl); +}; + + +} } } +#endif /*CODEGENTYPE_H*/ diff --git a/include/CodeGen/ModuleBuilder.h b/include/CodeGen/ModuleBuilder.h new file mode 100644 index 0000000..58e4e72 --- /dev/null +++ b/include/CodeGen/ModuleBuilder.h @@ -0,0 +1,22 @@ +#ifndef MODULE_BUILDER_H__ +#define MODULE_BUILDER_H__ + +namespace aeb { +namespace lds { +namespace CodeGen { + + class CodeGenerator { + public: + CodeGenerator () {}; + virtual ~CodeGenerator() {} ; + virtual aeb::lds::Module *GetModule() = 0; + virtual aeb::lds::CodeGen::CodeGenModule *GetBuilder() = 0; + virtual void HandleTopLevelDecl(AST::Decl *_decl) = 0; + }; + + CodeGenerator *CreateLdsGenerator(AST::ASTContext &C,const std::string &_ModuleName) ; +} +} +} + +#endif diff --git a/include/IR/Argument.h b/include/IR/Argument.h new file mode 100644 index 0000000..304cc3a --- /dev/null +++ b/include/IR/Argument.h @@ -0,0 +1,66 @@ +#ifndef ARGUMENT_H +#define ARGUMENT_H +#include +#include "aeb/dlilist_node.h" + +namespace aeb { + + template + class SymbolTableTraits ; + + namespace lds { + class BasicBlock; + class Transition; + class Function; + class Signal; + class Behavior; + class Module; + /** + * This class repesents a Function argument. Will + * be usefull to generate better C++ class + * + */ + class Argument : public Value, public aeb::dlilist_node { + Argument(const Argument &) : Value(*this) {}; // Avoid Copy construction + //operator =(const Instruction &) ; + // + std::string m_name; + Function *m_Parent; + + public: + typedef std::string ArgumentType ; + // Constructor + Argument(const std::string &Ty,Function *_f = NULL); + + virtual ~Argument() {}; + + void setParent(Function *); + + bool operator ==(const std::string &s) + { return !s.compare(getName()); }; + + std::string getTypeName() const { return m_name ;} + inline const Function *getParent() const { return m_Parent; }; + inline Function *getParent() { return m_Parent; }; + }; + + /** + * + */ + class SigArgument : public Value, public aeb::dlilist_node + { + Signal *m_Parent; + public: + SigArgument(const std::string &Ty,Signal *_f = NULL) ; + + const std::string &getTypeName() const {return getName() ; } + void setParent(Signal *p) { m_Parent = p;}; + inline const Signal *getParent() const { return m_Parent; }; + inline Signal *getParent() { return m_Parent; }; + }; + } +} +#endif /*ARGUMENT_H*/ +/** + * ex: set et sw=4 ts=4 list: + */ diff --git a/include/IR/BasicBlock.h b/include/IR/BasicBlock.h new file mode 100644 index 0000000..f01d197 --- /dev/null +++ b/include/IR/BasicBlock.h @@ -0,0 +1,106 @@ +#ifndef AEB_BASICBLOCK_H__ +#define AEB_BASICBLOCK_H__ + +#include "aeb/dlilist.h" +#include "IR/LdsInstruction.h" +#include "IR/SymbolTableTraits.h" + +namespace aeb { + + namespace lds { + + // First attempt for callback invocation + + + /** + * + * Need to be able to insert Instuctions in there. + * Basic Instructions : + * FunctionCall + * JUMP .... + * LOAD + * CMP + * + * TERMINATOR... + * + * Blocks are chained ... I still need to figure out how + */ + class BasicBlock : + public Value + , public aeb::dlilist_node + { + public: + // Constains a list of Instruction .... + typedef SymbolTable InstList; + + // Instruction Iterator + typedef InstList::iterator iterator; + typedef InstList::const_iterator const_iterator; + + protected: + InstList m_Instructions; + + std::string m_Name; + // Copy Constructor + BasicBlock(const BasicBlock &p,const std::string &name , BasicBlock *parent = NULL ); + + Behavior *m_Parent; + public: + + BasicBlock(const std::string &name="Sentinel",BasicBlock *parent = NULL); + + virtual ~BasicBlock(); + + const char *getName() { return m_Name.c_str();} + + void setName(const std::string &s) { m_Name = s; }; + // Parent acces for Block. + // Actually, the parent can be a function, a transition need to see how to solve this + Behavior *getParent() const { return m_Parent; }; + // + void setParent(Behavior *p) { m_Parent = p; }; + + // Iterators + inline iterator begin() { return m_Instructions.begin(); } + inline const_iterator begin() const { return m_Instructions.begin(); } + + inline iterator end() { return m_Instructions.end(); } + inline const_iterator end() const { return m_Instructions.end(); } + + inline size_t size() const { return m_Instructions.size();} ; + // Mising front, back, empty , size + + size_t NbOpcode() const ; + + size_t NbOpcode(iterator &c) const ; + + + static InstList BasicBlock::*getSublistAccess(Instruction*) { + return &BasicBlock::m_Instructions; + } + + /// Constructors are private + static BasicBlock *Create(const std::string &name,BasicBlock *Parent = NULL) { + return new BasicBlock(name,Parent); }; + + + const Instruction *getTerminator() { + if (m_Instructions.empty() ) return NULL; + return dynamic_cast(& (m_Instructions.back())); + ; + } + /// Access to the List to modify it + InstList &getInstList() { return m_Instructions ; }; + + const InstList &getInstList() const { return m_Instructions ; }; + + bool Empty() const { return m_Instructions.empty();}; + + // Add Instructions and so on + }; + + + } +} + +#endif diff --git a/include/IR/Behavior.h b/include/IR/Behavior.h new file mode 100644 index 0000000..d5190b1 --- /dev/null +++ b/include/IR/Behavior.h @@ -0,0 +1,68 @@ +#ifndef IR_BEHAVIOR_H__ +#define IR_BEHAVIOR_H__ + +#include "aeb/dlilist.h" +#include "IR/BasicBlock.h" +#include "IR/SymbolTableTraits.h" + +namespace aeb { + +namespace lds { + +class State; +class Function; +class Module; + + +/** + * The behavior class is a generic class for everything that contains behavioral instructions. + * - A function implementation is a behaviors. + * - A transition contains a behavior that is triggers on several events. I could say that several + * events implement the same behaviors + * + */ + +class Behavior : public Value +{ + protected: + //typedef aeb::dlilist BlockListType; + typedef aeb::SymbolTable BlockListType; + typedef BlockListType::iterator iterator; + typedef BlockListType::const_iterator const_iterator; + protected: + + BlockListType m_Blocks; + std::string m_Name; + + Behavior(const Behavior &p) ; + public: + + Behavior(const std::string & m_Name , Type *Ty,unsigned tid) ; + + virtual ~Behavior() ; + + static BlockListType Behavior::*getSublistAccess(BasicBlock *) { + return &Behavior::m_Blocks; + } + + + // Iterators, + iterator begin() { return m_Blocks.begin() ; }; + const_iterator begin() const { return m_Blocks.begin(); }; + iterator end() { return m_Blocks.end() ; } + const_iterator end() const { return m_Blocks.end() ; }; + /// Access to the List to modify it + BlockListType &getBlockList() { + return m_Blocks ; + }; + + const BlockListType &getBlockList() const { + return m_Blocks ; + }; + +}; + + +} +} +#endif diff --git a/include/IR/Constant.h b/include/IR/Constant.h new file mode 100644 index 0000000..d3bd301 --- /dev/null +++ b/include/IR/Constant.h @@ -0,0 +1,35 @@ +#ifndef CONSTANT_H +#define CONSTANT_H + +#include "IR/User.h" + +namespace aeb { +namespace lds { +class Module; +/** + * + * This class represents Constants in a Module. + * A Constant can be a Function, a Global Variable, + * an Integer used during Initialization phase. + * + * -TODO + * + */ +class Constant : public User { + protected: + // TODO the information bellow are stored in Value + // Missing Constant value when constante + Constant(const Constant &_g) : User(*this) {} + + Constant(Type *Ty,unsigned vty,Use *u,unsigned int nbOperand) + : User(Ty,vty,u,nbOperand) {} + public: + + // Need some basic Constructors + Constant *getInteger(Type *Ty,long _value) { return NULL ; }; + +}; + +} +} +#endif /*CONSTANT_H*/ diff --git a/include/IR/Function.h b/include/IR/Function.h new file mode 100644 index 0000000..256eb6a --- /dev/null +++ b/include/IR/Function.h @@ -0,0 +1,103 @@ +#ifndef IR_FUNCTION_H__ +#define IR_FUNCTION_H__ + +#include "aeb/dlilist.h" +#include "IR/Value.h" +#include "IR/BasicBlock.h" +#include "IR/Behavior.h" +#include "IR/Argument.h" +#include "IR/SymbolTableTraits.h" + +namespace aeb { +template<> + struct SymbolTableListSentinelTraits + : public dlilist_half_embedded_sentinel_traits {}; + +namespace lds { +class State; +class Function; +class Module; + + +/** + * A Function can have parameters ... + * Argument is the formal description of the argument. + * It'a attributes help in code generation (Reference argument + * By value arguement, Allocated Arguement) + * + */ + +class Function : public Behavior + , public aeb::dlilist_node +{ + + public: + /* Tells if the function is a declaration or a local implementation .... */ + enum FctType { + Local + ,ExternalLink + }; + + typedef aeb::SymbolTable ArgumentListType; + + typedef ArgumentListType::iterator ArgumentIterator; + typedef ArgumentListType::const_iterator ArgumentConstIterator; + protected: + Module *m_Parent; + FctType m_FctType; + long m_NbParam; + ArgumentListType m_ArgumentList; + public: + Function(const std::string &s="DefFct",FctType fc=ExternalLink) ; + + static Function *Create(const std::string &name,FctType ft = ExternalLink) { + return new Function(name,ft); + } + Module *getParent() { return m_Parent;}; + + const Module *getParent() const { return m_Parent;}; + + void setParent(Module *p) { m_Parent = p; }; + + bool isExternal() const { return m_FctType == ExternalLink; }; + // SymbolTable stuff + static ArgumentListType Function::*getSublistAccess(Argument *) { + return &Function::m_ArgumentList; + }; + + static BlockListType Function::*getSublistAccess(BasicBlock *b) { + return Behavior::getSublistAccess(b); + //m_Blocks; + }; + + // TODO Temporary, needs to be removed + inline long getNbParams() { return m_NbParam; }; + inline void setNbParams(long i) { m_NbParam = i; }; + // + inline ArgumentListType &args() { return m_ArgumentList;}; + // + bool operator ==(const std::string &s) const { return ! m_Name.compare(s); } + + bool operator !=(const std::string &s) const { return m_Name.compare(s); } + + // Iterators + ArgumentIterator arg_begin() { return m_ArgumentList.begin() ; } + ArgumentIterator arg_end() { return m_ArgumentList.end() ; } + + ArgumentConstIterator arg_begin() const { return m_ArgumentList.begin() ; } + ArgumentConstIterator arg_end() const { return m_ArgumentList.end() ; } + + Argument *getArgument(const std::string &n) + { + ArgumentIterator it = std::find(arg_begin(),arg_end(),n); + return it; + } ; +}; + + +} +} +#endif +/** + * ex: set et sw=4 ts=4 list: + */ diff --git a/include/IR/GlobalVariable.h b/include/IR/GlobalVariable.h new file mode 100644 index 0000000..81a99d2 --- /dev/null +++ b/include/IR/GlobalVariable.h @@ -0,0 +1,82 @@ +#ifndef GLOBALVARIABLE_H__ +#define GLOBALVARIABLE_H__ + +#include "IR/Constant.h" +#include "IR/OperandTraits.h" +namespace aeb { +// Forward declaration +template class SymbolTableListTraits; +namespace lds { +class Module; +class Constant; +/** + * + * This class represents a global Variable in the Module. + * it's supposed to be a Flag. (Type is not yet supported and requires a lot + * of work. But it should be done if I want to use Abstract Data Types (eg + * ASN1, XSD, WSDL ...) + * + * -TODO + * Also Missing the Initializer part. A global variable can be initialized. The + * Parser gets the expression and stores it. Now, The IR should also handle it + * preperly. + * May be, this class should inherit from User instead of Value. Later on, we + * can make the connection between the initialize et the variable. + * + */ +class GlobalVariable : public aeb::dlilist_node , public Constant { + protected: + friend class SymbolTableListTraits; + // TODO the information bellow are stored in Value + Module *m_Parent; + bool m_IsConstant : 1; /* Is it a constant Global Variable */ + // Missing Constant value when constante + GlobalVariable(const GlobalVariable &_g) : Constant(*this) {} + public: + GlobalVariable(const std::string &flg , bool constant,Type *_Ty = NULL); +#if 0 + : m_IsConstant(constant) + , Constant(_Ty, GlobalVariableVal,OperandTraits::op_begin(this),1) + , m_Parent(NULL) + { Value::setName(flg); } ; +#endif + virtual ~GlobalVariable() {} ; + + inline bool hasInitializer() const { return false; }; + void setInitializer(Constant *InitVal) ; + + /// Return Initializer if present. Should Not be called if absent + Constant *getInitializer() ; + + DECLARE_OPERAND_ACCESS(Value) + + /* Allocate Space for One operand */ + void * operator new(size_t s) + { + return User::operator new(s,1); + } + + void setParent(Module *p) { m_Parent = p ; } ; + + Module *getParent() const { return m_Parent;} ; + + bool isConstant() const { return m_IsConstant; }; + + bool operator ==(const std::string &s) { return ! getName().compare(s); }; + + bool operator !=(const std::string &s) { return getName().compare(s); }; + protected: + + +} ; + +template <> +struct OperandTraits : + public FixedNumOperandTraits +{ +}; +DEFINE_OPERAND_ACCESS(GlobalVariable,Value) + +} +} +#endif diff --git a/include/IR/IRBuilderAdaptor.h b/include/IR/IRBuilderAdaptor.h new file mode 100644 index 0000000..742967b --- /dev/null +++ b/include/IR/IRBuilderAdaptor.h @@ -0,0 +1,33 @@ +#ifndef IR_IRBUILDER_ADAPTOR_H__ +#define IR_IRBUILDER_ADAPTOR_H__ + +/** + * This template is an adaptor that will contain an IRBuilder implemention + * The goal is to be able to use Lds Builder or LLVM which is much more powerfull + */ + +template +class IRBuilderAdaptor { + /// Keeps an instance of the Adaptor + Builder &m_Instance; + + public: + IRBuilderAdaptor(const Build &i) : m_Instance(i) {} + + BBlock *GetInsertBlock(); + + void SetInsertPoint(BBlock *BB) { + m_Instance.SetInsertPoint(BB); + }; + + void ClearInsertPoint() { + m_Instance.ClearInserPoint(); + }; + // Parameters : Value, Block , Block + void CreateCondBr( BBlock *Tr, BBlock *Fl) { + + }; +}; + +}; +#endif diff --git a/include/IR/LdsBuilder.h b/include/IR/LdsBuilder.h new file mode 100644 index 0000000..327d089 --- /dev/null +++ b/include/IR/LdsBuilder.h @@ -0,0 +1,200 @@ +#ifndef AEB_LDS_IRBUILDER_H__ +#define AEB_LDS_IRBUILDER_H__ + +namespace aeb { + +namespace lds { + /** + * + * The Builder handles blocks. Should be easy from here one to + * compute jump distances and so one. + */ + class Builder { + typedef aeb::lds::BasicBlock Block; + typedef aeb::lds::BasicBlock::iterator Iterator; + + aeb::lds::BasicBlock *m_BB; + aeb::lds::BasicBlock::iterator m_InsertPt; // Instruction pointer... + public: + + Builder() : m_BB(NULL) {}; + Builder(const Builder &_b) : m_BB(_b.m_BB), m_InsertPt(_b.m_InsertPt) {}; + BasicBlock *GetInsertBlock( ) const { return m_BB; }; + + void SetInsertPoint(aeb::lds::BasicBlock *BB) { + m_BB = BB; + m_InsertPt = BB->end(); + }; + + void SetInsertPoint(Block *BB,aeb::lds::BasicBlock::iterator &IT ) { + m_BB = BB; + m_InsertPt = IT; + } + + void SetInsertPoint(Instruction *I) { + m_BB = I->getParent(); + m_InsertPt = Iterator(I); + } + + void ClearInsertPoint() { + m_BB = NULL; + m_InsertPt = Iterator(NULL); + }; + // Parameters : Value, Block , Block + BranchCondInst *CreateCondBr( aeb::lds::BasicBlock *Tr, aeb::lds::BasicBlock *Fl) + { + //Create BranchInstruction ... + return Insert(BranchCondInst::Create(Tr,Fl),"CondBr"); + }; + + BranchInst *CreateBr(aeb::lds::BasicBlock *Dest) { + return Insert(BranchInst::Create(Dest),"Br"); + } + + BranchSubroutine *CreateJsr(const std::string &flg) { + return Insert(BranchSubroutine::CreateJsr(flg),"Jsr"); + } + + IndirectBranchInst *CreateJsrInd(const std::string &flg) { + return Insert(IndirectBranchInst::CreateJsrInd(flg),"JsrInd"); + } + + GotoStateInst *CreateGotoState(const std::string &sn) { + return Insert(GotoStateInst::Create(sn),""); + } + + SwitchInst *CreateSwitch(Value *cond,aeb::lds::BasicBlock *jump = NULL) { + return Insert(SwitchInst::Create(cond,jump),""); + } + + + CallInst *CreateCall(const std::string &fctn,aeb::lds::BasicBlock *Dest = NULL) { + return Insert(CallInst::Create(fctn,Dest),""); + } + + + Instruction *CreateNot(Instruction *value) { + return Insert(ComplInst::Create(NULL)); + } + // Load value into Accumulator + Instruction *CreateLoad(const std::string &s) { + return Insert(LoadInst::CreateLoadA(s)); + } + Instruction *CreateLoad(Value *v) { + return Insert(LoadInst::Create(v)); + } + Instruction *CreateExtractValue(Value *v,int idx,const std::string &n) { + return Insert(ExtractValueInst::Create(v,idx)); + } + // Store value from accumulator into register + Instruction *CreateStore(const std::string &s) { + return Insert(StoreInst::CreateStoreA(s)); + } + Instruction *CreateStore(Value *s) { + return Insert(StoreInst::Create(s)); + } + // Set Flag + Instruction *CreateSet(const std::string &s) { + return Insert(FlagInst::CreateSet(s)); + } + // Reset Flag + Instruction *CreateReset(const std::string &s) { + return Insert(FlagInst::CreateReset(s)); + } + + // Reset Flag + Instruction *CreateNop() { + return Insert(NopInst::Create(),""); + } + Instruction *CreateSendEvent(const Value *S) { + return Insert(SendEventInst::Create(S),""); + } + SendEventInst *CreateOutput(const Value *v) { + return Insert(SendEventInst::CreateOutput(v),""); + } + + + + /** + * Binary Operations + */ + Instruction *CreateAnd(aeb::lds::BasicBlock *LHS,aeb::lds::BasicBlock *RHS) { + return Insert(aeb::lds::BinaryOperator::CreateAEL_AND(NULL,NULL,NULL)); + } + Instruction *CreateAnd(const std::string &s) { + return Insert(aeb::lds::BinaryOperator::CreateAEL_AND(s,NULL)); + } + + Instruction *CreateOr(aeb::lds::BasicBlock *LHS,aeb::lds::BasicBlock *RHS) { + return Insert(aeb::lds::BinaryOperator::CreateAEL_OR(NULL,NULL,NULL)); + } + + Instruction *CreatePlus(aeb::lds::BasicBlock *LHS,aeb::lds::BasicBlock *RHS) { + return Insert(aeb::lds::BinaryOperator::CreateAEL_PLUS(NULL,NULL,NULL)); + } + Instruction *CreatePlus(aeb::lds::Value *LHS,aeb::lds::Value *RHS) { + return Insert(aeb::lds::BinaryOperator::CreateAEL_PLUS(LHS,RHS,NULL)); + } + + Instruction *CreateMoin(aeb::lds::BasicBlock *LHS,aeb::lds::BasicBlock *RHS) { + return Insert(aeb::lds::BinaryOperator::CreateAEL_MOIN(NULL,NULL,NULL)); + } + Instruction *CreateMoin(aeb::lds::Value *LHS,aeb::lds::Value *RHS) { + return Insert(aeb::lds::BinaryOperator::CreateAEL_MOIN(LHS,RHS,NULL)); + } + + Instruction *CreateOr(const std::string &s) { + return Insert(aeb::lds::BinaryOperator::CreateAEL_OR(s,NULL)); + } + + Instruction *CreateCmp(aeb::lds::BasicBlock *LHS,aeb::lds::BasicBlock *RHS) { + return Insert(CmpInst::Create(NULL),""); + } + Instruction *CreateCmp(const std::string &S) { + return Insert(CmpInst::Create(S),""); + } + /// S should be: EQ, NE, GT,LT,LE,GE + Instruction *CreateCmp(Value *v,const std::string &S) { + return Insert(CmpInst::Create(v,S),""); + } + Instruction *CreateTest(const std::string &S) { + return Insert(LoadInst::CreateLoadA(S),""); + } + Instruction *CreateTest(unsigned long S) { + std::ostringstream oss; + oss< + InstTy *Insert(InstTy *I,const std::string &Name = "") { + if (m_BB) { + m_BB->getInstList().insert(m_InsertPt,I); + } else + std::cout<<"LdsBuilder::Insert no Block "<(this)->visit##TO_CLASS(static_cast(I)) ; \ +/** + * \brief Instruction Visitor Class, I'm wondering if this is going to work !! + * + * + * + */ +template +class InstrVisitor { + public: + // Range visiting + template + void visit(Iterator Begin,Iterator End) { + while (Begin != End ) { + static_cast(this)->visit(*Begin++); + } + } + template + void visitDecl(Iterator Begin,Iterator End) { + while (Begin != End ) { + static_cast(this)->visitDecl(*Begin++); + } + } + + void visit(Module &M) { + static_cast(this)->visitModule(M); + // May be I should visit Global Functions first + visit(M.global_begin(),M.global_end()); + visitDecl(M.signal_begin(),M.signal_end()); + visit(M.signal_begin(),M.signal_end()); + visit(M.function_begin(),M.function_end()); + visit(M.state_begin(),M.state_end()); + } + + void visit(GlobalVariable &T) { + static_cast(this)->visitGlobalVariable(T); + //visit(T.begin(),T.end()); + } + + + void visit(Function &T) { + // std::cout<<"visit Function:"<(this)->visitTransition(T); + // std::cout<<"visit Transition:"<(this)->visitBasicBlock(T); + // if ( ! T.getInstList().empty() ) + visit(T.begin(),T.end()); + } + + + void visit(Signal &T) { + static_cast(this)->visitSignal(T); + } + void visitDecl(Signal &T) { + static_cast(this)->visitDeclSignal(T); + } + + // Pointer Version + void visit(Module *M) { visit(*M); } + void visit(BasicBlock *M) { if ( M ) visit(*M); } + void visit(GlobalVariable *M) { visit(*M); } + void visit(Function *M) { visit(*M); } + void visit(State *M) { visit(*M); } + void visit(Transition *M) { visit(*M); } + + RetType visit(Instruction *M) { visit(*M); } + + + + RetType visit(Instruction &I) { + // std::cout<<"visit(Instruction : "<(this)->visit##OP(static_cast(I)) ; +#include "IR/ldsOpcode.h" +#undef OPCODE + default: + ; // Empty Instructions are ignored + // std::cout<<"visitInstruction: Not Known "<(this)->visitInstruction(I) ; \ + } +#include "IR/ldsOpcode.h" +#undef OPCODE + + +}; + + +} +} +#endif diff --git a/include/IR/LdsInstruction.h b/include/IR/LdsInstruction.h new file mode 100644 index 0000000..fe79f5e --- /dev/null +++ b/include/IR/LdsInstruction.h @@ -0,0 +1,734 @@ +#ifndef AEB_LDS_INSTRUCTION_H__ +#define AEB_LDS_INSTRUCTION_H__ +#include +#include "aeb/dlilist_node.h" + +#include "IR/Value.h" +#include "IR/User.h" +#include "IR/OperandTraits.h" + +namespace aeb { + + template + class SymbolTableTraits ; +namespace lds { + class BasicBlock; + class Transition; + class Behavior; + class Module; + class Value; + /** + * This class repesents a Intermediate language Instruction Set. + * Seee how to interface this with llvm ... + */ + class Instruction : public aeb::dlilist_node , public User { + Instruction(const Instruction &i) + : User(i) {}; // Avoid Copy construction + //operator =(const Instruction &) ; + // + BasicBlock *m_Parent; + protected: + unsigned int m_Opcode; + + inline void setOpcode(unsigned int _m) {m_Opcode = _m;}; + public: + enum { + NullOpcode +#define OPCODE(NUM,OP,SIZE,CLASS) , OP##Opcode +#include "ldsOpcode.h" + } Opcodes; + + Instruction(unsigned int Opcode = NullOpcode + , BasicBlock *parent = NULL) + : User(NULL,InstructionVal,NULL,0) , m_Opcode(Opcode) , m_Parent(parent) + { }; + Instruction(unsigned int Opcode + ,Use *OpBegin,unsigned NbOp) + : User(NULL,InstructionVal,OpBegin,NbOp) + , m_Opcode(Opcode) , m_Parent(NULL) + { }; + // Yeee works + virtual ~Instruction() { + //std::cout<<"Instruction::~Instruction"< BlockListType; + enum {BTRUE,BFALSE,BCOND,BEND}; + BasicBlock *m_Block[BEND]; + + void *operator new(size_t s) { + return User::operator new(s, 2); + } + protected: + BranchInst(unsigned int op,BasicBlock *IfTrue = NULL + ,BasicBlock *IfFalse = NULL) ; + ~BranchInst() + { } + + DECLARE_OPERAND_ACCESS(Value) + + + public: + static BranchInst *Create( BasicBlock *IfTrue + , Instruction *InsertAfter = NULL) + { + return new BranchInst(AEL_JUMP_PLUSOpcode,IfTrue); + } + + static BranchInst *Create( BasicBlock *IfTrue , BasicBlock *IfFalse + , BasicBlock *Cond + , Instruction *InsertAfter = NULL) + { + return new BranchInst(AEL_JUMP_PLUSOpcode,IfTrue); + } + virtual int ThenLength () ; + + aeb::lds::BasicBlock *getTrue() const { return m_Block[BTRUE] ; }; + aeb::lds::BasicBlock *getFalse() const { return m_Block[BFALSE] ; }; + aeb::lds::BasicBlock *getCond() const { return m_Block[BCOND] ; }; + + bool isUnConditional() const { return getFalse() == NULL;}; + + const char *getOpcodeName() ; + + virtual size_t NbOpcode() const ; + }; + template <> + struct OperandTraits : public FixedNumOperandTraits + { }; + + DEFINE_OPERAND_ACCESS(BranchInst,Value) + /** + * Basic Required Instructions for LDS VM + */ + class BranchCondInst : public BranchInst + { + BranchCondInst(unsigned int op , BasicBlock *Then,BasicBlock *Else) + : BranchInst(op,Then,Else) + {}; + + void *operator new(size_t s) { + return User::operator new(s, 2); + } + DECLARE_OPERAND_ACCESS(Value) + public: + static BranchCondInst *Create(BasicBlock *Then,BasicBlock *Else = NULL) + { + return new BranchCondInst(AEL_JUMP_PLUS_IF_NOTOpcode, Then,Else); + } + + virtual int ThenLength () ; + + const char *getOpcodeName() ; + + virtual size_t NbOpcode() const {return 2;} ; + }; + + template <> + struct OperandTraits : public FixedNumOperandTraits + { }; + + DEFINE_OPERAND_ACCESS(BranchCondInst,Value) + /** + * Basic Required Branch Subroutine + * It's either a defined internal function or a C Function + */ + class BranchSubroutine : public Instruction + { + BranchSubroutine( unsigned int op + , const std::string & _fn + , BasicBlock *Then = NULL) + : m_Fct(_fn) + , Instruction(op) + , m_Sub(Then) + //, BranchInst(op,Then,NULL) + {}; + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + std::string m_Fct; + BasicBlock *m_Sub; + public: + static BranchSubroutine *Create(const std::string &_fn,BasicBlock *Then) { + return new BranchSubroutine(AEL_JSROpcode, _fn,Then); + } + static BranchSubroutine *CreateJsr(const std::string &flag) { + return new BranchSubroutine(AEL_JSROpcode,flag); + } + static BranchSubroutine *CreateJsrInd(const std::string &flag) { + return new BranchSubroutine(AEL_JSR_INDOpcode,flag); + } +#if 0 + virtual int ThenLength () ; +#endif + const char *getOpcodeName() ; + + virtual size_t NbOpcode() const {return 2;} ; + }; + + /** + * + */ + class SwitchInst : public TerminatorInst + { + SwitchInst(unsigned int op, Value *cond,BasicBlock *def) + : m_Cond(cond) + , TerminatorInst(op) + , m_HashBlock(def) + {}; + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + protected: + BasicBlock *m_HashBlock; + //std::string m_Var; + Value *m_Cond; + public: + /* First Parameter should be a Value*/ + static SwitchInst *Create(Value *cond,BasicBlock *hash = NULL) { + return new SwitchInst(AEL_JUMP_INDOpcode,cond, hash); + } + + void addCase(int value,BasicBlock *doblock) { + } + + BasicBlock *getHash() const { return m_HashBlock; }; + + virtual int ThenLength () ; + + virtual size_t NbOpcode() const {return 3;} ; + + + virtual const char *getOpcodeName() ; + }; + + /** + * JMP subroutine + */ + class IndirectBranchInst : public Instruction + { + IndirectBranchInst( unsigned int op + , int _nbp + , const std::string &s) + : Instruction(op) + , m_NbParameters(_nbp) + , m_Flag(s) + {}; + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + protected: + std::string m_Flag; + int m_NbParameters; + public: + static IndirectBranchInst *Create(BasicBlock *B) { + return new IndirectBranchInst(AEL_JUMP_INDOpcode,2,""); + } + static IndirectBranchInst *CreateJsr(const std::string &flag) { + return new IndirectBranchInst(AEL_JSR_INDOpcode,2,flag); + } + static IndirectBranchInst *CreateJsrInd(const std::string &flag) { + return new IndirectBranchInst(AEL_JSR_INDOpcode,2,flag); + } + + virtual size_t NbOpcode() const {return 2;} ; + + virtual const char *getOpcodeName() { + static std::string s; + s = Instruction::getOpcodeName(m_Opcode) ; + s+= " ," ; s+=m_Flag ; return s.c_str(); }; + + + }; + + /** + * Is AEL_(RE)SET Flag instructions .... + */ + class FlagInst : public Instruction + { + void *operator new(size_t s) { + return User::operator new(s, 0); + } + protected: + std::string m_Flag; + + FlagInst(unsigned int op,const std::string &f) + : Instruction(op) , m_Flag(f) + {}; + public: + static FlagInst *CreateSet(const std::string &flg) { + return new FlagInst(AEL_SETOpcode,flg); + } + static FlagInst *CreateReset(const std::string &flg) { + return new FlagInst(AEL_RESETOpcode,flg); + } + virtual size_t NbOpcode() const {return 2;} ; + + virtual const char *getOpcodeName() { + static std::string s; + s = Instruction::getOpcodeName(m_Opcode) ; + s+= " ," ; s+=m_Flag ; return s.c_str(); }; + + + }; + + /** + * Is AEL_(RE)SET Flag instructions .... + */ + class NopInst : public Instruction + { + void *operator new(size_t s) { + return User::operator new(s, 0); + } + protected: + + NopInst(unsigned int op) : Instruction(op) {}; + public: + static NopInst *Create() { + return new NopInst(AEL_NOPOpcode); + } + virtual size_t NbOpcode() const {return 1;} ; + + }; + + + + /** + * Is AEL_RETURN + */ + class ReturnInst : public TerminatorInst + { + ReturnInst(unsigned int op) : TerminatorInst(op) + {}; + void *operator new(size_t s) { + return User::operator new(s, 0); + } + public: + static ReturnInst *Create(BasicBlock *B = NULL) { + return new ReturnInst(AEL_RETURNOpcode); + } + static ReturnInst *CreateRetSub() { + return new ReturnInst(AEL_RTSOpcode); + } + virtual size_t NbOpcode() const {return 1;} ; + }; + + /** + * Is AEL_RST + * + */ + class ResumeInst : public Instruction { + ResumeInst(); + public: + static ResumeInst *Create(BasicBlock *B) { + return NULL; + } + }; + /** + * Save given FLAG as parameter into Accumulator + * meaning Load working register with value from VM memory + */ + class LoadInst : public Instruction + { + LoadInst(unsigned int op,const std::string &Flg="",bool _co=false) ; + + LoadInst(unsigned int op,Value *v); + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + public: + static LoadInst *Create(BasicBlock *B) { + return new LoadInst(AEL_TESTOpcode); + } + + static LoadInst *Create(Value *Flg) { + return new LoadInst(AEL_TESTOpcode,Flg); + } + + /** + * Load Accumulator with value from Flag + */ + static LoadInst *CreateLoadA(const std::string &Flg) { + return new LoadInst(AEL_TESTOpcode,Flg); + } + /** + * Load Constant into accumulator + */ + static LoadInst *CreateLoadConst(const std::string &B) { + return new LoadInst(AEL_TESTOpcode,B,true); + } + + virtual size_t NbOpcode() const {return 2;} ; + + virtual const char *getOpcodeName(); + + protected: + std::string m_Flag; + Value *m_Value; + bool m_Constant; + }; + + /** + * -- Save Global FLAG into Flag given as parameter + * meaning store Working register into VM memory + */ + class StoreInst : public Instruction + { + StoreInst(unsigned int op,const std::string &Flg="") + : m_Value(NULL), Instruction(op),m_Flag(Flg) {}; + StoreInst(unsigned int op,Value *v); + // : Instruction(op),m_Flag(Flg) {}; + void *operator new(size_t s) { + return User::operator new(s, 0); + } + public: + static StoreInst *Create(BasicBlock *B) { + return new StoreInst(AEL_CHARGEOpcode); + } + static StoreInst *Create(Value *v) { + return new StoreInst(AEL_CHARGEOpcode,v); + } + /** + * Store value from accumulator into place + */ + static StoreInst *CreateStoreA(const std::string &Flg) { + return new StoreInst(AEL_CHARGEOpcode,Flg); + } + virtual size_t NbOpcode() const {return 2;} ; + + virtual const char *getOpcodeName(); + + protected: + Value *m_Value; + std::string m_Flag; + }; + + + class BinaryOperator : public Instruction + { + BinaryOperator(unsigned int op,Value *V1,Value *V2,BasicBlock *insertAf = NULL) ; + // : Instruction(op),m_V1(V1),m_V2(V2) {}; + BinaryOperator( unsigned int op + , const std::string &Flg + , BasicBlock *insertAf = NULL) + : Instruction(op),m_Flag(Flg) , + m_V1(NULL),m_V2(NULL) + {}; + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + public: + static BinaryOperator *Create(unsigned int op,Value *V1,Value *V2,BasicBlock *insertAf) { + return new BinaryOperator(op,V1,V2); + } + + static BinaryOperator *Create(unsigned int op,const std::string &Flg,BasicBlock *insertAf) { + return new BinaryOperator(op,Flg); + } + virtual size_t NbOpcode() const {return 3;} ; + + virtual const char *getOpcodeName(); + +#define HANDLE_BINARY_INST(NUM,OP,SIZE,CLASS) \ + static BinaryOperator *Create ## OP( Value *V1,Value *V2,BasicBlock *insertAf) { \ + return new BinaryOperator(OP ## Opcode,V1,V2,insertAf); \ + } \ + static BinaryOperator *Create ## OP(const std::string &Flg ,BasicBlock *insertAf) { \ + return new BinaryOperator(OP ## Opcode,Flg,insertAf); \ + } \ + +#include "ldsOpcode.h" + protected: + Value *m_V1; + Value *m_V2; + std::string m_Flag; // Variable used for the operation + }; + + class UnaryOperator : public Instruction { + UnaryOperator(unsigned int op) : Instruction(op) {}; + public: + static UnaryOperator *Create(BasicBlock *B) { + return NULL; + } + }; + + class ExtractValueInst : public Instruction + { + ExtractValueInst(Value *v, int idx); + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + public: + static ExtractValueInst *Create(Value *v,int idx) { + return new ExtractValueInst(v,idx); + } + + virtual size_t NbOpcode() const { return 3;} + + virtual const char *getOpcodeName() ; + protected: + Value *m_Value; + //std::string m_Name; + int m_Index; + }; + /** + * For LDS automatons, COMPL is always followed by FLG_GLOBAL on wich it operates. + */ + class ComplInst : public Instruction + { + ComplInst(unsigned int op,Instruction *V1) + : Instruction(op) + , m_V1(V1) + {}; + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + public: + static ComplInst *Create(Instruction *B) { + return new ComplInst(AEL_COMPLOpcode,B); + } + virtual size_t NbOpcode() const { return 2;}; + + virtual const char *getOpcodeName() { + static std::string s; + s = Instruction::getOpcodeName(m_Opcode) ; + s+= " ,FLAG_GLOBAL" ; return s.c_str(); }; + protected: + Instruction *m_V1; + }; + + + /** + * Is the AEL_NAME. references an entry point in ael table. + * should be improved + * To be simple, need to know number of parameters ... + */ + class CallInst : public Instruction + { + CallInst(unsigned int op = 0,const std::string &callee = "" + ,BasicBlock *B=NULL) + : m_callee(callee) + , Instruction(op) + {}; + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + + std::string m_callee; + std::vector m_Params; + std::string m_ret; // Store computed opcode instruction + public: + + const char *getOpcodeName() ; + + /* Missing the FunctionType .... + * callee is the called function + */ + static CallInst *Create( const std::string &callee = "" + , BasicBlock *B= NULL) + { + return new CallInst(AEL_CALLOpcode,callee,B); + } + /* + * Parameter should be a Value, Constant Expression, GlobalVariable and so on + */ + void addParam(Value *p) + { m_Params.push_back(p) ; } ; + + std::string getCallee() const + { + return m_callee; + } + + size_t getNbParameters() const + { + return m_Params.size(); + } + Value *getParameter(int i) const + { + return m_Params[i]; + } + /* + * This is wrong with the new virtual machine + * TODO: See how to handle this case + */ + virtual size_t NbOpcode() const + { return 1 + m_Params.size();}; + }; + + /** + * Compare is not part of lds automaton. This is an extension + * + * + */ + class CmpInst : public Instruction + { + CmpInst(unsigned int op,const std::string &s="",bool lc=false); + + CmpInst(unsigned int op,Value *v,const std::string &s="",bool lc=false); + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + + public: + static CmpInst *Create(BasicBlock *B) { + return new CmpInst(AEL_EQUOpcode); + } + static CmpInst *Create(const std::string &B) { + return new CmpInst(AEL_EQUOpcode,B); + } + static CmpInst *Create(Value *v,const std::string &B) { + return new CmpInst(AEL_EQUOpcode,v,B); + } + + virtual size_t NbOpcode() const { return 2;}; + + virtual const char *getOpcodeName(); + + protected: + std::string m_Flag; + std::string m_CmpInst; + bool m_LoadConstant; + unsigned long m_Constant; + aeb::lds::Value *m_Value; + }; + + /* + * This is very specific to automatons. Beeing able to send a message internally. + * + */ + class SendEventInst : public Instruction { + SendEventInst(unsigned int op,const std::string &evt) : Instruction(op) , m_Event(evt) {}; + std::string m_Event; + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + protected: + std::vector m_Params; + public: + static SendEventInst *Create(const Value *evt) { + return new SendEventInst(AEL_LOOP_MSGOpcode,evt->getName()); + }; + // Send Event to other Agent or Pid + static SendEventInst *CreateOutput(const Value *v) { + return new SendEventInst(AEL_OUTPUTOpcode,v->getName()); + }; + virtual size_t NbOpcode() const + { return 2 + m_Params.size();}; + + virtual const char *getOpcodeName(); + + void addParam(Value *p) + { m_Params.push_back(p) ; } ; + + size_t getNbParameters() const + { + return m_Params.size(); + } + Value *getParameter(int i) const + { + return m_Params[i]; + } + protected: + }; + /** + * In lds, GOTO means set the VM into another State. + */ + class GotoStateInst : public Instruction + { + GotoStateInst(unsigned int op,const std::string &s) + : Instruction(op) + ,m_State(s) + {}; + + void *operator new(size_t s) { + return User::operator new(s, 0); + } + public: + static GotoStateInst *Create(const std::string &sn) { + return new GotoStateInst(AEL_ETATOpcode,sn); + }; + + virtual const char *getOpcodeName() { + static std::string s; + s = Instruction::getOpcodeName(m_Opcode) ; + s+= ", " ; s+=m_State; return s.c_str(); }; + protected: + std::string m_State; + virtual size_t NbOpcode() const { return 2 ;}; + }; +} +} +/** + * ex: set et sw=4 ts=4 list: + */ +#endif diff --git a/include/IR/Module.h b/include/IR/Module.h new file mode 100644 index 0000000..901b70f --- /dev/null +++ b/include/IR/Module.h @@ -0,0 +1,114 @@ +#ifndef IR_MODULE_H__ +#define IR_MODULE_H__ + +#include "aeb/dlilist.h" +#include "IR/BasicBlock.h" +#include "IR/Behavior.h" +#include "IR/Function.h" +#include "IR/Signal.h" +#include "IR/Transition.h" +#include "IR/SymbolTableTraits.h" +#include "IR/State.h" +#include "IR/GlobalVariable.h" + +namespace aeb { + +namespace lds { + +/** + * The module contains several lists : + * -> list of functions + * -> list of states + * -> list of events + * -> list of transitions. Which somehow owns an event. An event owns a function signature and even a Body + * Depending on the the State and Transition, the same event might have multiple implementations + * + * Several iterators a required for that purpose. + * + */ +class Module { + public: + typedef SymbolTable StateListType; + typedef SymbolTable FunctionListType; + typedef SymbolTable SignalListType; + typedef SymbolTable GlobalListType; + + typedef StateListType::iterator state_iterator; + typedef FunctionListType::iterator function_iterator; + typedef GlobalListType::iterator global_iterator; + typedef SignalListType::iterator signal_iterator; + protected: + std::string m_Name; + StateListType m_States; + FunctionListType m_Functions; + SignalListType m_Signals; + GlobalListType m_Globals; + public: + Module(const std::string &name ="") ; + virtual ~Module() ; + + // SymbolTable stuff + static GlobalListType Module::*getSublistAccess(GlobalVariable *) + { + return &Module::m_Globals; + } + + static FunctionListType Module::*getSublistAccess(Function *) { + return &Module::m_Functions; + } + + static SignalListType Module::*getSublistAccess(Signal *) { + return &Module::m_Signals; + } + + static StateListType Module::*getSublistAccess(State *) { + return &Module::m_States; + } + + + std::string getName() const {return m_Name; }; + // Wrong Return State !! + Function *getOrInsertFunction(const std::string &_name,Function *f=NULL,Function::FctType fct=Function::Local); + + State *getOrInsertState(const std::string &_name,State *s=NULL); + + Signal *getOrInsertSignal(const std::string &_name); + + Function *getFunction(const std::string &_name); + + // Iterator + state_iterator state_begin() {return m_States.begin() ; } + state_iterator state_end() {return m_States.end() ; } + + function_iterator function_begin() {return m_Functions.begin() ; } + function_iterator function_end() {return m_Functions.end() ; } + + global_iterator global_begin() {return m_Globals.begin() ; } + global_iterator global_end() {return m_Globals.end() ; } + + signal_iterator signal_begin() {return m_Signals.begin() ; } + signal_iterator signal_end() {return m_Signals.end() ; } + // + // + // + State *getState(const std::string &_name); + + const GlobalListType &getGlobalList() const; + + const FunctionListType &getFunctionList() const; + + GlobalVariable *getGlobal(const std::string &_name); + + void insertGlobal(GlobalVariable *g); + // Simple Function when GlobalVariable is just a Flag + GlobalVariable *insertGlobal(const std::string &_flag,bool c,Type *_Ty = NULL); +}; + + + +} +} +#endif +/** + * ex: set et sw=4 ts=4 list: + */ diff --git a/include/IR/OperandTraits.h b/include/IR/OperandTraits.h new file mode 100644 index 0000000..16096be --- /dev/null +++ b/include/IR/OperandTraits.h @@ -0,0 +1,53 @@ +#ifndef __OPERAND_TRAITS_H__ +#define __OPERAND_TRAITS_H__ + +namespace aeb { +namespace lds { + +template +struct FixedNumOperandTraits { + static Use *op_begin(SubClass* U) { + return reinterpret_cast(U) - ARITY; + } + static Use *op_end(SubClass* U) { + return reinterpret_cast(U); + } + static unsigned operands(const User*) { + return ARITY; + } +}; + +} +} + + +#define DECLARE_OPERAND_ACCESS(VALUE) \ + public: \ + inline op_iterator op_begin(); \ + inline const_op_iterator op_begin() const; \ + inline op_iterator op_end(); \ + inline const_op_iterator op_end() const; \ + protected: \ + template Use &Op(); \ + public: + +#define DEFINE_OPERAND_ACCESS(CLASS,VALUE) \ + template Use &CLASS::Op() { \ + return this->OpFrom(this); \ + } \ + CLASS::op_iterator CLASS::op_begin() { \ + return OperandTraits::op_begin(this); \ +} \ +CLASS::const_op_iterator CLASS::op_begin() const { \ + return OperandTraits::op_begin(const_cast(this)); \ +} \ +CLASS::op_iterator CLASS::op_end() { \ + return OperandTraits::op_end(this); \ +} \ +CLASS::const_op_iterator CLASS::op_end() const { \ + return OperandTraits::op_end(const_cast(this)); \ +} \ + + + +#endif diff --git a/include/IR/Signal.h b/include/IR/Signal.h new file mode 100644 index 0000000..9d44d93 --- /dev/null +++ b/include/IR/Signal.h @@ -0,0 +1,91 @@ +#ifndef IR_SIGNAL_H__ +#define IR_SIGNAL_H__ + +#include "aeb/dlilist.h" +#include "IR/BasicBlock.h" +#include "IR/Behavior.h" +#include "IR/Argument.h" +#include "IR/SymbolTableTraits.h" + +namespace aeb { + +namespace lds { +class State; +class Function; +class Module; + + +/** + * A Signal is a function + * Method of a state that can have parameters ... + * + * + */ +class Signal : public Behavior + , public aeb::dlilist_node +{ + + public: + /* Tells if the function is a declaration or a local implementation .... */ + enum FctType { + Local + ,ExternalLink + }; + + typedef aeb::SymbolTable ArgumentListType; + + typedef ArgumentListType::iterator ArgumentIterator; + typedef ArgumentListType::const_iterator ArgumentConstIterator; + protected: + Module *m_Parent; + FctType m_FctType; + long m_NbParam; + ArgumentListType m_ArgumentList; + public: + Signal(const std::string &s="DefFct",FctType fc=ExternalLink) ; + + static Signal *Create(const std::string &name,FctType ft = ExternalLink) + { + return new Signal(name,ft); + } + Module *getParent() { return m_Parent;}; + + const Module *getParent() const { return m_Parent;}; + + void setParent(Module *p) { m_Parent = p; }; + + bool isExternal() const { return m_FctType == ExternalLink; }; + // SymbolTable stuff + static ArgumentListType Signal::*getSublistAccess(SigArgument *) + { + return &Signal::m_ArgumentList; + } + + // TODO Temporary, needs to be removed + inline long getNbParams() { return args().size(); }; + inline void setNbParams(long i) { m_NbParam = i; }; + // + inline ArgumentListType &args() + { return m_ArgumentList;}; + // + bool operator ==(const std::string &s) const + { return ! m_Name.compare(s); } + + bool operator !=(const std::string &s) const + { return m_Name.compare(s); } + + // Iterators + ArgumentIterator arg_begin() { return m_ArgumentList.begin() ; } + ArgumentIterator arg_end() { return m_ArgumentList.end() ; } + + ArgumentConstIterator arg_begin() const + { return m_ArgumentList.begin() ; } + + ArgumentConstIterator arg_end() const + { return m_ArgumentList.end() ; } +}; + + +} +} +#endif diff --git a/include/IR/State.h b/include/IR/State.h new file mode 100644 index 0000000..762b8b2 --- /dev/null +++ b/include/IR/State.h @@ -0,0 +1,68 @@ +#ifndef IR_STATE_H__ +#define IR_STATE_H__ + +#include "aeb/dlilist.h" +#include "IR/BasicBlock.h" +#include "IR/Transition.h" +#include "IR/SymbolTableTraits.h" + +namespace aeb { +namespace lds { + class State; +} + +namespace lds { +class Signal; +/** + * The State contains several lists : + * -> list of states + * -> list of events + * -> list of transitions. Which somehow is a function + * + * Several iterators a required for that purpose. + * + */ +class State : public aeb::dlilist_node { + public: + //typedef aeb::dlilist TransitionListType; + typedef SymbolTable TransitionListType; + + typedef TransitionListType::iterator transition_iterator; + typedef TransitionListType::const_iterator const_transition_iterator; + + protected: + std::string m_Name; + TransitionListType m_Transitions; + Module *m_Parent; + public: + State(const std::string &_n="") : m_Name(_n) ,m_Parent(NULL) {}; + virtual ~State() { + } ; + + static TransitionListType State::*getSublistAccess(lds::Transition *) { + return &State::m_Transitions; + } + + void setParent(Module *m) { m_Parent = m ; }; + + Module *getParent() { return m_Parent; } + const Module *getParent() const { return m_Parent; } + std::string getName() const { return m_Name; }; + // Wrong Return State !! + Transition *getOrInsertTransition(const std::string &_name,Transition *t); + // A Transition, reacts on an event, executs Function and goes to State ... + // What if the state is not yet created ? (forward declaration....) + void insertTransition(Transition *t,Signal *evt,Function *fct,const std::string &st); + + // Iterators + transition_iterator transition_begin() { return m_Transitions.begin() ; } + transition_iterator transition_end() { return m_Transitions.end() ; } + // + Transition *getTransition(const std::string &_name); +}; + + + +} +} +#endif diff --git a/include/IR/SymbolTableTraits.h b/include/IR/SymbolTableTraits.h new file mode 100644 index 0000000..39e1daa --- /dev/null +++ b/include/IR/SymbolTableTraits.h @@ -0,0 +1,133 @@ +#ifndef SYMBOLTABLETRAITS_H__ +#define SYMBOLTABLETRAITS_H__ + +#include "aeb/dlilist.h" + +namespace aeb { + + template class dlilist_iterator; + template class dlilist; + template struct dlilist_traits ; + + template + struct SymbolTableListSentinelTraits : public dlilist_embedded_sentinel_traits {}; + +template struct SymbolTableParentType {}; +namespace lds { + class Function; + class Behaviour; + class Argument; + class SigArgument; + class Intruction; + class Signal; + class BasicBlock; + class GlobalVariable; + class Transition; + class State; +} + +#define DEF_SYMBOL_TABLE_PARENT_TYPE(node,parent) \ + template<> struct SymbolTableParentType {typedef lds::parent type; }; + +DEF_SYMBOL_TABLE_PARENT_TYPE(Instruction,BasicBlock) +//DEF_SYMBOL_TABLE_PARENT_TYPE(BasicBlock,Function) +DEF_SYMBOL_TABLE_PARENT_TYPE(BasicBlock,Behavior) +DEF_SYMBOL_TABLE_PARENT_TYPE(Argument,Function) +DEF_SYMBOL_TABLE_PARENT_TYPE(SigArgument,Signal) +DEF_SYMBOL_TABLE_PARENT_TYPE(Function,Module) +DEF_SYMBOL_TABLE_PARENT_TYPE(GlobalVariable,Module) +DEF_SYMBOL_TABLE_PARENT_TYPE(Signal,Module) +DEF_SYMBOL_TABLE_PARENT_TYPE(State,Module) +DEF_SYMBOL_TABLE_PARENT_TYPE(Transition,State) + +#undef DEF_SYMBOL_TABLE_PARENT_TYPE + +template class SymbolTable; +#if 0 +/** + * Inspired from llvm that is quiet complicated + * + * The first idea is to check if the callback mecanism works + * 05/02/2015 it just does not work... + */ +template +class SymbolTableTraits : public dlilist_default_traits { + + typedef dlilist_traits TraitsClass; + public: + + /** + * would never be able to write such a thing + */ + ParentClass *getListOwner() { + // Did not work because of dlilist template parameter wich was wrong + size_t Offset(size_t(&((ParentClass*)NULL->*ParentClass:: + getSublistAccess(static_cast(NULL))))); + + // This cast does not work :-( + aeb::dlilist* Anchor(static_cast< aeb::dlilist * const >(this) ); + + return reinterpret_cast(reinterpret_cast(Anchor)- + Offset); + } + + SymbolTableTraits() { }; + + void addNodeToList(SubClass *V) ; + + void removeNodeFromList(SubClass *V); + + void transferNodeFromList(dlilist_traits &L2, + dlilist_iterator first, + dlilist_iterator last); + +} ; +#endif +/** + * New + */ +template +class SymbolTableListTraits + : public dlilist_prevnext_traits + , public SymbolTableListSentinelTraits + , public dlilist_node_traits +{ + public: + typedef SymbolTable ListTy; + typedef typename SymbolTableParentType::type ItemParent; + + SymbolTableListTraits() { }; + + private: + /** + * would never be able to write such a thing + */ + ItemParent *getListOwner() { + // Did not work because of dlilist template parameter wich was wrong + size_t Offset(size_t(&((ItemParent*)NULL->*ItemParent:: + getSublistAccess(static_cast(NULL))))); + + // This cast does not work :-( + ListTy* Anchor(static_cast< ListTy * const >(this) ); + + return reinterpret_cast(reinterpret_cast(Anchor)- + Offset); + } + + public: + void addNodeToList(SubClass *V) ; + + void removeNodeFromList(SubClass *V); + + void transferNodeFromList(SymbolTableListTraits &L2, + dlilist_iterator first, + dlilist_iterator last); + +} ; + + +template +class SymbolTable : public aeb::dlilist > {}; + +} +#endif diff --git a/include/IR/SymbolTableTraitsImpl.h b/include/IR/SymbolTableTraitsImpl.h new file mode 100644 index 0000000..a0c0fd9 --- /dev/null +++ b/include/IR/SymbolTableTraitsImpl.h @@ -0,0 +1,81 @@ +#ifndef SYMBOLTABLELISTTRAITSIMPL_H__ +#define SYMBOLTABLELISTTRAITSIMPL_H__ + +#include "IR/SymbolTableTraits.h" + +namespace aeb { + +/* New Implementation ....*/ +#if defined(FUNCTION_SYMTAB) +template <> +void SymbolTableListTraits::addNodeToList(aeb::lds::Argument *s) +{ + ItemParent *p = getListOwner(); + if ( !p || s->getParent() != NULL) + { + std::cerr<<"SymbolTable::addNodeToList Big Problem Parent:"; + } + else + { + s->setParent(p); + // std::cout<<"SymbolTableListTraits "<getName()<<" before: "<getNbParams(); + if (! p->isExternal()) + p->setNbParams(p->getNbParams()+1); + // std::cout<<" After:"<getNbParams()< +void SymbolTableListTraits::addNodeToList(aeb::lds::BasicBlock *s) +{ + ItemParent *p = getListOwner(); + if ( !p || s->getParent() != NULL) + { + std::cerr<<"SymbolTable::addNodeToList BB Big Problem Parent:"; + } + else + { + s->setParent(p); +#if 0 + // DEBUG + std::cout<<"SymbolTableListTraits BB "<getName(); + std::cout<<" add node : "<getName()<<"\n"; +#endif + } +} +#endif +template +void SymbolTableListTraits::addNodeToList(SubClass *s) +{ + ItemParent *p = getListOwner(); + if ( !p || s->getParent() != NULL) + { + std::cerr<<"SymbolTable::addNodeToList Big Problem Parent:"; + } + else + { + s->setParent(p); + } +} + +template +void SymbolTableListTraits::removeNodeFromList(SubClass *S) +{ + //std::cerr<<"SymbolTable::removeNodeFromList \n"; + S->setParent(NULL); +} + +template +void SymbolTableListTraits +::transferNodeFromList(SymbolTableListTraits &L2, + dlilist_iterator first, + dlilist_iterator last) + +{ + std::cout<<"SymbolTableTraits::transferNodeFromList "< struct dlilist_traits + : public SymbolTableTraits { + + dlilist_traits() : SymbolTableTraits::SymbolTableTraits() { + std::cout<<"dlilist_traits:: construct "<::destroySentinel"<::provideInitialHead "<::ensureHead "<::createSentinel"<(&Sentinel); + } + + static void noteHead(lds::BasicBlock *,lds::BasicBlock *) { + std::cout<<"dlilist_traits::noteHead"< Sentinel; + }; + +#endif +namespace lds { +class State; +class Signal; +class Function; +class Module; + +#if 0 +/** + * The behavior class is a generic class for everything that contains behavioral instructions. + * - A function implementation is a behaviors. + * - A transition contains a behavior that is triggers on several events. I could say that several + * events implement the same behaviors + * + */ + +class Behavior + { + + typedef aeb::dlilist BlockListType; + typedef BlockListType::iterator iterator; + typedef BlockListType::const_iterator const_iterator; + protected: + + BlockListType m_Blocks; + std::string m_Name; + + Behavior(const Behavior &p) ; + public: + + Behavior(const std::string & m_Name = "") ; + + virtual ~Behavior() ; + + static dlilist Behavior::*getSublistAccess(BasicBlock *) { + return &Behavior::m_Blocks; + } + + + // Iterators, + iterator begin() { return m_Blocks.begin() ; }; + const_iterator begin() const { return m_Blocks.begin(); }; + iterator end() { return m_Blocks.end() ; } + const_iterator end() const { return m_Blocks.end() ; }; + + void setName(const std::string &name) { m_Name = name; } + + const char *getName() const { return m_Name.c_str() ; }; + /// Access to the List to modify it + BlockListType &getBlockList() { + return m_Blocks ; + }; + + const BlockListType &getBlockList() const { + return m_Blocks ; + }; + +}; +#endif + +/** + * \brief Transition contains BasicBlocks and Events declaration ... + * The events shall be reported to the State the transition belongs to. + * + * The Parent of the Transition is the State. + * The childs of a Transition are Blocks. + * + * + */ +class Transition : + public aeb::dlilist_node +{ + + protected: + + std::string m_Name; + State *m_Parent; + Signal *m_Event; + std::string m_TargetState; + Function *m_Function; + + Transition(const Transition &p) ; + public: + + Transition(const std::string & m_Name = "SentinelDef",State *Parent = NULL) ; + + virtual ~Transition() ; + + + /// Constructors are private + static Transition *Create(const std::string &name,State *Parent = NULL) { + return new Transition(name,Parent); + }; + + void setName(const std::string &name) { m_Name = name; } + const char *getName() const { return m_Name.c_str() ; }; + + State *getParent() { return m_Parent;}; + + const State *getParent() const { return m_Parent;}; + + void setParent(State *p) { m_Parent = p; }; + + // Setters; + void setEvent(Signal *s) { m_Event = s ; }; + const std::string &getEvent() const ; + + void setTargetState(const std::string &s) { m_TargetState = s ; }; + + std::string getTargetState() const ; + + void setFunction(Function *s) { m_Function = s ; }; + Function *getFunction() const { return m_Function; }; +}; + + +} +} +#endif +/** + * ex: set et sw=4 ts=4 list: + */ diff --git a/include/IR/Type.h b/include/IR/Type.h new file mode 100644 index 0000000..2aa746b --- /dev/null +++ b/include/IR/Type.h @@ -0,0 +1,106 @@ +#ifndef TYPE_H +#define TYPE_H + +namespace aeb { + +namespace lds { + +/** + * Values have type. It's either a BuiltinType or a Constructed type. + * The information must be known to be able to generate richer Intermadiate + * syntax. + */ +class Type +{ + public: + enum TypeID + { + // Primitive Types + VoidTyID = 0, + FloatTyID , + LabelTyID , + PidTyID , + // Derived ID's + IntegerTyID , + NaturalTyID , + TimeTyID , + DurationTyID, + FunctionTyID, + StructTyID , + ArrayTyID , + PointerTyID + }; + protected: + TypeID m_TypeID; + Type(TypeID tid) ; + /// Array of contained types + Type *m_ContainedTypes; + unsigned m_NbContainedTys; + public: + TypeID getTypeID() const { return m_TypeID; } + // Simple output function + void print(std::ostream &os) const; + void printLds(std::ostream &os) const; + void printNative(std::ostream &os) const; + + bool isVoidTy() const { return getTypeID() == VoidTyID; }; + bool isFloatTy() const { return getTypeID() == FloatTyID; }; + bool isPidTy() const { return getTypeID() == PidTyID; }; + bool isFunctionTy() const { return getTypeID() == FunctionTyID; }; + bool isArrayTy() const { return getTypeID() == ArrayTyID; }; + bool isPointerTy() const { return getTypeID() == PointerTyID; }; + bool isIntegerTy() const { return getTypeID() == IntegerTyID; }; + bool isNaturalTy() const { return getTypeID() == NaturalTyID; }; + bool isTimeTy() const { return getTypeID() == TimeTyID; }; + bool isDurationTy() const { return getTypeID() == DurationTyID; }; + + /*Helper function to get instance of type*/ + static Type *getPrimitiveType(TypeID tyid); +}; + + +/* Put Derived Types here for now */ + +class CompositeType : public Type { + protected: + CompositeType(TypeID id) : Type(id) {} + public: + virtual const Type *getTypeAtIndex(unsigned ) const; +}; + +/** + * Contains a set of element Types. + * I should be able to return, the number of elements and + * travel through them (iterator... ). + */ +class StructType : public CompositeType { + protected: + StructType() : CompositeType(StructTyID) {} + public: + /* Create Type known to IR */ + static StructType *create(const std::vector &_params); + /* Element Iterator */ + /* Random access */ + unsigned int getNumElements() const { return m_NbContainedTys; } + virtual const Type *getTypeAtIndex(unsigned Idx ) const { + assert( Idx < m_NbContainedTys && "Element out of range!"); + return & m_ContainedTypes[Idx]; + } + +}; + +/** + * An array should have a type and a number of elements. + * All elements have the same type. + */ +class ArrayType : public CompositeType { + protected: + ArrayType() : CompositeType(ArrayTyID) {} + + public: + +}; + +} +} +#endif /*TYPE_H*/ diff --git a/include/IR/Use.h b/include/IR/Use.h new file mode 100644 index 0000000..3bfd204 --- /dev/null +++ b/include/IR/Use.h @@ -0,0 +1,84 @@ +#ifndef __USE_H__ +#define __USE_H__ + +namespace aeb { +namespace lds { + +class Value; +/** + * Use class makes the connection between a User and it's value. It contains + * the edge of the two end points + */ +class Use +{ + Use(const Use &c) {}; + protected: + Value *m_Value; + + Use() : m_Value(NULL) {}; + virtual ~Use() + { + std::cout<<"~Use"<() { return m_Value; } + const Value * operator ->() const { return m_Value; } + protected: + // Add internal list traverval feature. + Use *m_Next; + Use **m_Prev; // Array of Pointers + + void setPrev(Use **useList) + { + //std::cout<<"Use("< +struct OperandTraits; + +class User; + +// Template specialisation for User +template <> +struct OperandTraits +{ + static inline Use * op_begin(User *); + static inline Use * op_end(User *); + + static inline unsigned int operands(User *); +}; + +/** + * This class implements the mechanism that + * makes the connection between an object + * that uses another one. + * + * This class uses a special allocator to prepend + * uses before User class. This is achieved by implementing + * standard allocator + */ +class User : public Value +{ + Use *m_Operands; + unsigned int m_NumOperands; + public: + /** + * + */ + /// operator delete - free memory allocated for User and Use objects + void operator delete(void *Usr); + /// placement delete - required by std, but never called. + void operator delete(void*, unsigned) { + std::cout<<"Constructor throws?"< + Use &OpFrom(const U *obj) + { + return (idx < 0) + ? OperandTraits::op_end(const_cast(obj))[idx] + : OperandTraits::op_begin(const_cast(obj))[idx]; + } + template + Use &Op() { + return OpFrom(this); + }; + template + const Use &Op() const { + return OpFrom(this); + }; + + void * operator new(size_t s,unsigned Us); + public: + + unsigned int getNumOperands() const { return m_NumOperands; } + /** Operand Iterator Interface */ + typedef Use *op_iterator; + typedef const Use *const_op_iterator; + + inline op_iterator op_begin() { return m_Operands;} + inline const_op_iterator op_begin() const { return m_Operands;} + inline op_iterator op_end() { return m_Operands + m_NumOperands;} + inline const_op_iterator op_end() const { return m_Operands + m_NumOperands;} + +}; + +// Template OperandTraits specialisation implementation +// Only here because we use User declared methodes +inline Use * OperandTraits::op_begin(User *u) +{ + return u->op_begin(); +} + +inline Use * OperandTraits::op_end(User *u) +{ + return u->op_end(); +} + +inline unsigned int OperandTraits::operands(User *u) +{ + return u->getNumOperands(); +} + + +// End namspace +}}; +/* + * vim: et sw=2 ts=2 list: + */ +#endif diff --git a/include/IR/Value.h b/include/IR/Value.h new file mode 100644 index 0000000..440e0ec --- /dev/null +++ b/include/IR/Value.h @@ -0,0 +1,119 @@ +#ifndef VALUE_H +#define VALUE_H + + +#include "IR/Use.h" + +namespace aeb { + + +namespace lds { + +class Type; +class State; +class Function; +class Argument; +class Instruction; +class GlobalVariable; +class Module; + +/** + * Once it comes to intermediate language we get closer to the computer and memory storage. + * At then end, everithing that needs to be generated are bytes stored in memory + * These bytes must be well organized aligned and structured. Each data generated is a value. + * That means that Instructions are value, GlobalVariables are values, Functions are values, Arguments + * are values. + * The purpose of this class is to keep track of the kind of value we are handling. + * + * Each value has a type and can have a name. Example a GlobalVariable. + * An Argument. + */ +class Value +{ + Type *m_VTy; + std::string m_Name; + unsigned m_SubClassID; // SubClass of Value , eg Intruction, Function, Argument + bool m_Used; + protected: + Use *m_UseList; // Pointer to Use List + // Can only be created by sub classes + Value(Type *_Ty,unsigned vid); + // + Value(const Value &_g) : m_Name(_g.m_Name),m_UseList(NULL) {}; + public: + virtual ~Value() + { } + + const Type *getType() const { return m_VTy; }; + + void setType(Type *_Ty) { m_VTy = _Ty; } ; + /// + void setName(const std::string &n); + + const std::string &getName() const; + /// We need to know if a value is used or not. + bool isUsed() const { return m_Used; }; + + void addUse(Use &u) + { + // TODO For debug purpose to be removed + //std::cout<<"Value("<getName()<addUse(*this); + m_Value = v; +} + +} +} + +/** + * ex: sw=2 et list: + */ +#endif /*VALUE_H*/ diff --git a/include/IR/ldsOpcode.h b/include/IR/ldsOpcode.h new file mode 100644 index 0000000..c82eed2 --- /dev/null +++ b/include/IR/ldsOpcode.h @@ -0,0 +1,57 @@ +#ifndef OPCODE +# define OPCODE(NUM,OP,SIZE,CLASS) +#endif +#ifndef OPCODE_TABLE +# define OPCODE_TABLE(OP,SIZE) +#endif + +#ifndef HANDLE_BINARY_INST +#ifndef OPCODE +# define HANDLE_BINARY_INST(NUM,OP,SIZE,CLASS) +#else +# define HANDLE_BINARY_INST(NUM,OP,SIZE,CLASS) OPCODE(NUM,OP,SIZE,CLASS) +#endif +#endif + +OPCODE_TABLE(FLAG_TABLE,1) +OPCODE_TABLE(CASE_TABLE,1) +OPCODE_TABLE(JUMP_TABLE,1) + +OPCODE( 1,AEL_NOP,1,Instruction) +OPCODE( 2,AEL_RETURN,1,ReturnInst) /* Put at the end of the excution of event action. */ +OPCODE( 3,AEL_ETAT,1,Instruction) /* Switch to state goto translation */ +OPCODE( 4,AEL_JUMP_PLUS,2,BranchInst) +OPCODE( 5,AEL_JUMP_PLUS_IF,2,BranchCondInst) +OPCODE( 6,AEL_JUMP_PLUS_IF_NOT,2,BranchCondInst) +OPCODE( 7,AEL_JUMP_MOINS,2,BranchInst) +OPCODE( 8,AEL_JUMP_IND,3,BranchInst) /* Jump Indirect used for switch case, jump_ind end idx ,,, end contains jump_mois idx */ +OPCODE( 9,AEL_JSR,1,BranchInst) /* Jump Subroutine */ +OPCODE(10,AEL_JSR_IND,1,BranchInst) /* Jump Subroutine Indirect */ +OPCODE(11,AEL_RTS,1,ReturnInst) /* EXIT end the execution put at end of procedure go back to caller */ +OPCODE(12,AEL_SET,2,Instruction) /* Set value to true*/ +OPCODE(13,AEL_RESET,2,Instruction) /* Set value to false */ +OPCODE(14,AEL_CHARGE,2,LoadInst) /* Load GLOBAL R into REGISTER (second parameter) used to Store result */ +OPCODE(15,AEL_TEST,2,Instruction) /* Load REGISTER into GLOBAL R*/ + +OPCODE(16,AEL_LOOP_MSG,1,Instruction) /* Send Internal event*/ +OPCODE(17,AEL_CALL,1,CallInst) /* Special opcode ... call user defined function .... */ + +OPCODE(20,AEL_COMPL,2,BinaryOperator) /* Not operation */ + +HANDLE_BINARY_INST(21,AEL_AND,1,BinaryOperator) /* Binary operands binary AND operation */ +HANDLE_BINARY_INST(22,AEL_OR,1,BinaryOperator) /* Binary operands binary OR operation */ +HANDLE_BINARY_INST(23,AEL_PLUS,1,BinaryOperator) /* Binary operands binary Addition operation */ +HANDLE_BINARY_INST(24,AEL_MOIN,1,BinaryOperator) /* Binary operands binary Minus operation */ +HANDLE_BINARY_INST(25,AEL_MUL,1,BinaryOperator) /* Binary operands binary Multiplication operation */ +HANDLE_BINARY_INST(26,AEL_EQU,1,BinaryOperator) /* Binary operands binary compare EQ,NE,GT,LT operation */ + +OPCODE(27,AEL_OUTPUT,1,Instruction) /* Special opcode ... call user defined function .... */ +OPCODE(28,AEL_ALLOCA,1,Instruction) /* Special opcode ... call user defined function .... */ +OPCODE(29,AEL_EXTRACT,1,Instruction) /* Special opcode ... call user defined function .... */ + /* Missing AEL_CREATE to create an agent */ +/* Begining of user defined AELS */ +OPCODE(30,AEL_END,1,Instruction) + +#undef OPCODE +#undef OPCODE_TABLE +#undef HANDLE_BINARY_INST diff --git a/include/LDSBytecode/AutomatonBytecode.h b/include/LDSBytecode/AutomatonBytecode.h new file mode 100644 index 0000000..32707cc --- /dev/null +++ b/include/LDSBytecode/AutomatonBytecode.h @@ -0,0 +1,37 @@ +#ifndef AUTOMATONBYTECODE_H +#define AUTOMATONBYTECODE_H + +namespace lds +{ + +/** + * This class is responsible to generate the + * automaton bytecode. maybe read and write + * The structure of the binary file is as follow + * -> long Magic Number + * -> long Version Number + * -> short Constant_poll_count + * -> cp_info Constant pool[] + * -> + * -> short State_pool_count can be until 1000 states ! + * -> state_info State_pool[] + * + * -> + */ +class AutomatonBytecode +{ + public: + // Default Constructor, Stream can be file or streambuff + AutomatonBytecode(std::ostream &os); + // Default Destructor + ~AutomatonBytecode(); + // Generate Bytecode + void Generate(aeb::lds::Module &m); + void Generate(AST::TranslationUnitDecl *); + protected: + std::ostream &m_ostream; +}; + + +} +#endif /*AUTOMATONBYTECODE_H*/ diff --git a/include/LDSBytecode/BytecodeReader.h b/include/LDSBytecode/BytecodeReader.h new file mode 100644 index 0000000..de6cf1b --- /dev/null +++ b/include/LDSBytecode/BytecodeReader.h @@ -0,0 +1,18 @@ +#ifndef BYTECODEREADER_H +#define BYTECODEREADER_H + +namespace lds { + +/** + * Read and LDS bytecode file this should + * help the Engine construct the required + * binary structures for the excution of + * the code + * + */ +class BytecodeReader +{ +}; + +}; +#endif /*BYTECODEREADER_H*/ diff --git a/include/LDSBytecode/BytecodeWriter.h b/include/LDSBytecode/BytecodeWriter.h new file mode 100644 index 0000000..84420dc --- /dev/null +++ b/include/LDSBytecode/BytecodeWriter.h @@ -0,0 +1,23 @@ +#ifndef BYTECODEWRITER_H +#define BYTECODEWRITER_H + +namespace lds { + +/** + * Does the byte code writer need the file ? + * I'm not sure. + */ +class BytecodeWriter +{ + public: + BytecodeWriter(std::ostream &o); + + ~BytecodeWriter(); + + void WriteInstruction(aeb::lds::Instrcution &i); + protected: +}; + +}; + +#endif /*BYTECODEWRITER_H*/ diff --git a/include/LDSExecutionEngine/LdsExecutionContext.h b/include/LDSExecutionEngine/LdsExecutionContext.h new file mode 100644 index 0000000..4fd983f --- /dev/null +++ b/include/LDSExecutionEngine/LdsExecutionContext.h @@ -0,0 +1,112 @@ +#ifndef LDSEXECUTIONCONTEXT_H +#define LDSEXECUTIONCONTEXT_H + +#define MIN_EC_STACK_SIZE 20 +#define MAX_EC_STACK_SIZE (2 * MIN_EC_STACK_SIZE) +#define FLAG_GLOBAL 0 + +namespace lds { + +typedef long Instruction; + +/** CallInformation Status */ +#define CIST_OAH (1<<0) /* */ +#define CIST_SDL (1<<2) /* Running SDL function */ +#define CIST_HOOKED (1<<3) /* Running Hook Functon */ +#define CIST_FRESH (1<<4) /* Initial Call */ +/** + * Call Information is part of the execution context. + * Keeps track of the current call and handles call + * another function .... to be able to come back + */ +struct CallInformation +{ + public: + CallInformation(); + + inline void incPC(int i = 1) { m_pc += i; }; + inline void decPC(int i = 1) { m_pc -= i; }; + inline void setPC(long i = 0) { m_pc = (Instruction *)i; }; + inline Instruction *getPC(void ) { return m_pc; }; + + StackIdx m_func; /* Function location in stack */ + TypeValue *m_top; /* Top position in the stack */ + // I should separate LDS calls from C calls + StackIdx m_base; /* In case of SDL base stack */ + Instruction *m_pc; /* Program/Inst Counter in PC */ + // Linked list of CallInformation + CallInformation *m_previous; + CallInformation *m_next; /* Dynamic call link */ + int m_call_status; /* Call status */ +}; + + +/** + * This class will contains the heap (allocated mem) + * Program loaded from bytecode + */ +struct GlobalContext +{ + +}; + +/** + * The execution context is used by The engine + * to run the program. + * + */ +struct ExecutionContext +{ + public: + // + ExecutionContext(); + // + ~ExecutionContext(); + /** + * Load Byte code into Context. + * -> Initial m_base_ci with the entry point function + * -> + */ + void Load(const std::string &file_name); + /* Naming */ + inline void incIP(int i = 1) { m_ci->incPC(i); }; + inline void decIP(int i = 1) { m_ci->decPC(i); }; + inline void setIP(int i = 0) { m_ci->setPC(i); }; + inline long getIP(void ) { return (long )m_ci->getPC(); }; + inline long getOpcode(long IP) { return (long)*m_ci->getPC() ;}; + // + inline void setState( long state ) {; }; + inline long getState( void ) { return 0 ; }; + // + inline TypeValue &Register(long reg) { return m_registers[reg];}; + inline TypeValue &Accumulator() { return m_registers[0]; }; + // + // + inline CallInformation *get_ci() { return m_ci ; }; + + inline StackIdx get_top() { return m_top; }; + + int precall(StackIdx func,int nresults); + + void postcall(StackIdx func,int nresults); + protected: + /* Last free entry in stack */ + StackIdx m_last_stack; + /* First free block in stack */ + StackIdx m_top; + /* Pointer to the stack */ + StackIdx m_stack; + /* Current Call Inforamtion */ + CallInformation *m_ci; + /* Initial Call Information */ + CallInformation m_base_ci; + /**/ + int m_status; + TypeValue m_registers[10]; + private: + // I don't want to use dynamic allocation for stack + TypeValue m_ec_stack[MAX_EC_STACK_SIZE]; +}; +}; + +#endif /*LDSEXECUTIONCONTEXT_H*/ diff --git a/include/LDSExecutionEngine/LdsExecutionEngine.h b/include/LDSExecutionEngine/LdsExecutionEngine.h new file mode 100644 index 0000000..4f9c109 --- /dev/null +++ b/include/LDSExecutionEngine/LdsExecutionEngine.h @@ -0,0 +1,40 @@ +#ifndef LDSEXECUTIONENGINE_H +#define LDSEXECUTIONENGINE_H + + +namespace lds +{ + +enum OpCodes { + NullOpcode = -1 +#define OPCODE(NUM,OP,SIZE,CLASS) , OP +#include "IR/ldsOpcode.h" +} ; + +/** + * The LDS Virtual Machine + */ +class ExecutionEngine +{ + public: + typedef void (*pEEFunction)(ExecutionContext &); + + ExecutionEngine() + { +#define OPCODE(NUM,OP,SIZE,CLASS) m_BuiltinOp[lds::OP] = &ExecutionEngine::OP ; +#include "IR/ldsOpcode.h" + }; + + void Load(const std::string &file_name,ExecutionContext &e); + + void run(ExecutionContext &c); + protected: + pEEFunction m_BuiltinOp[lds::AEL_END+1]; + // AEL BUILT IN OPERATIONS +#define OPCODE(NUM,OP,SIZE,CLASS) static void OP(ExecutionContext &) ; +#include "IR/ldsOpcode.h" +}; + +}; + +#endif /*LDSEXECUTIONENGINE_H*/ diff --git a/include/LDSExecutionEngine/LdsObject.h b/include/LDSExecutionEngine/LdsObject.h new file mode 100644 index 0000000..08a1edc --- /dev/null +++ b/include/LDSExecutionEngine/LdsObject.h @@ -0,0 +1,77 @@ +#ifndef LDSOBJECT_H +#define LDSOBJECT_H + + +namespace lds { + + class ExecutionContext ; + typedef int (*ldsCFunction)(lds::ExecutionContext *); + +#define LDS_TFUNCTION 0 +#define LDS_TSTRING 1 +#define LDS_TNUMBER 2 + +/* Variation of basic types */ + +#define LDS_TCFUNC (LDS_TFUNCTION | (0<<4)) /* raw C function */ +#define LDS_TLFUNC (LDS_TFUNCTION | (1<<4)) /* LDS TASK */ + +#define LDS_TNUMINT (LDS_TNUMBER | (0<<4)) +#define LDS_TNUMREAL (LDS_TNUMBER | (1<<4)) + + +/** + * Type Value Handled by the LDS Virtual Machine + * Missing Function / Object types + */ +typedef struct _LdsTypeValue { + + union { + void *p; /* Unknown data */ + int b; /* boolean */ + long l; /* Integer */ + double d; /* Real */ + ldsCFunction f; /* CFunction */ + } m_value; + int m_type; /* Object Type bits 4-5 variation / bit 3-0 TYPE */ + + /* Lets define some operators */ + _LdsTypeValue &operator ||(const _LdsTypeValue &v) + { + assert(m_type == v.m_type); + return *this; + }; + // + _LdsTypeValue &operator &&(const _LdsTypeValue &v) + { + assert(m_type == v.m_type); + return *this; + }; + // + bool operator !() + { + return true; + } + // + _LdsTypeValue &operator =(const _LdsTypeValue &v) + { + assert(m_type == v.m_type); + return *this; + } + // + _LdsTypeValue &operator =(const long v) + { + assert(m_type == LDS_TNUMINT); + return *this; + } + // Cast to bool + operator const bool() + { + return m_value.b; + } +} TypeValue; + +typedef TypeValue *StackIdx; + +} +#endif /*LDSOBJECT_H*/