// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // ExpressionNode.cc -- // // Author : Rodolfo G. Esteves // Created On : Sat May 16 13:17:07 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Fri Sep 1 15:07:09 2017 // Update Count : 618 // #include // for assert #include // for sscanf, size_t #include // for LLONG_MAX, LONG_MAX, INT_MAX, UINT... #include // for list #include // for basic_istream::operator>>, basic_i... #include // for string, operator+, operator== #include "Common/SemanticError.h" // for SemanticError #include "Common/utility.h" // for maybeMoveBuild, maybeBuild, CodeLo... #include "ParseNode.h" // for ExpressionNode, maybeMoveBuildType #include "SynTree/Constant.h" // for Constant #include "SynTree/Declaration.h" // for EnumDecl, StructDecl, UnionDecl #include "SynTree/Expression.h" // for Expression, ConstantExpr, NameExpr #include "SynTree/Statement.h" // for CompoundStmt, Statement #include "SynTree/Type.h" // for BasicType, Type, Type::Qualifiers #include "parserutility.h" // for notZeroExpr class Initializer; using namespace std; //############################################################################## // Difficult to separate extra parts of constants during lexing because actions are not allow in the middle of patterns: // // prefix action constant action suffix // // Alternatively, breaking a pattern using BEGIN does not work if the following pattern can be empty: // // constant BEGIN CONT ... // (...)? BEGIN 0 ... // possible empty suffix // // because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their // type. extern const Type::Qualifiers noQualifiers; // no qualifiers on constants static inline bool checkU( char c ) { return c == 'u' || c == 'U'; } static inline bool checkL( char c ) { return c == 'l' || c == 'L'; } static inline bool checkF( char c ) { return c == 'f' || c == 'F'; } static inline bool checkD( char c ) { return c == 'd' || c == 'D'; } static inline bool checkI( char c ) { return c == 'i' || c == 'I'; } static inline bool checkX( char c ) { return c == 'x' || c == 'X'; } static void sepNumeric( string & str, string & units ) { string::size_type posn = str.find_first_of( "`" ); if ( posn != string::npos ) { units = "?" + str.substr( posn ); // extract units str.erase( posn ); // remove units } // if } // sepNumeric Expression * build_constantInteger( std::string & str ) { static const BasicType::Kind kind[2][3] = { { BasicType::SignedInt, BasicType::LongSignedInt, BasicType::LongLongSignedInt }, { BasicType::UnsignedInt, BasicType::LongUnsignedInt, BasicType::LongLongUnsignedInt }, }; string units; // units sepNumeric( str, units ); // separate constant from units bool dec = true, Unsigned = false; // decimal, unsigned constant int size; // 0 => int, 1 => long, 2 => long long unsigned long long int v; // converted integral value size_t last = str.length() - 1; // last character of constant Expression * ret; // ROB: what do we do with units on 0 and 1? // special constants if ( str == "0" ) { ret = new ConstantExpr( Constant( (Type *)new ZeroType( noQualifiers ), str, (unsigned long long int)0 ) ); goto CLEANUP; } // if if ( str == "1" ) { ret = new ConstantExpr( Constant( (Type *)new OneType( noQualifiers ), str, (unsigned long long int)1 ) ); goto CLEANUP; } // if if ( str[0] == '0' ) { // octal/hex constant ? dec = false; if ( last != 0 && checkX( str[1] ) ) { // hex constant ? sscanf( (char *)str.c_str(), "%llx", &v ); //printf( "%llx %llu\n", v, v ); } else { // octal constant sscanf( (char *)str.c_str(), "%llo", &v ); //printf( "%llo %llu\n", v, v ); } // if } else { // decimal constant ? sscanf( (char *)str.c_str(), "%llu", &v ); //printf( "%llu %llu\n", v, v ); } // if if ( v <= INT_MAX ) { // signed int size = 0; } else if ( v <= UINT_MAX && ! dec ) { // unsigned int size = 0; Unsigned = true; // unsigned } else if ( v <= LONG_MAX ) { // signed long int size = 1; } else if ( v <= ULONG_MAX && ( ! dec || LONG_MAX == LLONG_MAX ) ) { // signed long int size = 1; Unsigned = true; // unsigned long int } else if ( v <= LLONG_MAX ) { // signed long long int size = 2; } else { // unsigned long long int size = 2; Unsigned = true; // unsigned long long int } // if if ( checkU( str[last] ) ) { // suffix 'u' ? Unsigned = true; if ( last > 0 && checkL( str[last - 1] ) ) { // suffix 'l' ? size = 1; if ( last > 1 && checkL( str[last - 2] ) ) { // suffix 'll' ? size = 2; } // if } // if } else if ( checkL( str[ last ] ) ) { // suffix 'l' ? size = 1; if ( last > 0 && checkL( str[last - 1] ) ) { // suffix 'll' ? size = 2; if ( last > 1 && checkU( str[last - 2] ) ) { // suffix 'u' ? Unsigned = true; } // if } else { if ( last > 0 && checkU( str[last - 1] ) ) { // suffix 'u' ? Unsigned = true; } // if } // if } // if ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[Unsigned][size] ), str, v ) ); CLEANUP: if ( units.length() != 0 ) { ret = new UntypedExpr( new NameExpr( units, ret ) ); } // if delete &str; // created by lex return ret; } // build_constantInteger Expression * build_constantFloat( std::string & str ) { static const BasicType::Kind kind[2][3] = { { BasicType::Float, BasicType::Double, BasicType::LongDouble }, { BasicType::FloatComplex, BasicType::DoubleComplex, BasicType::LongDoubleComplex }, }; string units; // units sepNumeric( str, units ); // separate constant from units bool complx = false; // real, complex int size = 1; // 0 => float, 1 => double (default), 2 => long double // floating-point constant has minimum of 2 characters: 1. or .1 size_t last = str.length() - 1; double v; sscanf( str.c_str(), "%lg", &v ); if ( checkI( str[last] ) ) { // imaginary ? complx = true; last -= 1; // backup one character } // if if ( checkF( str[last] ) ) { // float ? size = 0; } else if ( checkD( str[last] ) ) { // double ? size = 1; } else if ( checkL( str[last] ) ) { // long double ? size = 2; } // if if ( ! complx && checkI( str[last - 1] ) ) { // imaginary ? complx = true; } // if Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, kind[complx][size] ), str, v ) ); if ( units.length() != 0 ) { ret = new UntypedExpr( new NameExpr( units, ret ) ); } // if delete &str; // created by lex return ret; } // build_constantFloat static void sepString( string & str, string & units, char delimit ) { string::size_type posn = str.find_last_of( delimit ) + 1; if ( posn != str.length() ) { units = "?" + str.substr( posn ); // extract units str.erase( posn ); // remove units } // if } // sepString Expression * build_constantChar( std::string & str ) { string units; // units sepString( str, units, '\'' ); // separate constant from units Expression * ret = new ConstantExpr( Constant( new BasicType( noQualifiers, BasicType::Char ), str, (unsigned long long int)(unsigned char)str[1] ) ); if ( units.length() != 0 ) { ret = new UntypedExpr( new NameExpr( units, ret ) ); } // if delete &str; // created by lex return ret; } // build_constantChar ConstantExpr * build_constantStr( std::string & str ) { string units; // units sepString( str, units, '"' ); // separate constant from units ArrayType * at = new ArrayType( noQualifiers, new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), new ConstantExpr( Constant::from_ulong( str.size() + 1 - 2 ) ), // +1 for '\0' and -2 for '"' false, false ); ConstantExpr * ret = new ConstantExpr( Constant( at, str, (unsigned long long int)0 ) ); // constant 0 is ignored for pure string value // ROB: type mismatch // if ( units.length() != 0 ) { // ret = new UntypedExpr( new NameExpr( units, ret ) ); // } // if delete &str; // created by lex return ret; } // build_constantStr Expression * build_field_name_FLOATINGconstant( const std::string & str ) { // str is of the form A.B -> separate at the . and return member expression int a, b; char dot; std::stringstream ss( str ); ss >> a >> dot >> b; UntypedMemberExpr * ret = new UntypedMemberExpr( new ConstantExpr( Constant::from_int( b ) ), new ConstantExpr( Constant::from_int( a ) ) ); delete &str; return ret; } // build_field_name_FLOATINGconstant Expression * make_field_name_fraction_constants( Expression * fieldName, Expression * fracts ) { if ( fracts ) { if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( fracts ) ) { memberExpr->set_member( make_field_name_fraction_constants( fieldName, memberExpr->get_aggregate() ) ); return memberExpr; } else { return new UntypedMemberExpr( fracts, fieldName ); } } return fieldName; } // make_field_name_fraction_constants Expression * build_field_name_fraction_constants( Expression * fieldName, ExpressionNode * fracts ) { return make_field_name_fraction_constants( fieldName, maybeMoveBuild< Expression >( fracts ) ); } // build_field_name_fraction_constants Expression * build_field_name_REALFRACTIONconstant( const std::string & str ) { if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) throw SemanticError( "invalid tuple index " + str ); Expression * ret = build_constantInteger( *new std::string( str.substr(1) ) ); delete &str; return ret; } // build_field_name_REALFRACTIONconstant Expression * build_field_name_REALDECIMALconstant( const std::string & str ) { if ( str[str.size()-1] != '.' ) throw SemanticError( "invalid tuple index " + str ); Expression * ret = build_constantInteger( *new std::string( str.substr( 0, str.size()-1 ) ) ); delete &str; return ret; } // build_field_name_REALDECIMALconstant NameExpr * build_varref( const string * name ) { NameExpr * expr = new NameExpr( *name, nullptr ); delete name; return expr; } // build_varref // TODO: get rid of this and OperKinds and reuse code from OperatorTable static const char * OperName[] = { // must harmonize with OperKinds // diadic "SizeOf", "AlignOf", "OffsetOf", "?+?", "?-?", "?\\?", "?*?", "?/?", "?%?", "||", "&&", "?|?", "?&?", "?^?", "Cast", "?<>?", "??", "?<=?", "?>=?", "?==?", "?!=?", "?=?", "?@=?", "?\\=?", "?*=?", "?/=?", "?%=?", "?+=?", "?-=?", "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?", "?[?]", "...", // monadic "+?", "-?", "AddressOf", "*?", "!?", "~?", "++?", "?++", "--?", "?--", }; // OperName Expression * build_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) { Type * targetType = maybeMoveBuildType( decl_node ); if ( dynamic_cast< VoidType * >( targetType ) ) { delete targetType; return new CastExpr( maybeMoveBuild< Expression >(expr_node) ); } else { return new CastExpr( maybeMoveBuild< Expression >(expr_node), targetType ); } // if } // build_cast Expression * build_virtual_cast( DeclarationNode * decl_node, ExpressionNode * expr_node ) { Type * targetType = maybeMoveBuildType( decl_node ); Expression * castArg = maybeMoveBuild< Expression >( expr_node ); return new VirtualCastExpr( castArg, targetType ); } // build_virtual_cast Expression * build_fieldSel( ExpressionNode * expr_node, Expression * member ) { UntypedMemberExpr * ret = new UntypedMemberExpr( member, maybeMoveBuild< Expression >(expr_node) ); return ret; } // build_fieldSel Expression * build_pfieldSel( ExpressionNode * expr_node, Expression * member ) { UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) ); deref->location = expr_node->location; deref->get_args().push_back( maybeMoveBuild< Expression >(expr_node) ); UntypedMemberExpr * ret = new UntypedMemberExpr( member, deref ); return ret; } // build_pfieldSel Expression * build_addressOf( ExpressionNode * expr_node ) { return new AddressExpr( maybeMoveBuild< Expression >(expr_node) ); } // build_addressOf Expression * build_sizeOfexpr( ExpressionNode * expr_node ) { return new SizeofExpr( maybeMoveBuild< Expression >(expr_node) ); } // build_sizeOfexpr Expression * build_sizeOftype( DeclarationNode * decl_node ) { return new SizeofExpr( maybeMoveBuildType( decl_node ) ); } // build_sizeOftype Expression * build_alignOfexpr( ExpressionNode * expr_node ) { return new AlignofExpr( maybeMoveBuild< Expression >(expr_node) ); } // build_alignOfexpr Expression * build_alignOftype( DeclarationNode * decl_node ) { return new AlignofExpr( maybeMoveBuildType( decl_node) ); } // build_alignOftype Expression * build_offsetOf( DeclarationNode * decl_node, NameExpr * member ) { Expression * ret = new UntypedOffsetofExpr( maybeMoveBuildType( decl_node ), member->get_name() ); delete member; return ret; } // build_offsetOf Expression * build_and_or( ExpressionNode * expr_node1, ExpressionNode * expr_node2, bool kind ) { return new LogicalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), notZeroExpr( maybeMoveBuild< Expression >(expr_node2) ), kind ); } // build_and_or Expression * build_unary_val( OperKinds op, ExpressionNode * expr_node ) { std::list< Expression * > args; args.push_back( maybeMoveBuild< Expression >(expr_node) ); return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); } // build_unary_val Expression * build_unary_ptr( OperKinds op, ExpressionNode * expr_node ) { std::list< Expression * > args; args.push_back( maybeMoveBuild< Expression >(expr_node) ); // xxx -- this is exactly the same as the val case now, refactor this code. return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); } // build_unary_ptr Expression * build_binary_val( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) { std::list< Expression * > args; args.push_back( maybeMoveBuild< Expression >(expr_node1) ); args.push_back( maybeMoveBuild< Expression >(expr_node2) ); return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); } // build_binary_val Expression * build_binary_ptr( OperKinds op, ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) { std::list< Expression * > args; args.push_back( maybeMoveBuild< Expression >(expr_node1) ); args.push_back( maybeMoveBuild< Expression >(expr_node2) ); return new UntypedExpr( new NameExpr( OperName[ (int)op ] ), args ); } // build_binary_ptr Expression * build_cond( ExpressionNode * expr_node1, ExpressionNode * expr_node2, ExpressionNode * expr_node3 ) { return new ConditionalExpr( notZeroExpr( maybeMoveBuild< Expression >(expr_node1) ), maybeMoveBuild< Expression >(expr_node2), maybeMoveBuild< Expression >(expr_node3) ); } // build_cond Expression * build_comma( ExpressionNode * expr_node1, ExpressionNode * expr_node2 ) { return new CommaExpr( maybeMoveBuild< Expression >(expr_node1), maybeMoveBuild< Expression >(expr_node2) ); } // build_comma Expression * build_attrexpr( NameExpr * var, ExpressionNode * expr_node ) { return new AttrExpr( var, maybeMoveBuild< Expression >(expr_node) ); } // build_attrexpr Expression * build_attrtype( NameExpr * var, DeclarationNode * decl_node ) { return new AttrExpr( var, maybeMoveBuildType( decl_node ) ); } // build_attrtype Expression * build_tuple( ExpressionNode * expr_node ) { std::list< Expression * > exprs; buildMoveList( expr_node, exprs ); return new UntypedTupleExpr( exprs );; } // build_tuple Expression * build_func( ExpressionNode * function, ExpressionNode * expr_node ) { std::list< Expression * > args; buildMoveList( expr_node, args ); return new UntypedExpr( maybeMoveBuild< Expression >(function), args, nullptr ); } // build_func Expression * build_range( ExpressionNode * low, ExpressionNode * high ) { return new RangeExpr( maybeMoveBuild< Expression >( low ), maybeMoveBuild< Expression >( high ) ); } // build_range Expression * build_asmexpr( ExpressionNode * inout, ConstantExpr * constraint, ExpressionNode * operand ) { return new AsmExpr( maybeMoveBuild< Expression >( inout ), constraint, maybeMoveBuild< Expression >(operand) ); } // build_asmexpr Expression * build_valexpr( StatementNode * s ) { return new StmtExpr( dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(s) ) ); } // build_valexpr Expression * build_typevalue( DeclarationNode * decl ) { return new TypeExpr( maybeMoveBuildType( decl ) ); } // build_typevalue Expression * build_compoundLiteral( DeclarationNode * decl_node, InitializerNode * kids ) { Declaration * newDecl = maybeBuild< Declaration >(decl_node); // compound literal type if ( DeclarationWithType * newDeclWithType = dynamic_cast< DeclarationWithType * >( newDecl ) ) { // non-sue compound-literal type return new CompoundLiteralExpr( newDeclWithType->get_type(), maybeMoveBuild< Initializer >(kids) ); // these types do not have associated type information } else if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( newDecl ) ) { if ( newDeclStructDecl->has_body() ) { return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl ), maybeMoveBuild< Initializer >(kids) ); } else { return new CompoundLiteralExpr( new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); } // if } else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( newDecl ) ) { if ( newDeclUnionDecl->has_body() ) { return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl ), maybeMoveBuild< Initializer >(kids) ); } else { return new CompoundLiteralExpr( new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); } // if } else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( newDecl ) ) { if ( newDeclEnumDecl->has_body() ) { return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl ), maybeMoveBuild< Initializer >(kids) ); } else { return new CompoundLiteralExpr( new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() ), maybeMoveBuild< Initializer >(kids) ); } // if } else { assert( false ); } // if } // build_compoundLiteral // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //