diff options
Diffstat (limited to 'src/frontend/clang.cpp')
-rw-r--r-- | src/frontend/clang.cpp | 790 |
1 files changed, 790 insertions, 0 deletions
diff --git a/src/frontend/clang.cpp b/src/frontend/clang.cpp new file mode 100644 index 0000000..e7b74ed --- /dev/null +++ b/src/frontend/clang.cpp @@ -0,0 +1,790 @@ +// +// Created by ztuowen on 10/10/16. +// + +#include <typeinfo> +#include <sstream> +#include "ir_chill.hh" +#include "loop.hh" +#include "chill_error.hh" + +#include "clang/Frontend/FrontendActions.h" +#include <clang/CodeGen/CodeGenAction.h> +#include <clang/Frontend/CompilerInstance.h> +#include <clang/Frontend/CompilerInvocation.h> +#include <clang/Basic/DiagnosticOptions.h> +#include <clang/Frontend/TextDiagnosticPrinter.h> +#include <clang/AST/ASTContext.h> +#include <clang/AST/RecordLayout.h> +#include <clang/AST/Decl.h> +#include <clang/Parse/ParseAST.h> +#include <clang/Basic/TargetInfo.h> + +#include <llvm/ADT/IntrusiveRefCntPtr.h> +#include <llvm/Support/Host.h> + +#include "code_gen/CG_chillRepr.h" +#include "code_gen/CG_chillBuilder.h" +#include <vector> +#include <chilldebug.h> + +#include "chillAST.h" + +using namespace clang; +using namespace clang::driver; +using namespace omega; +using namespace std; + +#define NL_RET(x) {chillAST_NodeList *ret = new chillAST_NodeList(); \ + ret->push_back(x); \ + return ret;} + +static string binops[] = { + " ", " ", // BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators. + "*", "/", "%", // BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators. + "+", "-", // BO_Add, BO_Sub, // [C99 6.5.6] Additive operators. + "<<", ">>", // BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators. + "<", ">", "<=", ">=", // BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators. + "==", "!=", // BO_EQ, BO_NE, // [C99 6.5.9] Equality operators. + "&", // BO_And, // [C99 6.5.10] Bitwise AND operator. + "??", // BO_Xor, // [C99 6.5.11] Bitwise XOR operator. + "|", // BO_Or, // [C99 6.5.12] Bitwise OR operator. + "&&", // BO_LAnd, // [C99 6.5.13] Logical AND operator. + "||", // BO_LOr, // [C99 6.5.14] Logical OR operator. + "=", "*=", // BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators. + "/=", "%=", // BO_DivAssign, BO_RemAssign, + "+=", "-=", // BO_AddAssign, BO_SubAssign, + "???", "???", // BO_ShlAssign, BO_ShrAssign, + "&&=", "???", // BO_AndAssign, BO_XorAssign, + "||=", // BO_OrAssign, + ","}; // BO_Comma // [C99 6.5.17] Comma operator. + + +static string unops[] = { + "++", "--", // [C99 6.5.2.4] Postfix increment and decrement + "++", "--", // [C99 6.5.3.1] Prefix increment and decrement + "@", "*", // [C99 6.5.3.2] Address and indirection + "+", "-", // [C99 6.5.3.3] Unary arithmetic + "~", "!", // [C99 6.5.3.3] Unary arithmetic + "__real", "__imag", // "__real expr"/"__imag expr" Extension. + "__extension" // __extension__ marker. +}; + +chillAST_NodeList* ConvertTypeDefDecl(clang::TypedefDecl *TDD); + +chillAST_NodeList* ConvertRecordDecl(clang::RecordDecl *D); + +chillAST_NodeList* ConvertDeclStmt(clang::DeclStmt *clangDS); + +chillAST_NodeList* ConvertCompoundStmt(clang::CompoundStmt *clangCS); + +chillAST_NodeList* ConvertFunctionDecl(clang::FunctionDecl *D); + +chillAST_NodeList* ConvertForStmt(clang::ForStmt *clangFS); + +chillAST_NodeList* ConvertUnaryOperator(clang::UnaryOperator *clangU); + +chillAST_NodeList* ConvertBinaryOperator(clang::BinaryOperator *clangBO); + +chillAST_NodeList* ConvertArraySubscriptExpr(clang::ArraySubscriptExpr *clangASE); + +chillAST_NodeList* ConvertDeclRefExpr(clang::DeclRefExpr *clangDRE); + +chillAST_NodeList* ConvertIntegerLiteral(clang::IntegerLiteral *clangIL); + +chillAST_NodeList* ConvertFloatingLiteral(clang::FloatingLiteral *clangFL); + +chillAST_NodeList* ConvertImplicitCastExpr(clang::ImplicitCastExpr *clangICE); + +chillAST_NodeList* ConvertCStyleCastExpr(clang::CStyleCastExpr *clangICE); + +chillAST_NodeList* ConvertReturnStmt(clang::ReturnStmt *clangRS); + +chillAST_NodeList* ConvertCallExpr(clang::CallExpr *clangCE); + +chillAST_NodeList* ConvertIfStmt(clang::IfStmt *clangIS); + +chillAST_NodeList* ConvertMemberExpr(clang::MemberExpr *clangME); + + +chillAST_NodeList* ConvertTranslationUnit(clang::TranslationUnitDecl *TUD, char *filename); + +/*! + * \brief Convert fon Clang AST to CHiLL AST also append to parent node p if necessary + * + * @param s Clang statement + * @return A set of new statements + */ +chillAST_NodeList* ConvertGenericClangAST(clang::Stmt *s); + +// forward defs +SourceManager *globalSRCMAN; // ugly. shame. + +char *splitTypeInfo(char *underlyingtype); + +chillAST_Node* unwrap(chillAST_NodeList* nl){ + chillAST_Node* n; + if (!nl || !nl->size()) n = NULL; + else n = (*nl)[0]; + delete nl; + return n; +} + +chillAST_NodeList* ConvertVarDecl(VarDecl *D) { + bool isParm = false; + + QualType T0 = D->getType(); + QualType T = T0; + if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { // My GOD clang stinks + T = Parm->getOriginalType(); + isParm = true; + } + + char *vartype = strdup(T.getAsString().c_str()); + char *arraypart = splitTypeInfo(vartype); + + char *varname = strdup(D->getName().str().c_str()); + + chillAST_VarDecl *chillVD = new chillAST_VarDecl(vartype, varname, arraypart, (void *) D); + + chillVD->isAParameter = isParm; + + int numdim = 0; + chillVD->knownArraySizes = true; + if (index(vartype, '*')) chillVD->knownArraySizes = false; // float *a; for example + if (index(arraypart, '*')) chillVD->knownArraySizes = false; + + // note: vartype here, arraypart in next code.. is that right? + if (index(vartype, '*')) { + for (int i = 0; i < strlen(vartype); i++) if (vartype[i] == '*') numdim++; + chillVD->numdimensions = numdim; + } + + if (index(arraypart, '[')) { // JUST [12][34][56] no asterisks + char *dupe = strdup(arraypart); + + int len = strlen(arraypart); + for (int i = 0; i < len; i++) if (dupe[i] == '[') numdim++; + + chillVD->numdimensions = numdim; + int *as = (int *) malloc(sizeof(int *) * numdim); + if (!as) { + fprintf(stderr, "can't malloc array sizes in ConvertVarDecl()\n"); + exit(-1); + } + chillVD->arraysizes = as; // 'as' changed later! + + + char *ptr = dupe; + while (ptr = index(ptr, '[')) { + ptr++; + int dim; + sscanf(ptr, "%d", &dim); + *as++ = dim; + + ptr = index(ptr, ']'); + } + free(dupe); + } + + Expr *Init = D->getInit(); + if (Init) { + fprintf(stderr, " = VARDECL HAS INIT. (TODO) (RIGHT NOW)"); + exit(-1); + } + + free(vartype); + free(varname); + + VariableDeclarations.push_back(chillVD); + + NL_RET(chillVD); +} + + +chillAST_NodeList* ConvertRecordDecl(clang::RecordDecl *RD) { // for structs and unions + int count = 0; + for (clang::RecordDecl::field_iterator fi = RD->field_begin(); fi != RD->field_end(); fi++) count++; + + char blurb[128]; + + chillAST_TypedefDecl *astruct = new chillAST_TypedefDecl(blurb, "", NULL); + astruct->setStruct(true); + astruct->setStructName(RD->getNameAsString().c_str()); + + for (clang::RecordDecl::field_iterator fi = RD->field_begin(); fi != RD->field_end(); fi++) { + clang::FieldDecl *FD = (*fi); + string TypeStr = FD->getType().getAsString(); + const char *typ = TypeStr.c_str(); + const char *name = FD->getNameAsString().c_str(); + chillAST_VarDecl *VD = NULL; + // very clunky and incomplete + VD = new chillAST_VarDecl(typ, name, "", astruct); // can't handle arrays yet + astruct->subparts.push_back(VD); + } + NL_RET(astruct); +} + + +chillAST_NodeList* ConvertTypeDefDecl(TypedefDecl *TDD) { + char *under = strdup(TDD->getUnderlyingType().getAsString().c_str()); + char *arraypart = splitTypeInfo(under); + char *alias = strdup(TDD->getName().str().c_str()); + chillAST_TypedefDecl *CTDD = new chillAST_TypedefDecl(under, alias, arraypart); + free(under); + free(arraypart); + NL_RET(CTDD); +} + + +chillAST_NodeList* ConvertDeclStmt(DeclStmt *clangDS) { + chillAST_VarDecl *chillvardecl; // the thing we'll return if this is a single declaration + bool multiples = !clangDS->isSingleDecl(); + DeclGroupRef dgr = clangDS->getDeclGroup(); + clang::DeclGroupRef::iterator DI = dgr.begin(); + clang::DeclGroupRef::iterator DE = dgr.end(); + chillAST_NodeList* decls = new chillAST_NodeList(); + for (; DI != DE; ++DI) { + Decl *D = *DI; + const char *declty = D->getDeclKindName(); + if (!strcmp("Var", declty)) { + VarDecl *V = dyn_cast<VarDecl>(D); + std::string Name = V->getNameAsString(); + char *varname = strdup(Name.c_str()); + QualType T = V->getType(); + string TypeStr = T.getAsString(); + char *vartype = strdup(TypeStr.c_str()); + CHILL_DEBUG_PRINT("DeclStmt (clang 0x%x) for %s %s\n", D, vartype, varname); + char *arraypart = splitTypeInfo(vartype); + chillvardecl = new chillAST_VarDecl(vartype, varname, arraypart, (void *) D); + // store this away for declrefexpr that references it! + VariableDeclarations.push_back(chillvardecl); + decls->push_back(chillvardecl); + // TODO + if (V->hasInit()) { + CHILL_ERROR(" ConvertDeclStmt() UNHANDLED initialization\n"); + exit(-1); + } + } + } + return decls; +} + + +chillAST_NodeList* ConvertCompoundStmt(CompoundStmt *clangCS) { + // make an empty CHILL compound statement + chillAST_CompoundStmt *chillCS = new chillAST_CompoundStmt; + // for each clang child + for (auto I = clangCS->child_begin(); I != clangCS->child_end(); ++I) { // ?? loop looks WRONG + // create the chill ast for each child + Stmt *child = *I; + chillAST_NodeList* nl = ConvertGenericClangAST(child); + // usually n will be a statement. We just add it as a child. + // SOME DeclStmts have multiple declarations. They will add themselves and return NULL + chillCS->addChildren(*nl); + delete nl; + } + NL_RET(chillCS); +} + + +chillAST_NodeList* ConvertFunctionDecl(FunctionDecl *D) { + QualType QT = D->getReturnType(); + string ReturnTypeStr = QT.getAsString(); + // Function name + DeclarationName DeclName = D->getNameInfo().getName(); + string FuncName = DeclName.getAsString(); + chillAST_FunctionDecl *chillFD = new chillAST_FunctionDecl(ReturnTypeStr.c_str(), FuncName.c_str(), D); + + int numparams = D->getNumParams(); + CHILL_DEBUG_PRINT(" %d parameters\n", numparams); + for (int i = 0; i < numparams; i++) { + VarDecl *clangvardecl = D->getParamDecl(i); // the ith parameter (CLANG) + ParmVarDecl *pvd = D->getParamDecl(i); + QualType T = pvd->getOriginalType(); + CHILL_DEBUG_PRINT("OTYPE %s\n", T.getAsString().c_str()); + + chillAST_NodeList* nl = ConvertVarDecl(clangvardecl); + chillAST_VarDecl* decl = (chillAST_VarDecl*)unwrap(nl); + + VariableDeclarations.push_back(decl); + chillFD->addParameter(decl); + CHILL_DEBUG_PRINT("chillAST ParmVarDecl for %s from chill location 0x%x\n", decl->varname, clangvardecl); + } // for each parameter + + if (D->getBuiltinID()) { + chillFD->setExtern(); + CHILL_DEBUG_PRINT("%s is builtin (extern)\n", FuncName.c_str()); + }; + + Stmt *clangbody = D->getBody(); + if (clangbody) { + // may just be fwd decl or external, without an actual body + chillAST_NodeList* nl = ConvertGenericClangAST(clangbody); + chillFD->setBody(unwrap(nl)); + } + + FunctionDeclarations.push_back(chillFD); + NL_RET(chillFD); +} + + +chillAST_NodeList* ConvertForStmt(ForStmt *clangFS) { + chillAST_Node *init = unwrap(ConvertGenericClangAST(clangFS->getInit())); + chillAST_Node *cond = unwrap(ConvertGenericClangAST(clangFS->getCond())); + chillAST_Node *incr = unwrap(ConvertGenericClangAST(clangFS->getInc())); + chillAST_Node *body = unwrap(ConvertGenericClangAST(clangFS->getBody())); + if (body->getType() != CHILLAST_NODE_COMPOUNDSTMT) { + // make single statement loop bodies loop like other loops + CHILL_DEBUG_PRINT("ForStmt body of type %s\n", body->getTypeString()); + chillAST_CompoundStmt *cs = new chillAST_CompoundStmt(); + cs->addChild(body); + body = cs; + } + chillAST_ForStmt *chill_loop = new chillAST_ForStmt(init, cond, incr, body); + NL_RET(chill_loop); +} + + +chillAST_NodeList* ConvertIfStmt(IfStmt *clangIS) { + Expr *cond = clangIS->getCond(); + Stmt *thenpart = clangIS->getThen(); + Stmt *elsepart = clangIS->getElse(); + + chillAST_Node *con = unwrap(ConvertGenericClangAST(cond)); + chillAST_Node *thn = NULL; + if (thenpart) { + thn = unwrap(ConvertGenericClangAST(thenpart)); + if (!thn->isCompoundStmt()) { + chillAST_Node* tmp=new chillAST_CompoundStmt(); + tmp->addChild(thn); + thn = tmp; + } + } + chillAST_Node *els = NULL; + if (elsepart) { + els = unwrap(ConvertGenericClangAST(elsepart)); + if (!els->isCompoundStmt()) { + chillAST_Node* tmp=new chillAST_CompoundStmt(); + tmp->addChild(els); + els = tmp; + } + } + + chillAST_IfStmt *ifstmt = new chillAST_IfStmt(con, thn, els); + NL_RET(ifstmt); +} + + +chillAST_NodeList* ConvertUnaryOperator(UnaryOperator *clangUO) { + const char *op = unops[clangUO->getOpcode()].c_str(); + bool pre = clangUO->isPrefix(); + chillAST_Node *sub = unwrap(ConvertGenericClangAST(clangUO->getSubExpr())); + + chillAST_UnaryOperator *chillUO = new chillAST_UnaryOperator(op, pre, sub); + NL_RET(chillUO); +} + + +chillAST_NodeList* ConvertBinaryOperator(BinaryOperator *clangBO) { + + // get the clang parts + Expr *lhs = clangBO->getLHS(); + Expr *rhs = clangBO->getRHS(); + BinaryOperator::Opcode op = clangBO->getOpcode(); // this is CLANG op, not CHILL op + + + // convert to chill equivalents + chillAST_Node *l = unwrap(ConvertGenericClangAST(lhs)); + const char *opstring = binops[op].c_str(); + chillAST_Node *r = unwrap(ConvertGenericClangAST(rhs)); + // TODO chill equivalent for numeric op. + + // build up the chill Binary Op AST node + chillAST_BinaryOperator *binop = new chillAST_BinaryOperator(l, opstring, r); + + NL_RET(binop); +} + + +chillAST_NodeList* ConvertArraySubscriptExpr(ArraySubscriptExpr *clangASE) { + Expr *clangbase = clangASE->getBase(); + Expr *clangindex = clangASE->getIdx(); + + chillAST_Node *bas = unwrap(ConvertGenericClangAST(clangbase)); + chillAST_Node *indx = unwrap(ConvertGenericClangAST(clangindex)); + + // TODO clangAST contamination + chillAST_ArraySubscriptExpr *chillASE = new chillAST_ArraySubscriptExpr(bas, indx, NULL, clangASE); + NL_RET(chillASE); +} + + +chillAST_NodeList* ConvertDeclRefExpr(DeclRefExpr *clangDRE) { + DeclarationNameInfo DNI = clangDRE->getNameInfo(); + + ValueDecl *vd = static_cast<ValueDecl *>(clangDRE->getDecl()); // ValueDecl ?? VarDecl ?? + + QualType QT = vd->getType(); + string TypeStr = QT.getAsString(); + + DeclarationName DN = DNI.getName(); + const char *varname = DN.getAsString().c_str(); + chillAST_DeclRefExpr *chillDRE = new chillAST_DeclRefExpr(TypeStr.c_str(), varname, NULL); + + // find the definition (we hope) TODO Wrong treatment + if ((!strcmp("Var", vd->getDeclKindName())) || (!strcmp("ParmVar", vd->getDeclKindName()))) { + // it's a variable reference + int numvars = VariableDeclarations.size(); + chillAST_VarDecl *chillvd = NULL; + for (int i = 0; i < numvars; i++) { + if (VariableDeclarations[i]->uniquePtr == vd) + chillvd = VariableDeclarations[i]; + } + if (!chillvd) { + fprintf(stderr, "\nWARNING, ir_clang.cc clang DeclRefExpr %s refers to a declaration I can't find! at ox%x\n", + varname, vd); + fprintf(stderr, "variables I know of are:\n"); + for (int i = 0; i < numvars; i++) { + chillAST_VarDecl *adecl = VariableDeclarations[i]; + if (adecl->isParmVarDecl()) fprintf(stderr, "(parameter) "); + fprintf(stderr, "%s %s at location 0x%x\n", adecl->vartype, adecl->varname, adecl->uniquePtr); + } + fprintf(stderr, "\n"); + } + + if (chillvd == NULL) { + CHILL_ERROR("chillDRE->decl = 0x%x\n", chillvd); + exit(-1); + } + + chillDRE->decl = (chillAST_Node *) chillvd; + } else if (!strcmp("Function", vd->getDeclKindName())) { + int numfuncs = FunctionDeclarations.size(); + chillAST_FunctionDecl *chillfd = NULL; + for (int i = 0; i < numfuncs; i++) { + if (FunctionDeclarations[i]->uniquePtr == vd) + chillfd = FunctionDeclarations[i]; + } + if (chillfd == NULL) { + CHILL_ERROR("chillDRE->decl = 0x%x\n", chillfd); + exit(-1); + } + chillDRE->decl = (chillAST_Node *) chillfd; + } else { + CHILL_ERROR("clang DeclRefExpr refers to declaration of %s of kind %s\n", varname, vd->getDeclKindName()); + exit(-1); + } + NL_RET(chillDRE); +} + + +chillAST_NodeList* ConvertIntegerLiteral(IntegerLiteral *clangIL) { + bool isSigned = clangIL->getType()->isSignedIntegerType(); + const char *printable = clangIL->getValue().toString(10, isSigned).c_str(); + int val = stoi(printable); + chillAST_IntegerLiteral *chillIL = new chillAST_IntegerLiteral(val); + NL_RET(chillIL); +} + + +chillAST_NodeList* ConvertFloatingLiteral(FloatingLiteral *clangFL) { + // Get an appriximate value of the APFloat + float val = clangFL->getValueAsApproximateDouble(); + SmallString<16> Str; + clangFL->getValue().toString(Str); + + SourceLocation sloc = clangFL->getLocStart(); + SourceLocation eloc = clangFL->getLocEnd(); + + std::string start = sloc.printToString(*globalSRCMAN); + const char *filename = globalSRCMAN->getBufferName(sloc); + + if (filename && strlen(filename) > 0) {} + else { + fprintf(stderr, "\nConvertFloatingLiteral() filename is NULL?\n"); + sloc = globalSRCMAN->getSpellingLoc(sloc); // should get spelling loc? + start = sloc.printToString(*globalSRCMAN); + filename = globalSRCMAN->getBufferName(sloc); + } + + unsigned int offset = globalSRCMAN->getFileOffset(sloc); + FILE *fp = fopen(filename, "r"); + fseek(fp, offset, SEEK_SET); // go to the part of the file where the float is defined + char buf[10240]; + fgets(buf, sizeof(buf), fp); // read a line starting where the float starts + fclose(fp); + // buf has the line we want grab the float constant out of it + char *ptr = buf; + if (*ptr == '-') ptr++; // ignore possible minus sign + int len = strspn(ptr, ".-0123456789f"); + buf[len] = '\0'; + chillAST_FloatingLiteral *chillFL = new chillAST_FloatingLiteral(val,1, buf); + NL_RET(chillFL); +} + + +chillAST_NodeList* ConvertImplicitCastExpr(ImplicitCastExpr *clangICE) { + chillAST_Node *sub = unwrap(ConvertGenericClangAST(clangICE->getSubExpr())); + chillAST_ImplicitCastExpr *chillICE = new chillAST_ImplicitCastExpr(sub); + + NL_RET(chillICE); +} + + +chillAST_NodeList* ConvertCStyleCastExpr(CStyleCastExpr *clangCSCE) { + const char *towhat = strdup(clangCSCE->getTypeAsWritten().getAsString().c_str()); + + chillAST_Node *sub = unwrap(ConvertGenericClangAST(clangCSCE->getSubExprAsWritten())); + chillAST_CStyleCastExpr *chillCSCE = new chillAST_CStyleCastExpr(towhat, sub); + NL_RET(chillCSCE); +} + + +chillAST_NodeList* ConvertReturnStmt(ReturnStmt *clangRS) { + chillAST_Node *retval = unwrap(ConvertGenericClangAST(clangRS->getRetValue())); // NULL is handled + + chillAST_ReturnStmt *chillRS = new chillAST_ReturnStmt(retval); + NL_RET(chillRS); +} + + +chillAST_NodeList* ConvertCallExpr(CallExpr *clangCE) { + chillAST_Node *callee = unwrap(ConvertGenericClangAST(clangCE->getCallee())); + chillAST_CallExpr *chillCE = new chillAST_CallExpr(callee); + int numargs = clangCE->getNumArgs(); + Expr **clangargs = clangCE->getArgs(); + for (int i = 0; i < numargs; i++) + chillCE->addArg(unwrap(ConvertGenericClangAST(clangargs[i]))); + + NL_RET(chillCE); +} + + +chillAST_NodeList* ConvertParenExpr(ParenExpr *clangPE) { + chillAST_Node *sub = unwrap(ConvertGenericClangAST(clangPE->getSubExpr())); + chillAST_ParenExpr *chillPE = new chillAST_ParenExpr(sub); + + NL_RET(chillPE); +} + + +chillAST_NodeList* ConvertTranslationUnit(TranslationUnitDecl *TUD, char *filename) { + static DeclContext *DC = TUD->castToDeclContext(TUD); + + chillAST_SourceFile *topnode = new chillAST_SourceFile(filename); + topnode->setFrontend("clang"); + topnode->chill_array_counter = 1; + topnode->chill_scalar_counter = 0; + + // now recursively build clang AST from the children of TUD + DeclContext::decl_iterator start = DC->decls_begin(); + DeclContext::decl_iterator end = DC->decls_end(); + for (DeclContext::decl_iterator DI = start; DI != end; ++DI) { + Decl *D = *DI; + chillAST_Node *child; + // Skip internal declarations of clang + + if (isa<FunctionDecl>(D)) { + child = unwrap(ConvertFunctionDecl(dyn_cast<FunctionDecl>(D))); + } else if (isa<VarDecl>(D)) { + child = unwrap(ConvertVarDecl(dyn_cast<VarDecl>(D))); + } else if (isa<TypedefDecl>(D)) { + child = unwrap(ConvertTypeDefDecl(dyn_cast<TypedefDecl>(D))); + } else if (isa<RecordDecl>(D)) { + CHILL_DEBUG_PRINT("\nTUD RecordDecl\n"); + child = unwrap(ConvertRecordDecl(dyn_cast<RecordDecl>(D))); + } else if (isa<TypeAliasDecl>(D)) { + CHILL_ERROR("TUD TypeAliasDecl TODO \n"); + exit(-1); + } else { + CHILL_ERROR("\nTUD a declaration of type %s (%d) which I can't handle\n", D->getDeclKindName(), D->getKind()); + exit(-1); + } + topnode -> addChild(child); + + if (D->isImplicit() || !globalSRCMAN->getFilename(D->getLocation()).equals(filename)) child->isFromSourceFile = false; + } + + NL_RET(topnode); +} + +chillAST_NodeList* ConvertMemberExpr(clang::MemberExpr *clangME) { + chillAST_Node *base = unwrap(ConvertGenericClangAST(clangME->getBase())); + + DeclarationNameInfo memnameinfo = clangME->getMemberNameInfo(); + DeclarationName DN = memnameinfo.getName(); + const char *member = DN.getAsString().c_str(); + + chillAST_MemberExpr *ME = new chillAST_MemberExpr(base, member, clangME); + + NL_RET(ME); + +} + +chillAST_NodeList* ConvertGenericClangAST(Stmt *s) { + + if (s == NULL) return NULL; + Decl *D = (Decl *) s; + + chillAST_NodeList *ret = NULL; // find the SINGLE constant or data reference at this node or below + + if (isa<CompoundStmt>(s)) { + ret = ConvertCompoundStmt(dyn_cast<CompoundStmt>(s)); + } else if (isa<DeclStmt>(s)) { + ret = ConvertDeclStmt(dyn_cast<DeclStmt>(s)); + } else if (isa<ForStmt>(s)) { + ret = ConvertForStmt(dyn_cast<ForStmt>(s)); + } else if (isa<BinaryOperator>(s)) { + ret = ConvertBinaryOperator(dyn_cast<BinaryOperator>(s)); + } else if (isa<ArraySubscriptExpr>(s)) { + ret = ConvertArraySubscriptExpr(dyn_cast<ArraySubscriptExpr>(s)); + } else if (isa<DeclRefExpr>(s)) { + ret = ConvertDeclRefExpr(dyn_cast<DeclRefExpr>(s)); + } else if (isa<FloatingLiteral>(s)) { + ret = ConvertFloatingLiteral(dyn_cast<FloatingLiteral>(s)); + } else if (isa<IntegerLiteral>(s)) { + ret = ConvertIntegerLiteral(dyn_cast<IntegerLiteral>(s)); + } else if (isa<UnaryOperator>(s)) { + ret = ConvertUnaryOperator(dyn_cast<UnaryOperator>(s)); + } else if (isa<ImplicitCastExpr>(s)) { + ret = ConvertImplicitCastExpr(dyn_cast<ImplicitCastExpr>(s)); + } else if (isa<CStyleCastExpr>(s)) { + ret = ConvertCStyleCastExpr(dyn_cast<CStyleCastExpr>(s)); + } else if (isa<ReturnStmt>(s)) { + ret = ConvertReturnStmt(dyn_cast<ReturnStmt>(s)); + } else if (isa<CallExpr>(s)) { + ret = ConvertCallExpr(dyn_cast<CallExpr>(s)); + } else if (isa<ParenExpr>(s)) { + ret = ConvertParenExpr(dyn_cast<ParenExpr>(s)); + } else if (isa<IfStmt>(s)) { + ret = ConvertIfStmt(dyn_cast<IfStmt>(s)); + } else if (isa<MemberExpr>(s)) { + ret = ConvertMemberExpr(dyn_cast<MemberExpr>(s)); + } else if (isa<FunctionDecl>(D)) { + ret = ConvertFunctionDecl( dyn_cast<FunctionDecl>(D)); + } else if (isa<VarDecl>(D)) { + ret = ConvertVarDecl( dyn_cast<VarDecl>(D) ); + } else if (isa<TypedefDecl>(D)) { + ret = ConvertTypeDefDecl( dyn_cast<TypedefDecl>(D)); + } else { + // more work to do + if (isa<Decl>(D)) CHILL_ERROR("Decl of kind %s unhandled\n", D->getDeclKindName() ); + if (isa<Stmt>(s)) CHILL_ERROR("Stmt of type %s unhandled\n", s->getStmtClassName()); + exit(-1); + } + + return ret; +} + +class NULLASTConsumer : public ASTConsumer { +}; + +aClangCompiler::aClangCompiler(char *filename) { + SourceFileName = strdup(filename); + + // Arguments to pass to the clang frontend + std::vector<const char *> args; + args.push_back(strdup(filename)); + + // The compiler invocation needs a DiagnosticsEngine so it can report problems + diagnosticOptions = new DiagnosticOptions(); // private member of aClangCompiler + + pTextDiagnosticPrinter = new clang::TextDiagnosticPrinter(llvm::errs(), + diagnosticOptions); // private member of aClangCompiler + diagnosticsEngine = new clang::DiagnosticsEngine(diagID, diagnosticOptions, pTextDiagnosticPrinter); + + // Create the compiler invocation + // This class is designed to represent an abstract "invocation" of the compiler, + // including data such as the include paths, the code generation options, + // the warning flags, and so on. + std::unique_ptr<clang::CompilerInvocation> CI(new clang::CompilerInvocation()); + clang::CompilerInvocation::CreateFromArgs(*CI, &args[0], &args[0] + args.size(), *diagnosticsEngine); + // Create the compiler instance + Clang = new clang::CompilerInstance(); // TODO should have a better name ClangCompilerInstance + + + // Get ready to report problems + Clang->createDiagnostics(nullptr, true); + //Clang.createDiagnostics(0, 0); + + + targetOptions = std::make_shared<clang::TargetOptions>(); + targetOptions->Triple = llvm::sys::getDefaultTargetTriple(); + + TargetInfo *pti = TargetInfo::CreateTargetInfo(Clang->getDiagnostics(), targetOptions); + + Clang->setTarget(pti); + Clang->createFileManager(); + FileManager &FileMgr = Clang->getFileManager(); + fileManager = &FileMgr; + Clang->createSourceManager(FileMgr); + SourceManager &SourceMgr = Clang->getSourceManager(); + sourceManager = &SourceMgr; // ?? aclangcompiler copy + globalSRCMAN = &SourceMgr; // TODO global bad + + Clang->setInvocation(CI.get()); // Replace the current invocation + + Clang->createPreprocessor(TU_Complete); + + Clang->createASTContext(); // needs preprocessor + astContext_ = &Clang->getASTContext(); + const FileEntry *FileIn = FileMgr.getFile(filename); // needs preprocessor + SourceMgr.setMainFileID(SourceMgr.createFileID(FileIn, clang::SourceLocation(), clang::SrcMgr::C_User)); + Clang->getDiagnosticClient().BeginSourceFile(Clang->getLangOpts(), &Clang->getPreprocessor()); + + NULLASTConsumer TheConsumer; // must pass a consumer in to ParseAST(). This one does nothing + CHILL_DEBUG_PRINT("actually parsing file %s using clang\n", filename); + ParseAST(Clang->getPreprocessor(), &TheConsumer, Clang->getASTContext()); + // Translation Unit is contents of a file + TranslationUnitDecl *TUD = astContext_->getTranslationUnitDecl(); + // create another AST, very similar to the clang AST but not written by idiots + CHILL_DEBUG_PRINT("converting entire clang AST into chill AST (ir_clang.cc)\n"); + chillAST_Node *wholefile = unwrap(ConvertTranslationUnit(TUD, filename)); + entire_file_AST = (chillAST_SourceFile *) wholefile; + astContext_ = &Clang->getASTContext(); +} + +void findmanually(chillAST_Node *node, char *procname, std::vector<chillAST_Node *> &procs) { + + if (node->getType() == CHILLAST_NODE_FUNCTIONDECL) { + char *name = ((chillAST_FunctionDecl *) node)->functionName; + if (!strcmp(name, procname)) { + procs.push_back(node); + // quit recursing. probably not correct in some horrible case + return; + } + } + + + // this is where the children can be used effectively. + // we don't really care what kind of node we're at. We just check the node itself + // and then its children is needed. + + int numc = node->getNumChildren(); + + for (int i = 0; i < numc; i++) + findmanually(node->getChild(i), procname, procs); + return; +} + +chillAST_FunctionDecl *aClangCompiler::findprocedurebyname(char *procname) { + + std::vector<chillAST_Node *> procs; + findmanually(entire_file_AST, procname, procs); + + if (procs.size() == 0) { + CHILL_ERROR("could not find function named '%s' in AST from file %s\n", procname, SourceFileName); + exit(-1); + } + + if (procs.size() > 1) { + CHILL_ERROR("oddly, found %d functions named '%s' in AST from file %s\n", procs.size(), procname, SourceFileName); + CHILL_ERROR("I am unsure what to do\n"); + exit(-1); + } + + CHILL_DEBUG_PRINT("found the procedure named %s\n", procname); + return (chillAST_FunctionDecl *) procs[0]; + +}
\ No newline at end of file |