#ifndef IR_CLANG_HH #define IR_CLANG_HH #include #include "ir_code.hh" #include "chill_error.hh" #define __STDC_CONSTANT_MACROS #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/ParentMap.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/GlobalDecl.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/ASTConsumers.h" #include "clang/Frontend/FrontendActions.h" #include "clang/CodeGen/CodeGenAction.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/Tool.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Basic/DiagnosticOptions.h" #include "chillAST.h" extern std::vector VariableDeclarations; // a global. TODO typedef llvm::SmallVector StmtList; // TODO delete struct IR_chillScalarSymbol : public IR_ScalarSymbol { chillAST_VarDecl *chillvd; IR_chillScalarSymbol(const IR_Code *ir, chillAST_VarDecl *vd) { fprintf(stderr, "making scalar symbol %s\n", vd->varname); ir_ = ir; chillvd = vd; } std::string name() const; int size() const; bool operator==(const IR_Symbol &that) const; IR_Symbol *clone() const; }; struct IR_chillArraySymbol : public IR_ArraySymbol { //int indirect_; // what was this? int offset_; // what is this? chillAST_VarDecl *chillvd; IR_chillArraySymbol(const IR_Code *ir, chillAST_VarDecl *vd, int offset = 0) { //if ( vd == 0 ) //fprintf(stderr, "IR_chillArraySymbol::IR_chillArraySymbol (%s) vd 0x%x\n", vd->varname, vd); ir_ = ir; chillvd = vd; //indirect_ = indirect; offset_ = offset; } // No Fortran support! IR_ARRAY_LAYOUT_TYPE layout_type() const { return IR_ARRAY_LAYOUT_ROW_MAJOR; } std::string name() const; int elem_size() const; int n_dim() const; omega::CG_outputRepr *size(int dim) const; bool operator!=(const IR_Symbol &that) const; bool operator==(const IR_Symbol &that) const; IR_Symbol *clone() const; // TODO Hack to pass build IR_CONSTANT_TYPE elem_type() const { fprintf(stderr, "Not implemented elem_type in IR_chillArraySymbol"); return IR_CONSTANT_UNKNOWN; }; }; struct IR_chillConstantRef : public IR_ConstantRef { union { omega::coef_t i_; double f_; }; IR_chillConstantRef(const IR_Code *ir, omega::coef_t i) { ir_ = ir; type_ = IR_CONSTANT_INT; i_ = i; } IR_chillConstantRef(const IR_Code *ir, double f) { ir_ = ir; type_ = IR_CONSTANT_FLOAT; f_ = f; } omega::coef_t integer() const { assert(is_integer()); return i_; } bool operator==(const IR_Ref &that) const; omega::CG_outputRepr *convert(); IR_Ref *clone() const; }; enum OP_POSITION { OP_DEST = -1, OP_UNKNOWN, OP_SRC }; #define OP_LEFT OP_DEST #define OP_RIGHT OP_SRC struct IR_chillScalarRef : public IR_ScalarRef { OP_POSITION op_pos_; // -1 means destination operand, 0== unknown, 1 == source operand //chillAST_BinaryOperator *bop; // binary op that contains this scalar? chillAST_DeclRefExpr *dre; // declrefexpr that uses this scalar ref, if that exists chillAST_VarDecl *chillvd; // the vardecl for this scalar IR_chillScalarRef(const IR_Code *ir, chillAST_BinaryOperator *ins, OP_POSITION pos) { fprintf(stderr, "\n***** new IR_xxxxScalarRef( ir, ins, pos ) *****\n\n"); exit(-1); // this constructor takes a binary operation and an indicator of which side of the op to use, // and finds the scalar in the lhs or rhs of the binary op. ir_ = ir; dre = NULL; //bop = ins; // do we need this? if (pos == OP_LEFT) { chillAST_Node *lhs = ins->getLHS(); if (lhs->isDeclRefExpr()) { chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *) lhs; dre = DRE; chillvd = DRE->getVarDecl(); } else if (lhs->isVarDecl()) { chillvd = (chillAST_VarDecl *) lhs; } else { fprintf(stderr, "IR_chillScalarRef constructor, I'm confused\n"); exit(-1); } } else { chillAST_Node *rhs = ins->getRHS(); if (rhs->isDeclRefExpr()) { chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *) rhs; dre = DRE; chillvd = DRE->getVarDecl(); } else if (rhs->isVarDecl()) { chillvd = (chillAST_VarDecl *) rhs; } else { fprintf(stderr, "IR_chillScalarRef constructor, I'm confused\n"); exit(-1); } } op_pos_ = pos; } IR_chillScalarRef(const IR_Code *ir, chillAST_DeclRefExpr *d) { // fprintf(stderr, "\n***** new IR_xxxxScalarRef( ir, REF EXPR sym %s ) *****\n\n", d->getVarDecl()->varname); //fprintf(stderr, "new IR_chillScalarRef with a DECLREFEXPR (has dre) \n"); ir_ = ir; dre = d; //bop = NULL; chillvd = d->getVarDecl(); op_pos_ = OP_UNKNOWN; //fprintf(stderr, "\nScalarRef has:\n"); //fprintf(stderr, "assignment op DOESNT EXIST\n"); //fprintf(stderr, "ins_pos %d\n", ins_pos_); //fprintf(stderr, "op_pos %d\n", op_pos_); //fprintf(stderr, "ref expr dre = 0x%x\n", dre); } IR_chillScalarRef(const IR_Code *ir, chillAST_VarDecl *vardecl) { fprintf(stderr, "\n***** new IR_xxxxScalarRef( ir, sym 0x1234567 ) ***** THIS SHOULD NEVER HAPPEN\n\n"); fprintf(stderr, "vardecl %s\n", vardecl->varname); ir_ = ir; dre = NULL; fprintf(stderr, "new IR_chillScalarRef with a vardecl but no dre\n"); //bop = NULL; chillvd = vardecl; op_pos_ = OP_UNKNOWN; //fprintf(stderr, "\nScalarRef has:\n"); //fprintf(stderr, "assignment op DOESNT EXIST\n"); //fprintf(stderr, "ins_pos %d\n", ins_pos_); //fprintf(stderr, "op_pos %d\n", op_pos_); //fprintf(stderr, "ref expr dre = 0x%x\n", dre); } bool is_write() const; IR_ScalarSymbol *symbol() const; bool operator==(const IR_Ref &that) const; omega::CG_outputRepr *convert(); IR_Ref *clone() const; }; struct IR_chillArrayRef : public IR_ArrayRef { chillAST_ArraySubscriptExpr *chillASE; int iswrite; IR_chillArrayRef(const IR_Code *ir, chillAST_ArraySubscriptExpr *ase, int write) { ir_ = ir; chillASE = ase; iswrite = write; } bool is_write() const; omega::CG_outputRepr *index(int dim) const; IR_ArraySymbol *symbol() const; bool operator!=(const IR_Ref &that) const; bool operator==(const IR_Ref &that) const; omega::CG_outputRepr *convert(); IR_Ref *clone() const; // Not implemented // virtual void Dump() const; }; struct IR_chillLoop : public IR_Loop { int step_size_; chillAST_DeclRefExpr *chillindex; // the loop index variable (I) // was DeclRefExpr chillAST_ForStmt *chillforstmt; chillAST_Node *chilllowerbound; chillAST_Node *chillupperbound; chillAST_Node *chillbody; // presumably a compound statement, but not guaranteeed IR_CONDITION_TYPE conditionoperator; IR_chillLoop(const IR_Code *ir, clang::ForStmt *tf); IR_chillLoop(const IR_Code *ir, chillAST_ForStmt *forstmt); ~IR_chillLoop() {} IR_ScalarSymbol *index() const { return new IR_chillScalarSymbol(ir_, chillindex->getVarDecl()); } omega::CG_outputRepr *lower_bound() const; omega::CG_outputRepr *upper_bound() const; IR_CONDITION_TYPE stop_cond() const; IR_Block *body() const; // Handle following types of increment expressions: // Unary increment/decrement // i += K OR i -= K // i = i + K OR i = i - K // where K is positive int step_size() const { return step_size_; } // K is always an integer ??? IR_Control *clone() const; IR_Block *convert(); virtual void dump() const; }; struct IR_chillBlock : public IR_Block { // ONLY ONE OF bDecl or cs_ will be nonNULL ?? private: //StmtList bDecl_; // declarations in the block?? //clang::CompoundStmt *cs_; // will a block always have a compound statement? (no) //StmtList *stmts; // ?? public: // Block is a basic block?? (no, just a chunk of code ) std::vector statements; IR_chillBlock(const IR_chillBlock *CB) { // clone existing IR_chillBlock ir_ = CB->ir_; for (int i = 0; i < CB->statements.size(); i++) statements.push_back(CB->statements[i]); } IR_chillBlock(const IR_Code *ir, std::vector ast) : statements(ast) { ir_ = ir; } IR_chillBlock(const IR_Code *ir, chillAST_Node *ast = NULL) { // : cs_(NULL), bDecl_(NULL) { ir_ = ir; if (ast != NULL) statements.push_back(ast); } ~IR_chillBlock() {} omega::CG_outputRepr *extract() const; omega::CG_outputRepr *original() const; IR_Control *clone() const; //StmtList getStmtList() const; std::vector getStmtList() const; int numstatements() { return statements.size(); }; void addStatement(chillAST_Node *s); void dump() const; }; #ifdef NOTYET struct IR_clangIf: public IR_If { SgNode *ti_; IR_clangIf(const IR_Code *ir, SgNode *ti) { ir_ = ir; ti_ = ti; } ~IR_clangIf() { } omega::CG_outputRepr *condition() const; IR_Block *then_body() const; IR_Block *else_body() const; IR_Block *convert(); IR_Control *clone() const; }; #endif class aClangCompiler { private: //Chill_ASTConsumer *astConsumer_; clang::ASTContext *astContext_; clang::DiagnosticOptions *diagnosticOptions; clang::TextDiagnosticPrinter *pTextDiagnosticPrinter; llvm::IntrusiveRefCntPtr diagID; clang::DiagnosticsEngine *diagnosticsEngine; clang::CompilerInstance *Clang; clang::Preprocessor *preprocessor; //FileManager *FileMgr; //clang::CompilerInvocation *CI; clang::FileManager *fileManager; clang::SourceManager *sourceManager; // UNUSED? clang::Diagnostic *diagnostic; clang::LangOptions *languageOptions; clang::HeaderSearchOptions *headerSearchOptions; //clang::HeaderSearch *headerSearch; std::shared_ptr targetOptions; clang::TargetInfo *pTargetInfo; clang::PreprocessorOptions *preprocessorOptions; clang::FrontendOptions *frontendOptions; clang::IdentifierTable *idTable; clang::SelectorTable *selTable; clang::Builtin::Context *builtinContext; public: char *SourceFileName; chillAST_SourceFile *entire_file_AST; // TODO move out of public aClangCompiler(char *filename); // constructor chillAST_FunctionDecl *findprocedurebyname(char *name); // someday, return the chill AST clang::FunctionDecl *FD; //Chill_ASTConsumer *getASTConsumer() { return astConsumer_; } clang::ASTContext *getASTContext() { return astContext_; } clang::SourceManager *getASTSourceManager() { return sourceManager; }; }; // singleton class for global clang initialization // TODO: Add support for multiple files in same script class IR_clangCode_Global_Init { private: static IR_clangCode_Global_Init *pinstance; // the one and only // protecting the constructor is the SINGLETON PATTERN. a global by any other name // IR_clangCode_Global_Init(); ~IR_clangCode_Global_Init(); // is this hidden, too? chillAST_FunctionDecl *chillFD; // the original C code clang::ASTContext *astContext_; clang::SourceManager *sourceManager; public: clang::ASTContext *getASTContext() { return astContext_; } clang::SourceManager *getSourceManager() { return sourceManager; }; static IR_clangCode_Global_Init *Instance(char **argv); static IR_clangCode_Global_Init *Instance() { return pinstance; }; aClangCompiler *ClangCompiler; // this is the thing we really just want one of void setCurrentFunction(chillAST_Node *F) { chillFD = (chillAST_FunctionDecl *) F; }; chillAST_FunctionDecl *getCurrentFunction() { return chillFD; }; void setCurrentASTContext(clang::ASTContext *A) { astContext_ = A; }; clang::ASTContext *getCurrentASTContext() { return astContext_; }; void setCurrentASTSourceManager(clang::SourceManager *S) { sourceManager = S; }; clang::SourceManager *getCurrentASTSourceManager() { return sourceManager; }; }; class IR_clangCode : public IR_Code { // for an entire file? A single function? protected: // char *filename; char *procedurename; chillAST_Node *entire_file_AST; chillAST_FunctionDecl *chillfunc; // the function we're currenly modifying std::vector entire_file_symbol_table; // loop symbol table?? for (int i=0; ... ) ?? clang::FunctionDecl *func_; // a clang construct the function we're currenly modifying clang::ASTContext *astContext_; clang::SourceManager *sourceManager; // firstScope; // symboltable1,2,3 ?? // topleveldecls // public: clang::ASTContext *getASTContext() { return astContext_; }; clang::SourceManager *getASTSourceManager() { return sourceManager; }; IR_clangCode(const char *filename, const char *proc_name); ~IR_clangCode(); IR_ScalarSymbol *CreateScalarSymbol(const IR_Symbol *sym, int i); IR_ArraySymbol *CreateArraySymbol(const IR_Symbol *sym, std::vector &size, int i); IR_ScalarRef *CreateScalarRef(const IR_ScalarSymbol *sym); IR_ArrayRef *CreateArrayRef(const IR_ArraySymbol *sym, std::vector &index); virtual bool FromSameStmt(IR_ArrayRef *A, IR_ArrayRef *B); int ArrayIndexStartAt() { return 0; } // TODO FORTRAN std::vector FindScalarRef(const omega::CG_outputRepr *repr) const; std::vector FindArrayRef(const omega::CG_outputRepr *repr) const; std::vector FindOneLevelControlStructure(const IR_Block *block) const; IR_Block *MergeNeighboringControlStructures(const std::vector &controls) const; IR_Block *GetCode() const; void ReplaceCode(IR_Control *old, omega::CG_outputRepr *repr); void ReplaceExpression(IR_Ref *old, omega::CG_outputRepr *repr); IR_CONDITION_TYPE QueryBooleanExpOperation(const omega::CG_outputRepr *) const; IR_OPERATION_TYPE QueryExpOperation(const omega::CG_outputRepr *repr) const; std::vector QueryExpOperand(const omega::CG_outputRepr *repr) const; IR_Ref *Repr2Ref(const omega::CG_outputRepr *) const; friend class IR_chillArraySymbol; friend class IR_chillArrayRef; }; #endif