//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ stmtutils::StmtWrapper Converter::CXXStmtConverter::VisitCXXTryStmt(clang::CXXTryStmt* tryStmt) { //frontend_assert(false && "Try -- Currently not supported!"); core::CompoundStmtPtr body = builder.wrapBody( stmtutils::tryAggregateStmts( builder, Visit(tryStmt->getTryBlock()) ) ); vector<core::CatchClausePtr> catchClauses; unsigned numCatch = tryStmt->getNumHandlers(); for(unsigned i=0;i<numCatch;i++) { clang::CXXCatchStmt* catchStmt = tryStmt->getHandler(i); core::VariablePtr var; if(const clang::VarDecl* exceptionVarDecl = catchStmt->getExceptionDecl() ) { core::TypePtr exceptionTy = convFact.convertType(catchStmt->getCaughtType()); if(convFact.varDeclMap.find(exceptionVarDecl) != convFact.varDeclMap.end()) { //static cast allowed here, because the insertion of //exceptionVarDecls is exclusively done here var = (convFact.varDeclMap[exceptionVarDecl]).as<core::VariablePtr>(); VLOG(2) << convFact.lookUpVariable(catchStmt->getExceptionDecl()).as<core::VariablePtr>(); } else { var = builder.variable(exceptionTy); //we assume that exceptionVarDecl is not in the varDeclMap frontend_assert(convFact.varDeclMap.find(exceptionVarDecl) == convFact.varDeclMap.end() && "excepionVarDecl already in vardeclmap"); //insert var to be used in conversion of handlerBlock convFact.varDeclMap.insert( { exceptionVarDecl, var } ); VLOG(2) << convFact.lookUpVariable(catchStmt->getExceptionDecl()).as<core::VariablePtr>(); } } else { //no exceptiondecl indicates a catch-all (...) var = builder.variable(gen.getAny()); } core::CompoundStmtPtr body = builder.wrapBody(stmtutils::tryAggregateStmts(builder, Visit(catchStmt->getHandlerBlock()))); catchClauses.push_back(builder.catchClause(var, body)); } return stmtutils::tryAggregateStmt(builder, builder.tryCatchStmt(body, catchClauses)); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Takes a clang::CastExpr, converts its subExpr into IR and wraps it with the necessary IR casts ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// core::ExpressionPtr performClangCastOnIR(insieme::frontend::conversion::Converter& converter, const clang::CastExpr* castExpr) { core::ExpressionPtr expr = converter.convertExpr(castExpr->getSubExpr()); core::TypePtr targetTy = converter.convertType(castExpr->getType()); core::TypePtr exprTy = expr->getType(); if(VLOG_IS_ON(2)) { VLOG(2) << "castExpr: "; castExpr->dump(); VLOG(2) << "\n"; } const core::FrontendIRBuilder& builder = converter.getIRBuilder(); //const core::lang::BasicGenerator& basic = builder.getLangBasic(); //core::NodeManager& mgr = converter.getNodeManager(); switch(castExpr->getCastKind()) { //////////////////////////////////////////////////////////////////////////////////////////////////////////// // A conversion which causes the extraction of an r-value from the operand gl-value. // The result of an r-value conversion is always unqualified. // IR: this is the same as ref_deref: ref<a'> -> a' case clang::CK_LValueToRValue: return builder.deref(expr); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Numerical value type conversions // handled by IR numeric_cast case clang::CK_IntegralCast: case clang::CK_IntegralToFloating: case clang::CK_FloatingToIntegral: case clang::CK_FloatingCast: return builder.numericCast(expr, targetTy); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Numeric and pointer to boolean case clang::CK_IntegralToBoolean: case clang::CK_FloatingToBoolean: case clang::CK_PointerToBoolean: return utils::exprToBool(expr); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // A conversion which causes a bit pattern of one type to be reinterpreted as a bit pattern of another type. // Generally the operands must have equivalent size and unrelated types. The pointer conversion // char* -> int* is a bitcast. A conversion from any pointer type to a C pointer type is a bitcast unless // it's actually BaseToDerived or DerivedToBase. A conversion to a block pointer or ObjC pointer type is a // bitcast only if the operand has the same type kind; otherwise, it's one of the specialized casts below. // Vector coercions are bitcasts. case clang::CK_BitCast: return implementBitcast(converter, targetTy, expr); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Integral to pointer. A special kind of reinterpreting conversion. // (char*) 0x1001aab0, reinterpret_cast<int*>(0) case clang::CK_IntegralToPointer: return core::lang::buildPtrFromIntegral(expr, targetTy); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Pointer to integral. A special kind of reinterpreting conversion. // (int)((void*)0x1001aab0) case clang::CK_PointerToIntegral: return core::lang::buildPtrToIntegral(expr, targetTy); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Null pointer constant to pointer, e.g. (int*)0 case clang::CK_NullToPointer: return core::lang::buildPtrNull(targetTy); ////////////////////////////////////////////////////////////////////////////////////////////////////////// // Array to pointer decay. int[10] -> int* char[5][6] -> char(*)[6] case clang::CK_ArrayToPointerDecay: return core::lang::buildPtrFromArray(expr); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // CK_FunctionToPointerDecay - Function to pointer decay. void(int) -> void(*)(int) // CK_BuiltinFnToFnPtr - Same as above, for builtin functions case clang::CK_FunctionToPointerDecay: case clang::CK_BuiltinFnToFnPtr: return core::lang::buildPtrOfFunction(expr); //////////////////////////////////////////////////////////////////////////////////////////////////////////// // NoOps: Conversions that have no effect // * same type casts, CK_NoOp, e.g. int -> int case clang::CK_NoOp: return expr; //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Unused return value: (void)fun() case clang::CK_ToVoid: return builder.unitConsume(expr); //////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_ConstructorConversion: // // Conversion by constructor. struct A { A(int); }; A a = A(10); // { // // this should be handled by backend compiler // // http://stackoverflow.com/questions/1384007/conversion-constructor-vs-conversion-operator-precedence // return expr; // } //////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_FloatingRealToComplex: //case clang::CK_IntegralRealToComplex: // return builder.callExpr(mgr.getLangExtension<core::lang::ComplexExtension>().getConstantToComplex(), expr); ///*A conversion of a floating point real to a floating point complex of the original type. Injects the value as the //* real component with a zero imaginary component. float -> _Complex float. //* */ ///*Converts from an integral real to an integral complex whose element type matches the source. Injects the value as the //* real component with a zero imaginary component. long -> _Complex long. //* */ //////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_FloatingComplexCast: //case clang::CK_FloatingComplexToIntegralComplex: //case clang::CK_IntegralComplexCast: //case clang::CK_IntegralComplexToFloatingComplex: // return mgr.getLangExtension<core::lang::ComplexExtension>().castComplexToComplex(expr, targetTy); ///*Converts between different floating point complex types. _Complex float -> _Complex double. //* */ ///*Converts from a floating complex to an integral complex. _Complex float -> _Complex int. //* */ ///*Converts between different integral complex types. _Complex char -> _Complex long long _Complex unsigned int -> //* _Complex signed int. //* */ ///*Converts from an integral complex to a floating complex. _Complex unsigned -> _Complex float. //* */ //////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_FloatingComplexToReal: //case clang::CK_IntegralComplexToReal: // return mgr.getLangExtension<core::lang::ComplexExtension>().getReal(expr); ///*Converts a floating point complex to floating point real of the source's element type. Just discards the imaginary //* component. _Complex long double -> long double. //* */ ///*Converts an integral complex to an integral real of the source's element type by discarding the imaginary component. //* _Complex short -> short. //* */ /////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_IntegralComplexToBoolean: //case clang::CK_FloatingComplexToBoolean: // /*Converts a complex to bool by comparing against 0+0i. // * */ // return mgr.getLangExtension<core::lang::ComplexExtension>().castComplexToBool(expr); //////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_LValueBitCast: // /* case clang::CK_LValueBitCast - A conversion which reinterprets the address of an l-value as an l-value of a different // * kind. Used for reinterpret_casts of l-value expressions to reference types. bool b; reinterpret_cast<char&>(b) = 'a'; // * */ // { // // if we have a cpp ref we have to unwrap the expression // if(core::analysis::isAnyCppRef(expr->getType())) { expr = builder.toIRRef(expr); } // // the target type is a ref type because lvalue // // bitcasts look like reinterpret_cast<type&>(x) // targetTy = builder.refType(targetTy); // core::CallExprPtr newExpr = builder.callExpr(targetTy, gen.getRefReinterpret(), expr, builder.getTypeLiteral(GET_REF_ELEM_TYPE(targetTy))); // // wrap it as cpp ref // return builder.callExpr(mgr.getLangExtension<core::lang::IRppExtensions>().getRefIRToCpp(), newExpr); // } //////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_MemberPointerToBoolean: // /*case clang::CK_MemberPointerToBoolean - Member pointer to boolean. A check against the null member pointer. // * */ // { // if(expr->getType().isa<core::FunctionTypePtr>()) { // return builder.callExpr(gen.getBoolLNot(), builder.callExpr(gen.getBool(), gen.getFuncIsNull(), expr)); // } // frontend_assert(core::analysis::isMemberPointer(expr->getType())) << " not a memberPointer? " << expr << " : " << expr->getType(); // return core::analysis::getMemberPointerCheck(expr); // } //////////////////////////////////////////////////////////////////////////////////////////////////////////// //// PARTIALY IMPLEMENTED //////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_UncheckedDerivedToBase: //case clang::CK_DerivedToBase: // // A conversion from a C++ class pointer to a base class pointer. A *a = new B(); // { // // TODO: do we need to check if is pointerType? // // in case of pointer, the inner expression is modeled as ref< array < C, 1> > // // it is needed to deref the first element // expr = getCArrayElemRef(builder, expr); // // unwrap CppRef if CppRef // if(core::analysis::isAnyCppRef(exprTy)) { expr = core::analysis::unwrapCppRef(expr); } // clang::CastExpr::path_const_iterator it; // for(it = castExpr->path_begin(); it != castExpr->path_end(); ++it) { // core::TypePtr targetTy = converter.convertType((*it)->getType()); // // if it is no ref we have to materialize it, otherwise refParent cannot be called // if(expr->getType()->getNodeType() != core::NT_RefType) { // // expr = builder.callExpr (mgr.getLangExtension<core::lang::IRppExtensions>().getMaterialize(), expr); // expr = builder.refVar(expr); // } // expr = builder.refParent(expr, targetTy); // } // if(castExpr->getType().getTypePtr()->isPointerType()) { // // is a pointer type -> return pointer // expr = builder.callExpr(gen.getScalarToArray(), expr); // } // VLOG(2) << "cast resoult: \n" << dumpPretty(expr) << " \n of type: " << expr->getType(); // return expr; // } //////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_BaseToDerived: // // A conversion from a C++ class pointer/reference to a derived class pointer/reference. B *b = static_cast<B*>(a); // { // // we want to know the TYPE of static_cast<TYPE>() // targetTy = converter.convertType(llvm::dyn_cast<clang::ExplicitCastExpr>(castExpr)->getType()); // VLOG(2) << exprTy << " " << targetTy; // core::ExpressionPtr retIr; // // pointers: // if(core::analysis::isPointerType(exprTy)) { // assert_true(core::analysis::isPointerType(targetTy)) << "from pointer to non pointer is not possible"; // targetTy = targetTy.as<core::RefTypePtr>()->getElementType(); // return builder.callExpr(mgr.getLangExtension<core::lang::IRppExtensions>().getStaticCast(), expr, builder.getTypeLiteral((targetTy))); // } // // NORE: All value casts are upgraded to CPP ref, this has no implications for the generated code since lvalues in clang are already refs. // // and makes everithing smoother and easyer // if(exprTy.isa<core::RefTypePtr>()) { // expr = builder.toCppRef(expr); // exprTy = expr.getType(); // } // if(core::analysis::isCppRef(exprTy)) { // if(!core::analysis::isCppRef(targetTy)) { targetTy = core::analysis::getCppRef(targetTy); } // retIr = builder.callExpr(mgr.getLangExtension<core::lang::IRppExtensions>().getStaticCastRefCppToRefCpp(), expr, // builder.getTypeLiteral((targetTy))); // } else if(core::analysis::isConstCppRef(exprTy)) { // if(!core::analysis::isCppRef(targetTy)) { targetTy = core::analysis::getConstCppRef(targetTy); } // retIr = builder.callExpr(mgr.getLangExtension<core::lang::IRppExtensions>().getStaticCastConstCppToConstCpp(), expr, // builder.getTypeLiteral((targetTy))); // } else { // std::cerr << " === BASE TO DERIVED FAILED ===========" << std::endl; // std::cerr << "####### Expr: #######" << std::endl; // std::cerr << (expr); // std::cerr << "\n####### Expr Type: #######" << std::endl; // std::cerr << (exprTy); // std::cerr << "\n####### cast Type: #######" << std::endl; // std::cerr << (targetTy); // std::cerr << "\n####### clang: #######" << std::endl; // castExpr->dump(); // abort(); // } // return retIr; // } //////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_Dynamic: // // A C++ dynamic_cast. // { // // we want to know the TYPE of static_cast<TYPE>() // targetTy = converter.convertType(llvm::dyn_cast<clang::ExplicitCastExpr>(castExpr)->getType()); // VLOG(2) << exprTy << " " << targetTy; // core::ExpressionPtr retIr; // // pointers: // if(core::analysis::isPointerType(exprTy)) { // assert_true(core::analysis::isPointerType(targetTy)) << "from pointer to non pointer is not possible"; // targetTy = targetTy.as<core::RefTypePtr>()->getElementType(); // return builder.callExpr(mgr.getLangExtension<core::lang::IRppExtensions>().getDynamicCast(), expr, builder.getTypeLiteral((targetTy))); // } // // NORE: All value casts are upgraded to CPP ref, this has no implications for the generated code since lvalues in clang are already refs. // // and makes everithing smoother and easyer // if(exprTy.isa<core::RefTypePtr>()) { // expr = builder.toCppRef(expr); // exprTy = expr.getType(); // } // if(core::analysis::isCppRef(exprTy)) { // if(!core::analysis::isCppRef(targetTy)) { targetTy = core::analysis::getCppRef(targetTy); } // retIr = builder.callExpr(mgr.getLangExtension<core::lang::IRppExtensions>().getDynamicCastRefCppToRefCpp(), expr, // builder.getTypeLiteral((targetTy))); // } else if(core::analysis::isConstCppRef(exprTy)) { // if(!core::analysis::isCppRef(targetTy)) { targetTy = core::analysis::getConstCppRef(targetTy); } // retIr = builder.callExpr(mgr.getLangExtension<core::lang::IRppExtensions>().getDynamicCastConstCppToConstCpp(), expr, // builder.getTypeLiteral((targetTy))); // } else { // std::cerr << " === Dynamic cast FAILED ===========" << std::endl; // std::cerr << "####### Expr: #######" << std::endl; // std::cerr << (expr); // std::cerr << "\n####### Expr Type: #######" << std::endl; // std::cerr << (exprTy); // std::cerr << "\n####### cast Type: #######" << std::endl; // std::cerr << (targetTy); // std::cerr << "\n####### clang: #######" << std::endl; // castExpr->dump(); // abort(); // } // return retIr; // } //////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_NullToMemberPointer: // /*case clang::CK_NullToMemberPointer - Null pointer constant to member pointer. // * int A::*mptr = 0; int (A::*fptr)(int) = nullptr; // */ // { return builder.callExpr(targetTy, gen.getNullFunc(), builder.getTypeLiteral(targetTy)); } //////////////////////////////////////////////////////////////////////////////////////////////////////////// //case clang::CK_UserDefinedConversion: // /*case clang::CK_UserDefinedConversion - Conversion using a user defined type conversion function.i // * struct A { operator int(); }; int i = int(A()); // * */ // { return converter.convertExpr(castExpr->getSubExpr()); } //case clang::CK_AtomicToNonAtomic: //case clang::CK_NonAtomicToAtomic: //case clang::CK_CopyAndAutoreleaseBlockObject: // std::cout << " \nCAST: " << castExpr->getCastKindName() << " not supported!!" << std::endl; // std::cout << " at location: " << frontend::utils::location(castExpr->getLocStart(), converter.getSourceManager()) << std::endl; // castExpr->dump(); // assert_fail(); default: break; // fall through to not implemented assertion below } frontend_assert(false) << "Clang cast type not implemented: " << castExpr->getCastKindName(); return expr; }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ stmtutils::StmtWrapper Converter::CXXStmtConverter::VisitCXXForRangeStmt(clang::CXXForRangeStmt* frStmt) { frontend_assert(false && "ForRange -- Currently not supported!"); return stmtutils::StmtWrapper(); }
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ stmtutils::StmtWrapper Converter::CXXStmtConverter::VisitCXXCatchStmt(clang::CXXCatchStmt* catchStmt) { frontend_assert(false && "Catch -- Taken care of inside of TryStmt!"); return stmtutils::StmtWrapper(); }