Changeset fc12f05 for src/CodeGen
- Timestamp:
- Nov 13, 2023, 3:43:43 AM (23 months ago)
- Branches:
- master
- Children:
- 25f2798
- Parents:
- 0030b508 (diff), 2174191 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src/CodeGen
- Files:
-
- 2 added
- 3 deleted
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
src/CodeGen/FixMain.cc
r0030b508 rfc12f05 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // FixMain.cc -- 7 // FixMain.cc -- Tools to change a Cforall main into a C main. 8 8 // 9 9 // Author : Thierry Delisle … … 13 13 // Update Count : 0 14 14 // 15 16 15 17 16 #include "FixMain.h" … … 23 22 24 23 #include "AST/Decl.hpp" 24 #include "AST/Pass.hpp" 25 25 #include "AST/Type.hpp" 26 #include " Common/PassVisitor.h"26 #include "AST/Vector.hpp" 27 27 #include "Common/SemanticError.h" // for SemanticError 28 28 #include "CodeGen/GenType.h" // for GenType 29 #include "SynTree/Declaration.h" // for FunctionDecl, operator<<30 #include "SynTree/Type.h" // for FunctionType31 29 #include "SymTab/Mangler.h" 32 30 … … 35 33 namespace { 36 34 37 struct FindMainCore {38 FunctionDecl * main_signature= nullptr;35 struct FindMainCore final { 36 ast::FunctionDecl const * main_declaration = nullptr; 39 37 40 void previsit( FunctionDecl* decl ) {41 if ( FixMain::isMain( decl ) ) {42 if ( main_ signature) {38 void previsit( ast::FunctionDecl const * decl ) { 39 if ( isMain( decl ) ) { 40 if ( main_declaration ) { 43 41 SemanticError( decl, "Multiple definition of main routine\n" ); 44 42 } 45 main_ signature= decl;43 main_declaration = decl; 46 44 } 47 45 } 48 46 }; 49 47 48 std::string genTypeAt( const ast::vector<ast::Type> & types, size_t at ) { 49 return genType( types[at], "", Options( false, false, false, false ) ); 50 50 } 51 51 52 template<typename container> 53 std::string genTypeAt(const container& p, size_t idx) { 54 return genType((*std::next(p.begin(), idx))->get_type(), ""); 55 } 56 57 void FixMain::fix( std::list< Declaration * > & translationUnit, 58 std::ostream &os, const char* bootloader_filename ) { 59 PassVisitor< FindMainCore > main_finder; 60 acceptAll( translationUnit, main_finder ); 61 FunctionDecl * main_signature = main_finder.pass.main_signature; 62 63 if( main_signature ) { 64 os << "static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return "; 65 main_signature->mangleName = SymTab::Mangler::mangle(main_signature); 66 67 os << main_signature->get_scopedMangleName() << "("; 68 const auto& params = main_signature->get_functionType()->get_parameters(); 69 switch(params.size()) { 70 case 3: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv, (" << genTypeAt(params, 2) << ")envp"; break; 71 case 2: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv"; break; 72 case 0: break; 73 default : assert(false); 74 } 75 os << "); }\n"; 76 77 std::ifstream bootloader(bootloader_filename, std::ios::in); 78 assertf( bootloader.is_open(), "cannot open bootloader.c\n" ); 79 os << bootloader.rdbuf(); 80 } 81 } 82 83 namespace { 84 85 ObjectDecl * signedIntObj() { 86 return new ObjectDecl( 87 "", Type::StorageClasses(), LinkageSpec::Cforall, 0, 88 new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ); 52 ast::ObjectDecl * makeIntObj(){ 53 return new ast::ObjectDecl( CodeLocation(), "", 54 new ast::BasicType( ast::BasicType::SignedInt ) ); 89 55 } 90 56 91 ObjectDecl * makeArgvObj() { 92 return new ObjectDecl( 93 "", Type::StorageClasses(), LinkageSpec::Cforall, 0, 94 new PointerType( Type::Qualifiers(), 95 new PointerType( Type::Qualifiers(), 96 new BasicType( Type::Qualifiers(), BasicType::Char ) ) ), 97 nullptr ); 57 ast::ObjectDecl * makeCharStarStarObj() { 58 return new ast::ObjectDecl( CodeLocation(), "", 59 new ast::PointerType( 60 new ast::PointerType( 61 new ast::BasicType( ast::BasicType::Char ) ) ) ); 98 62 } 99 63 100 std::string create_mangled_main_function_name( FunctionType * function_type ) { 101 std::unique_ptr<FunctionDecl> decl( new FunctionDecl( 102 "main", Type::StorageClasses(), LinkageSpec::Cforall, 103 function_type, nullptr ) ); 104 return SymTab::Mangler::mangle( decl.get() ); 64 std::string getMangledNameOfMain( 65 ast::vector<ast::DeclWithType> && params, ast::ArgumentFlag isVarArgs ) { 66 ast::ptr<ast::FunctionDecl> decl = new ast::FunctionDecl( 67 CodeLocation(), 68 "main", 69 ast::vector<ast::TypeDecl>(), 70 ast::vector<ast::DeclWithType>(), 71 std::move( params ), 72 { makeIntObj() }, 73 nullptr, 74 ast::Storage::Classes(), 75 ast::Linkage::Spec(), 76 ast::vector<ast::Attribute>(), 77 ast::Function::Specs(), 78 isVarArgs 79 ); 80 return Mangle::mangle( decl.get() ); 105 81 } 106 82 107 std::string mangled_0_argument_main() { 108 FunctionType* main_type = new FunctionType( Type::Qualifiers(), true ); 109 main_type->get_returnVals().push_back( signedIntObj() ); 110 return create_mangled_main_function_name( main_type ); 83 std::string getMangledNameOf0ParameterMain() { 84 return getMangledNameOfMain( {}, ast::VariableArgs ); 111 85 } 112 86 113 std::string mangled_2_argument_main() { 114 FunctionType* main_type = new FunctionType( Type::Qualifiers(), false ); 115 main_type->get_returnVals().push_back( signedIntObj() ); 116 main_type->get_parameters().push_back( signedIntObj() ); 117 main_type->get_parameters().push_back( makeArgvObj() ); 118 return create_mangled_main_function_name( main_type ); 87 std::string getMangledNameOf2ParameterMain() { 88 return getMangledNameOfMain( { 89 makeIntObj(), 90 makeCharStarStarObj(), 91 }, ast::FixedArgs ); 119 92 } 120 93 … … 122 95 // This breaks if you move it out of the function. 123 96 static const std::string mangled_mains[] = { 124 mangled_0_argument_main(),125 mangled_2_argument_main(),126 // mangled_3_argument_main(),97 getMangledNameOf0ParameterMain(), 98 getMangledNameOf2ParameterMain(), 99 //getMangledNameOf3ParameterMain(), 127 100 }; 128 101 … … 133 106 } 134 107 108 struct FixLinkageCore final { 109 ast::Linkage::Spec const spec; 110 FixLinkageCore( ast::Linkage::Spec spec ) : spec( spec ) {} 111 112 ast::FunctionDecl const * previsit( ast::FunctionDecl const * decl ) { 113 if ( decl->name != "main" ) return decl; 114 return ast::mutate_field( decl, &ast::FunctionDecl::linkage, spec ); 115 } 116 }; 117 135 118 } // namespace 136 119 137 bool FixMain::isMain( FunctionDecl * decl ) { 138 if ( std::string("main") != decl->name ) { 139 return false; 140 } 141 return is_main( SymTab::Mangler::mangle( decl, true, true ) ); 142 } 143 144 bool FixMain::isMain( const ast::FunctionDecl * decl ) { 120 bool isMain( const ast::FunctionDecl * decl ) { 145 121 if ( std::string("main") != decl->name ) { 146 122 return false; … … 149 125 } 150 126 151 }; 127 void fixMainLinkage( ast::TranslationUnit & translationUnit, 128 bool replace_main ) { 129 ast::Linkage::Spec const spec = 130 ( replace_main ) ? ast::Linkage::Cforall : ast::Linkage::C; 131 ast::Pass<FixLinkageCore>::run( translationUnit, spec ); 132 } 133 134 void fixMainInvoke( ast::TranslationUnit & translationUnit, 135 std::ostream &os, const char * bootloader_filename ) { 136 137 ast::Pass<FindMainCore> main_finder; 138 ast::accept_all( translationUnit, main_finder ); 139 if ( nullptr == main_finder.core.main_declaration ) return; 140 141 ast::FunctionDecl * main_declaration = 142 ast::mutate( main_finder.core.main_declaration ); 143 144 main_declaration->mangleName = Mangle::mangle( main_declaration ); 145 146 os << "static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return "; 147 os << main_declaration->scopedMangleName() << "("; 148 const auto& params = main_declaration->type->params; 149 switch ( params.size() ) { 150 case 3: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv, (" << genTypeAt(params, 2) << ")envp"; break; 151 case 2: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv"; break; 152 case 0: break; 153 default : assert(false); 154 } 155 os << "); }\n"; 156 157 std::ifstream bootloader( bootloader_filename, std::ios::in ); 158 assertf( bootloader.is_open(), "cannot open bootloader.c\n" ); 159 os << bootloader.rdbuf(); 160 } 161 162 } // namespace CodeGen -
src/CodeGen/FixMain.h
r0030b508 rfc12f05 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // FixMain.h -- 7 // FixMain.h -- Tools to change a Cforall main into a C main. 8 8 // 9 9 // Author : Thierry Delisle … … 17 17 18 18 #include <iosfwd> 19 #include <memory>20 #include <list>21 19 22 #include "SynTree/LinkageSpec.h"23 24 class Declaration;25 class FunctionDecl;26 20 namespace ast { 27 21 class FunctionDecl; 22 class TranslationUnit; 28 23 } 29 24 30 25 namespace CodeGen { 31 26 32 class FixMain { 33 public : 34 static inline LinkageSpec::Spec mainLinkage() { 35 return replace_main ? LinkageSpec::Cforall : LinkageSpec::C; 36 } 27 /// Is this function a program main function? 28 bool isMain( const ast::FunctionDecl * decl ); 37 29 38 static inline void setReplaceMain(bool val) { 39 replace_main = val; 40 } 30 /// Adjust the linkage of main functions. 31 void fixMainLinkage( ast::TranslationUnit & transUnit, bool replaceMain ); 41 32 42 static bool isMain(FunctionDecl* decl); 43 static bool isMain(const ast::FunctionDecl * decl); 44 45 static void fix( std::list< Declaration * > & decls, 46 std::ostream &os, const char* bootloader_filename ); 47 48 private: 49 static bool replace_main; 50 }; 33 /// Add a wrapper around to run the Cforall main. 34 void fixMainInvoke( ast::TranslationUnit & transUnit, 35 std::ostream & os, const char * bootloaderFilename ); 51 36 52 37 } // namespace CodeGen -
src/CodeGen/FixNames.cc
r0030b508 rfc12f05 22 22 #include "AST/Expr.hpp" 23 23 #include "AST/Pass.hpp" 24 #include "Common/PassVisitor.h"25 24 #include "Common/SemanticError.h" // for SemanticError 26 25 #include "FixMain.h" // for FixMain 27 26 #include "SymTab/Mangler.h" // for Mangler 28 #include "SynTree/LinkageSpec.h" // for Cforall, isMangled29 #include "SynTree/Constant.h" // for Constant30 #include "SynTree/Declaration.h" // for FunctionDecl, ObjectDecl, Declarat...31 #include "SynTree/Expression.h" // for ConstantExpr32 #include "SynTree/Label.h" // for Label, noLabels33 #include "SynTree/Statement.h" // for ReturnStmt, CompoundStmt34 #include "SynTree/Type.h" // for Type, BasicType, Type::Qualifiers35 #include "SynTree/Visitor.h" // for Visitor, acceptAll36 27 #include "CompilationState.h" 37 28 38 29 namespace CodeGen { 39 class FixNames : public WithGuards {40 public:41 void postvisit( ObjectDecl *objectDecl );42 void postvisit( FunctionDecl *functionDecl );43 30 44 void previsit( CompoundStmt *compoundStmt ); 45 private: 46 int scopeLevel = 1; 47 48 void fixDWT( DeclarationWithType *dwt ); 49 }; 50 51 void fixNames( std::list< Declaration* > & translationUnit ) { 52 PassVisitor<FixNames> fixer; 53 acceptAll( translationUnit, fixer ); 54 } 55 56 void FixNames::fixDWT( DeclarationWithType * dwt ) { 57 if ( dwt->get_name() != "" ) { 58 if ( LinkageSpec::isMangled( dwt->get_linkage() ) ) { 59 if (!useNewAST) { 60 dwt->set_mangleName( SymTab::Mangler::mangle( dwt ) ); 61 } 62 dwt->set_scopeLevel( scopeLevel ); 63 } // if 64 } // if 65 } 66 67 void FixNames::postvisit( ObjectDecl * objectDecl ) { 68 fixDWT( objectDecl ); 69 } 70 71 void FixNames::postvisit( FunctionDecl * functionDecl ) { 72 fixDWT( functionDecl ); 73 74 if ( FixMain::isMain( functionDecl ) ) { 75 int nargs = functionDecl->get_functionType()->get_parameters().size(); 76 if( !(nargs == 0 || nargs == 2 || nargs == 3) ) { 77 SemanticError(functionDecl, "Main expected to have 0, 2 or 3 arguments\n"); 78 } 79 functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( new ConstantExpr( Constant::from_int( 0 ) ) ) ); 80 } 81 } 82 83 void FixNames::previsit( CompoundStmt * ) { 84 scopeLevel++; 85 GuardAction( [this](){ scopeLevel--; } ); 86 } 31 namespace { 87 32 88 33 /// Does work with the main function and scopeLevels. 89 class FixNames _newfinal {34 class FixNames final { 90 35 int scopeLevel = 1; 91 36 … … 103 48 104 49 const ast::FunctionDecl *postvisit( const ast::FunctionDecl *functionDecl ) { 105 if ( FixMain::isMain( functionDecl ) ) {50 if ( isMain( functionDecl ) ) { 106 51 auto mutDecl = ast::mutate( functionDecl ); 107 52 … … 138 83 }; 139 84 85 } // namespace 86 140 87 void fixNames( ast::TranslationUnit & translationUnit ) { 141 ast::Pass<FixNames _new>::run( translationUnit );88 ast::Pass<FixNames>::run( translationUnit ); 142 89 } 143 90 -
src/CodeGen/FixNames.h
r0030b508 rfc12f05 16 16 #pragma once 17 17 18 #include <list> // for list19 20 class Declaration;21 18 namespace ast { 22 19 class TranslationUnit; … … 24 21 25 22 namespace CodeGen { 26 /// mangles object and function names 27 void fixNames( std::list< Declaration* > & translationUnit ); 23 28 24 /// Sets scope levels and fills in main's default return. 29 25 void fixNames( ast::TranslationUnit & translationUnit ); 26 30 27 } // namespace CodeGen 31 28 -
src/CodeGen/GenType.cc
r0030b508 rfc12f05 19 19 #include <sstream> // for operator<<, ostringstream, basic_os... 20 20 21 #include "CodeGenerator.h" // for CodeGenerator 22 #include "SynTree/Declaration.h" // for DeclarationWithType 23 #include "SynTree/Expression.h" // for Expression 24 #include "SynTree/Type.h" // for PointerType, Type, FunctionType 25 #include "SynTree/Visitor.h" // for Visitor 21 #include "AST/Print.hpp" // for print 22 #include "AST/Vector.hpp" // for vector 23 #include "CodeGeneratorNew.hpp" // for CodeGenerator_new 24 #include "Common/UniqueName.h" // for UniqueName 26 25 27 26 namespace CodeGen { 28 struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting { 29 std::string typeString; 30 GenType( const std::string &typeString, const Options &options ); 31 32 void previsit( BaseSyntaxNode * ); 33 void postvisit( BaseSyntaxNode * ); 34 35 void postvisit( FunctionType * funcType ); 36 void postvisit( VoidType * voidType ); 37 void postvisit( BasicType * basicType ); 38 void postvisit( PointerType * pointerType ); 39 void postvisit( ArrayType * arrayType ); 40 void postvisit( ReferenceType * refType ); 41 void postvisit( StructInstType * structInst ); 42 void postvisit( UnionInstType * unionInst ); 43 void postvisit( EnumInstType * enumInst ); 44 void postvisit( TypeInstType * typeInst ); 45 void postvisit( TupleType * tupleType ); 46 void postvisit( VarArgsType * varArgsType ); 47 void postvisit( ZeroType * zeroType ); 48 void postvisit( OneType * oneType ); 49 void postvisit( GlobalScopeType * globalType ); 50 void postvisit( TraitInstType * inst ); 51 void postvisit( TypeofType * typeof ); 52 void postvisit( VTableType * vtable ); 53 void postvisit( QualifiedType * qualType ); 54 55 private: 56 void handleQualifiers( Type *type ); 57 std::string handleGeneric( ReferenceToType * refType ); 58 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic ); 59 60 Options options; 61 }; 62 63 std::string genType( Type *type, const std::string &baseString, const Options &options ) { 64 PassVisitor<GenType> gt( baseString, options ); 27 28 namespace { 29 30 #warning Remove the _new when old version is removed. 31 struct GenType_new : 32 public ast::WithShortCircuiting, 33 public ast::WithVisitorRef<GenType_new> { 34 std::string result; 35 GenType_new( const std::string &typeString, const Options &options ); 36 37 void previsit( ast::Node const * ); 38 void postvisit( ast::Node const * ); 39 40 void postvisit( ast::FunctionType const * type ); 41 void postvisit( ast::VoidType const * type ); 42 void postvisit( ast::BasicType const * type ); 43 void postvisit( ast::PointerType const * type ); 44 void postvisit( ast::ArrayType const * type ); 45 void postvisit( ast::ReferenceType const * type ); 46 void postvisit( ast::StructInstType const * type ); 47 void postvisit( ast::UnionInstType const * type ); 48 void postvisit( ast::EnumInstType const * type ); 49 void postvisit( ast::TypeInstType const * type ); 50 void postvisit( ast::TupleType const * type ); 51 void postvisit( ast::VarArgsType const * type ); 52 void postvisit( ast::ZeroType const * type ); 53 void postvisit( ast::OneType const * type ); 54 void postvisit( ast::GlobalScopeType const * type ); 55 void postvisit( ast::TraitInstType const * type ); 56 void postvisit( ast::TypeofType const * type ); 57 void postvisit( ast::VTableType const * type ); 58 void postvisit( ast::QualifiedType const * type ); 59 60 private: 61 void handleQualifiers( ast::Type const *type ); 62 std::string handleGeneric( ast::BaseInstType const * type ); 63 void genArray( const ast::CV::Qualifiers &qualifiers, ast::Type const *base, ast::Expr const *dimension, bool isVarLen, bool isStatic ); 64 std::string genParamList( const ast::vector<ast::Type> & ); 65 66 Options options; 67 }; 68 69 GenType_new::GenType_new( const std::string &typeString, const Options &options ) : result( typeString ), options( options ) {} 70 71 void GenType_new::previsit( ast::Node const * ) { 72 // Turn off automatic recursion for all nodes, to allow each visitor to 73 // precisely control the order in which its children are visited. 74 visit_children = false; 75 } 76 77 void GenType_new::postvisit( ast::Node const * node ) { 78 std::stringstream ss; 79 ast::print( ss, node ); 80 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() ); 81 } 82 83 void GenType_new::postvisit( ast::VoidType const * type ) { 84 result = "void " + result; 85 handleQualifiers( type ); 86 } 87 88 void GenType_new::postvisit( ast::BasicType const * type ) { 89 ast::BasicType::Kind kind = type->kind; 90 assert( 0 <= kind && kind < ast::BasicType::NUMBER_OF_BASIC_TYPES ); 91 result = std::string( ast::BasicType::typeNames[kind] ) + " " + result; 92 handleQualifiers( type ); 93 } 94 95 void GenType_new::genArray( const ast::CV::Qualifiers & qualifiers, ast::Type const * base, ast::Expr const *dimension, bool isVarLen, bool isStatic ) { 96 std::ostringstream os; 97 if ( result != "" ) { 98 if ( result[ 0 ] == '*' ) { 99 os << "(" << result << ")"; 100 } else { 101 os << result; 102 } 103 } 104 os << "["; 105 if ( isStatic ) { 106 os << "static "; 107 } 108 if ( qualifiers.is_const ) { 109 os << "const "; 110 } 111 if ( qualifiers.is_volatile ) { 112 os << "volatile "; 113 } 114 if ( qualifiers.is_restrict ) { 115 os << "__restrict "; 116 } 117 if ( qualifiers.is_atomic ) { 118 os << "_Atomic "; 119 } 120 if ( dimension != 0 ) { 121 ast::Pass<CodeGenerator_new>::read( dimension, os, options ); 122 } else if ( isVarLen ) { 123 // no dimension expression on a VLA means it came in with the * token 124 os << "*"; 125 } 126 os << "]"; 127 128 result = os.str(); 129 130 base->accept( *visitor ); 131 } 132 133 void GenType_new::postvisit( ast::PointerType const * type ) { 134 if ( type->isStatic || type->isVarLen || type->dimension ) { 135 genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic ); 136 } else { 137 handleQualifiers( type ); 138 if ( result[ 0 ] == '?' ) { 139 result = "* " + result; 140 } else { 141 result = "*" + result; 142 } 143 type->base->accept( *visitor ); 144 } 145 } 146 147 void GenType_new::postvisit( ast::ArrayType const * type ) { 148 genArray( type->qualifiers, type->base, type->dimension, type->isVarLen, type->isStatic ); 149 } 150 151 void GenType_new::postvisit( ast::ReferenceType const * type ) { 152 assertf( !options.genC, "Reference types should not reach code generation." ); 153 handleQualifiers( type ); 154 result = "&" + result; 155 type->base->accept( *visitor ); 156 } 157 158 void GenType_new::postvisit( ast::FunctionType const * type ) { 159 std::ostringstream os; 160 161 if ( result != "" ) { 162 if ( result[ 0 ] == '*' ) { 163 os << "(" << result << ")"; 164 } else { 165 os << result; 166 } 167 } 168 169 if ( type->params.empty() ) { 170 if ( type->isVarArgs ) { 171 os << "()"; 172 } else { 173 os << "(void)"; 174 } 175 } else { 176 os << "(" ; 177 178 os << genParamList( type->params ); 179 180 if ( type->isVarArgs ) { 181 os << ", ..."; 182 } 183 os << ")"; 184 } 185 186 result = os.str(); 187 188 if ( type->returns.size() == 0 ) { 189 result = "void " + result; 190 } else { 191 type->returns.front()->accept( *visitor ); 192 } 193 194 // Add forall clause. 195 if( !type->forall.empty() && !options.genC ) { 196 //assertf( !options.genC, "FunctionDecl type parameters should not reach code generation." ); 65 197 std::ostringstream os; 66 67 if ( ! type->get_attributes().empty() ) { 68 PassVisitor<CodeGenerator> cg( os, options ); 69 cg.pass.genAttributes( type->get_attributes() ); 70 } // if 71 72 type->accept( gt ); 73 return os.str() + gt.pass.typeString; 74 } 75 76 std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) { 77 return genType( type, baseString, Options(pretty, genC, lineMarks, false ) ); 78 } 79 80 std::string genPrettyType( Type * type, const std::string & baseString ) { 81 return genType( type, baseString, true, false ); 82 } 83 84 GenType::GenType( const std::string &typeString, const Options &options ) : typeString( typeString ), options( options ) {} 85 86 // *** BaseSyntaxNode 87 void GenType::previsit( BaseSyntaxNode * ) { 88 // turn off automatic recursion for all nodes, to allow each visitor to 89 // precisely control the order in which its children are visited. 90 visit_children = false; 91 } 92 93 void GenType::postvisit( BaseSyntaxNode * node ) { 94 std::stringstream ss; 95 node->print( ss ); 96 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() ); 97 } 98 99 void GenType::postvisit( VoidType * voidType ) { 100 typeString = "void " + typeString; 101 handleQualifiers( voidType ); 102 } 103 104 void GenType::postvisit( BasicType * basicType ) { 105 BasicType::Kind kind = basicType->kind; 106 assert( 0 <= kind && kind < BasicType::NUMBER_OF_BASIC_TYPES ); 107 typeString = std::string( BasicType::typeNames[kind] ) + " " + typeString; 108 handleQualifiers( basicType ); 109 } 110 111 void GenType::genArray( const Type::Qualifiers & qualifiers, Type * base, Expression *dimension, bool isVarLen, bool isStatic ) { 198 ast::Pass<CodeGenerator_new> cg( os, options ); 199 os << "forall("; 200 cg.core.genCommaList( type->forall ); 201 os << ")" << std::endl; 202 result = os.str() + result; 203 } 204 } 205 206 std::string GenType_new::handleGeneric( ast::BaseInstType const * type ) { 207 if ( !type->params.empty() ) { 112 208 std::ostringstream os; 113 if ( typeString != "" ) { 114 if ( typeString[ 0 ] == '*' ) { 115 os << "(" << typeString << ")"; 116 } else { 117 os << typeString; 118 } // if 119 } // if 120 os << "["; 121 122 if ( isStatic ) { 123 os << "static "; 124 } // if 125 if ( qualifiers.is_const ) { 126 os << "const "; 127 } // if 128 if ( qualifiers.is_volatile ) { 129 os << "volatile "; 130 } // if 131 if ( qualifiers.is_restrict ) { 132 os << "__restrict "; 133 } // if 134 if ( qualifiers.is_atomic ) { 135 os << "_Atomic "; 136 } // if 137 if ( dimension != 0 ) { 138 PassVisitor<CodeGenerator> cg( os, options ); 139 dimension->accept( cg ); 140 } else if ( isVarLen ) { 141 // no dimension expression on a VLA means it came in with the * token 142 os << "*"; 143 } // if 144 os << "]"; 145 146 typeString = os.str(); 147 148 base->accept( *visitor ); 149 } 150 151 void GenType::postvisit( PointerType * pointerType ) { 152 assert( pointerType->base != 0); 153 if ( pointerType->get_isStatic() || pointerType->get_isVarLen() || pointerType->dimension ) { 154 genArray( pointerType->get_qualifiers(), pointerType->base, pointerType->dimension, pointerType->get_isVarLen(), pointerType->get_isStatic() ); 155 } else { 156 handleQualifiers( pointerType ); 157 if ( typeString[ 0 ] == '?' ) { 158 typeString = "* " + typeString; 159 } else { 160 typeString = "*" + typeString; 161 } // if 162 pointerType->base->accept( *visitor ); 163 } // if 164 } 165 166 void GenType::postvisit( ArrayType * arrayType ) { 167 genArray( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->get_isVarLen(), arrayType->get_isStatic() ); 168 } 169 170 void GenType::postvisit( ReferenceType * refType ) { 171 assert( 0 != refType->base ); 172 assertf( ! options.genC, "Reference types should not reach code generation." ); 173 handleQualifiers( refType ); 174 typeString = "&" + typeString; 175 refType->base->accept( *visitor ); 176 } 177 178 void GenType::postvisit( FunctionType * funcType ) { 179 std::ostringstream os; 180 181 if ( typeString != "" ) { 182 if ( typeString[ 0 ] == '*' ) { 183 os << "(" << typeString << ")"; 184 } else { 185 os << typeString; 186 } // if 187 } // if 188 189 /************* parameters ***************/ 190 191 const std::list<DeclarationWithType *> &pars = funcType->parameters; 192 193 if ( pars.empty() ) { 194 if ( funcType->get_isVarArgs() ) { 195 os << "()"; 196 } else { 197 os << "(void)"; 198 } // if 199 } else { 200 PassVisitor<CodeGenerator> cg( os, options ); 201 os << "(" ; 202 203 cg.pass.genCommaList( pars.begin(), pars.end() ); 204 205 if ( funcType->get_isVarArgs() ) { 206 os << ", ..."; 207 } // if 208 os << ")"; 209 } // if 210 211 typeString = os.str(); 212 213 if ( funcType->returnVals.size() == 0 ) { 214 typeString = "void " + typeString; 215 } else { 216 funcType->returnVals.front()->get_type()->accept( *visitor ); 217 } // if 218 219 // add forall 220 if( ! funcType->forall.empty() && ! options.genC ) { 221 // assertf( ! genC, "Aggregate type parameters should not reach code generation." ); 222 std::ostringstream os; 223 PassVisitor<CodeGenerator> cg( os, options ); 224 os << "forall("; 225 cg.pass.genCommaList( funcType->forall.begin(), funcType->forall.end() ); 226 os << ")" << std::endl; 227 typeString = os.str() + typeString; 228 } 229 } 230 231 std::string GenType::handleGeneric( ReferenceToType * refType ) { 232 if ( ! refType->parameters.empty() ) { 233 std::ostringstream os; 234 PassVisitor<CodeGenerator> cg( os, options ); 235 os << "("; 236 cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() ); 237 os << ") "; 238 return os.str(); 239 } 240 return ""; 241 } 242 243 void GenType::postvisit( StructInstType * structInst ) { 244 typeString = structInst->name + handleGeneric( structInst ) + " " + typeString; 245 if ( options.genC ) typeString = "struct " + typeString; 246 handleQualifiers( structInst ); 247 } 248 249 void GenType::postvisit( UnionInstType * unionInst ) { 250 typeString = unionInst->name + handleGeneric( unionInst ) + " " + typeString; 251 if ( options.genC ) typeString = "union " + typeString; 252 handleQualifiers( unionInst ); 253 } 254 255 void GenType::postvisit( EnumInstType * enumInst ) { 256 if ( enumInst->baseEnum && enumInst->baseEnum->base ) { 257 typeString = genType(enumInst->baseEnum->base, typeString, options); 258 } else { 259 typeString = enumInst->name + " " + typeString; 260 if ( options.genC ) { 261 typeString = "enum " + typeString; 262 } 263 } 264 handleQualifiers( enumInst ); 265 } 266 267 void GenType::postvisit( TypeInstType * typeInst ) { 268 assertf( ! options.genC, "Type instance types should not reach code generation." ); 269 typeString = typeInst->name + " " + typeString; 270 handleQualifiers( typeInst ); 271 } 272 273 void GenType::postvisit( TupleType * tupleType ) { 274 assertf( ! options.genC, "Tuple types should not reach code generation." ); 275 unsigned int i = 0; 276 std::ostringstream os; 277 os << "["; 278 for ( Type * t : *tupleType ) { 279 i++; 280 os << genType( t, "", options ) << (i == tupleType->size() ? "" : ", "); 281 } 282 os << "] "; 283 typeString = os.str() + typeString; 284 } 285 286 void GenType::postvisit( VarArgsType * varArgsType ) { 287 typeString = "__builtin_va_list " + typeString; 288 handleQualifiers( varArgsType ); 289 } 290 291 void GenType::postvisit( ZeroType * zeroType ) { 292 // ideally these wouldn't hit codegen at all, but should be safe to make them ints 293 typeString = (options.pretty ? "zero_t " : "long int ") + typeString; 294 handleQualifiers( zeroType ); 295 } 296 297 void GenType::postvisit( OneType * oneType ) { 298 // ideally these wouldn't hit codegen at all, but should be safe to make them ints 299 typeString = (options.pretty ? "one_t " : "long int ") + typeString; 300 handleQualifiers( oneType ); 301 } 302 303 void GenType::postvisit( GlobalScopeType * globalType ) { 304 assertf( ! options.genC, "Global scope type should not reach code generation." ); 305 handleQualifiers( globalType ); 306 } 307 308 void GenType::postvisit( TraitInstType * inst ) { 309 assertf( ! options.genC, "Trait types should not reach code generation." ); 310 typeString = inst->name + " " + typeString; 311 handleQualifiers( inst ); 312 } 313 314 void GenType::postvisit( TypeofType * typeof ) { 315 std::ostringstream os; 316 PassVisitor<CodeGenerator> cg( os, options ); 317 os << "typeof("; 318 typeof->expr->accept( cg ); 319 os << ") " << typeString; 320 typeString = os.str(); 321 handleQualifiers( typeof ); 322 } 323 324 void GenType::postvisit( VTableType * vtable ) { 325 assertf( ! options.genC, "Virtual table types should not reach code generation." ); 326 std::ostringstream os; 327 os << "vtable(" << genType( vtable->base, "", options ) << ") " << typeString; 328 typeString = os.str(); 329 handleQualifiers( vtable ); 330 } 331 332 void GenType::postvisit( QualifiedType * qualType ) { 333 assertf( ! options.genC, "Qualified types should not reach code generation." ); 334 std::ostringstream os; 335 os << genType( qualType->parent, "", options ) << "." << genType( qualType->child, "", options ) << typeString; 336 typeString = os.str(); 337 handleQualifiers( qualType ); 338 } 339 340 void GenType::handleQualifiers( Type * type ) { 341 if ( type->get_const() ) { 342 typeString = "const " + typeString; 343 } // if 344 if ( type->get_volatile() ) { 345 typeString = "volatile " + typeString; 346 } // if 347 if ( type->get_restrict() ) { 348 typeString = "__restrict " + typeString; 349 } // if 350 if ( type->get_atomic() ) { 351 typeString = "_Atomic " + typeString; 352 } // if 353 } 209 ast::Pass<CodeGenerator_new> cg( os, options ); 210 os << "("; 211 cg.core.genCommaList( type->params ); 212 os << ") "; 213 return os.str(); 214 } 215 return ""; 216 } 217 218 void GenType_new::postvisit( ast::StructInstType const * type ) { 219 result = type->name + handleGeneric( type ) + " " + result; 220 if ( options.genC ) result = "struct " + result; 221 handleQualifiers( type ); 222 } 223 224 void GenType_new::postvisit( ast::UnionInstType const * type ) { 225 result = type->name + handleGeneric( type ) + " " + result; 226 if ( options.genC ) result = "union " + result; 227 handleQualifiers( type ); 228 } 229 230 void GenType_new::postvisit( ast::EnumInstType const * type ) { 231 if ( type->base && type->base->base ) { 232 result = genType( type->base->base, result, options ); 233 } else { 234 result = type->name + " " + result; 235 if ( options.genC ) { 236 result = "enum " + result; 237 } 238 } 239 handleQualifiers( type ); 240 } 241 242 void GenType_new::postvisit( ast::TypeInstType const * type ) { 243 assertf( !options.genC, "TypeInstType should not reach code generation." ); 244 result = type->name + " " + result; 245 handleQualifiers( type ); 246 } 247 248 void GenType_new::postvisit( ast::TupleType const * type ) { 249 assertf( !options.genC, "TupleType should not reach code generation." ); 250 unsigned int i = 0; 251 std::ostringstream os; 252 os << "["; 253 for ( ast::ptr<ast::Type> const & t : type->types ) { 254 i++; 255 os << genType( t, "", options ) << (i == type->size() ? "" : ", "); 256 } 257 os << "] "; 258 result = os.str() + result; 259 } 260 261 void GenType_new::postvisit( ast::VarArgsType const * type ) { 262 result = "__builtin_va_list " + result; 263 handleQualifiers( type ); 264 } 265 266 void GenType_new::postvisit( ast::ZeroType const * type ) { 267 // Ideally these wouldn't hit codegen at all, but should be safe to make them ints. 268 result = (options.pretty ? "zero_t " : "long int ") + result; 269 handleQualifiers( type ); 270 } 271 272 void GenType_new::postvisit( ast::OneType const * type ) { 273 // Ideally these wouldn't hit codegen at all, but should be safe to make them ints. 274 result = (options.pretty ? "one_t " : "long int ") + result; 275 handleQualifiers( type ); 276 } 277 278 void GenType_new::postvisit( ast::GlobalScopeType const * type ) { 279 assertf( !options.genC, "GlobalScopeType should not reach code generation." ); 280 handleQualifiers( type ); 281 } 282 283 void GenType_new::postvisit( ast::TraitInstType const * type ) { 284 assertf( !options.genC, "TraitInstType should not reach code generation." ); 285 result = type->name + " " + result; 286 handleQualifiers( type ); 287 } 288 289 void GenType_new::postvisit( ast::TypeofType const * type ) { 290 std::ostringstream os; 291 os << "typeof("; 292 ast::Pass<CodeGenerator_new>::read( type, os, options ); 293 os << ") " << result; 294 result = os.str(); 295 handleQualifiers( type ); 296 } 297 298 void GenType_new::postvisit( ast::VTableType const * type ) { 299 assertf( !options.genC, "Virtual table types should not reach code generation." ); 300 std::ostringstream os; 301 os << "vtable(" << genType( type->base, "", options ) << ") " << result; 302 result = os.str(); 303 handleQualifiers( type ); 304 } 305 306 void GenType_new::postvisit( ast::QualifiedType const * type ) { 307 assertf( !options.genC, "QualifiedType should not reach code generation." ); 308 std::ostringstream os; 309 os << genType( type->parent, "", options ) << "." << genType( type->child, "", options ) << result; 310 result = os.str(); 311 handleQualifiers( type ); 312 } 313 314 void GenType_new::handleQualifiers( ast::Type const * type ) { 315 if ( type->is_const() ) { 316 result = "const " + result; 317 } 318 if ( type->is_volatile() ) { 319 result = "volatile " + result; 320 } 321 if ( type->is_restrict() ) { 322 result = "__restrict " + result; 323 } 324 if ( type->is_atomic() ) { 325 result = "_Atomic " + result; 326 } 327 } 328 329 std::string GenType_new::genParamList( const ast::vector<ast::Type> & range ) { 330 auto cur = range.begin(); 331 auto end = range.end(); 332 if ( cur == end ) return ""; 333 std::ostringstream oss; 334 UniqueName param( "__param_" ); 335 while ( true ) { 336 oss << genType( *cur++, options.genC ? param.newName() : "", options ); 337 if ( cur == end ) break; 338 oss << ", "; 339 } 340 return oss.str(); 341 } 342 343 } // namespace 344 345 std::string genType( ast::Type const * type, const std::string & base, const Options & options ) { 346 std::ostringstream os; 347 if ( !type->attributes.empty() ) { 348 ast::Pass<CodeGenerator_new> cg( os, options ); 349 cg.core.genAttributes( type->attributes ); 350 } 351 352 return os.str() + ast::Pass<GenType_new>::read( type, base, options ); 353 } 354 355 std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ) { 356 return ast::Pass<GenType_new>::read( type, base, options ); 357 } 358 354 359 } // namespace CodeGen 355 360 -
src/CodeGen/GenType.h
r0030b508 rfc12f05 21 21 22 22 class Type; 23 namespace ast { 24 class Type; 25 } 23 26 24 27 namespace CodeGen { … … 26 29 std::string genType( Type *type, const std::string &baseString, bool pretty = false, bool genC = false, bool lineMarks = false ); 27 30 std::string genPrettyType( Type * type, const std::string & baseString ); 31 32 std::string genType( ast::Type const * type, const std::string & base, const Options & options ); 33 std::string genTypeNoAttr( ast::Type const * type, const std::string & base, const Options & options ); 34 28 35 } // namespace CodeGen 29 36 -
src/CodeGen/Generate.cc
r0030b508 rfc12f05 19 19 #include <string> // for operator<< 20 20 21 #include "CodeGenerator .h" // for CodeGenerator, doSemicolon, oper...21 #include "CodeGeneratorNew.hpp" // for CodeGenerator_new, doSemicolon, ... 22 22 #include "GenType.h" // for genPrettyType 23 #include "Common/PassVisitor.h" // for PassVisitor24 #include "SynTree/LinkageSpec.h" // for isBuiltin, isGeneratable25 #include "SynTree/BaseSyntaxNode.h" // for BaseSyntaxNode26 #include "SynTree/Declaration.h" // for Declaration27 #include "SynTree/Type.h" // for Type28 23 29 24 using namespace std; 30 25 31 26 namespace CodeGen { 32 namespace {33 /// Removes misc. nodes that should not exist in CodeGen34 struct TreeCleaner {35 void premutate( CompoundStmt * stmt );36 Statement * postmutate( ImplicitCtorDtorStmt * stmt );37 27 38 static bool shouldClean( Declaration * ); 39 }; 40 41 void cleanTree( std::list< Declaration * > & translationUnit ) { 42 PassVisitor<TreeCleaner> cleaner; 43 filter( translationUnit, [](Declaration * decl) { return TreeCleaner::shouldClean(decl); }, false ); 44 mutateAll( translationUnit, cleaner ); 45 } // cleanTree 46 } // namespace 47 48 void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC, bool lineMarks, bool printExprTypes ) { 49 cleanTree( translationUnit ); 50 51 PassVisitor<CodeGenerator> cgv( os, pretty, generateC, lineMarks, printExprTypes ); 52 for ( auto & dcl : translationUnit ) { 53 if ( LinkageSpec::isGeneratable( dcl->get_linkage() ) && (doIntrinsics || ! LinkageSpec::isBuiltin( dcl->get_linkage() ) ) ) { 54 cgv.pass.updateLocation( dcl ); 55 dcl->accept(cgv); 56 if ( doSemicolon( dcl ) ) { 57 os << ";"; 58 } // if 59 os << cgv.pass.endl; 60 } // if 61 } // for 28 namespace { 29 bool shouldClean( ast::Decl const * decl ) { 30 return dynamic_cast<ast::TraitDecl const *>( decl ); 62 31 } 63 32 64 void generate( BaseSyntaxNode * node, std::ostream & os ) { 65 if ( Type * type = dynamic_cast< Type * >( node ) ) { 66 os << genPrettyType( type, "" ); 67 } else { 68 PassVisitor<CodeGenerator> cgv( os, true, false, false, false ); 69 node->accept( cgv ); 70 } 71 os << std::endl; 72 } 73 74 namespace { 75 void TreeCleaner::premutate( CompoundStmt * cstmt ) { 76 filter( cstmt->kids, [](Statement * stmt) { 77 if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) { 78 return shouldClean( declStmt->decl ); 79 } 80 return false; 81 }, false ); 33 /// Removes various nodes that should not exist in CodeGen. 34 struct TreeCleaner_new { 35 ast::CompoundStmt const * previsit( ast::CompoundStmt const * stmt ) { 36 auto mutStmt = ast::mutate( stmt ); 37 erase_if( mutStmt->kids, []( ast::Stmt const * stmt ){ 38 auto declStmt = dynamic_cast<ast::DeclStmt const *>( stmt ); 39 return ( declStmt ) ? shouldClean( declStmt->decl ) : false; 40 } ); 41 return mutStmt; 82 42 } 83 43 84 Statement * TreeCleaner::postmutate( ImplicitCtorDtorStmt * stmt ) { 85 Statement * callStmt = nullptr; 86 std::swap( stmt->callStmt, callStmt ); 87 delete stmt; 88 return callStmt; 44 ast::Stmt const * postvisit( ast::ImplicitCtorDtorStmt const * stmt ) { 45 return stmt->callStmt; 89 46 } 47 }; 48 } // namespace 90 49 91 bool TreeCleaner::shouldClean( Declaration * decl ) { 92 return dynamic_cast< TraitDecl * >( decl ); 50 void generate( ast::TranslationUnit & translationUnit, std::ostream & os, bool doIntrinsics, 51 bool pretty, bool generateC, bool lineMarks, bool printExprTypes ) { 52 erase_if( translationUnit.decls, shouldClean ); 53 ast::Pass<TreeCleaner_new>::run( translationUnit ); 54 55 ast::Pass<CodeGenerator_new> cgv( os, 56 Options( pretty, generateC, lineMarks, printExprTypes ) ); 57 for ( auto & decl : translationUnit.decls ) { 58 if ( decl->linkage.is_generatable && (doIntrinsics || !decl->linkage.is_builtin ) ) { 59 cgv.core.updateLocation( decl ); 60 decl->accept( cgv ); 61 if ( doSemicolon( decl ) ) { 62 os << ";"; 63 } 64 os << cgv.core.endl; 93 65 } 94 } // namespace 66 } 67 } 68 95 69 } // namespace CodeGen 96 70 -
src/CodeGen/Generate.h
r0030b508 rfc12f05 22 22 class Declaration; 23 23 24 namespace ast { 25 class TranslationUnit; 26 } 27 24 28 namespace CodeGen { 25 /// Generates code. doIntrinsics determines if intrinsic functions are printed, pretty formats output nicely (e.g., uses unmangled names, etc.), generateC is true when the output must consist only of C code (allows some assertions, etc.)26 void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC = false , bool lineMarks = false, bool printTypeExpr = false );27 29 28 /// Generate code for a single node -- helpful for debugging in gdb 29 void generate( BaseSyntaxNode * node, std::ostream & os ); 30 /// Generates all code in transUnit and writing it to the os. 31 /// doIntrinsics: Should intrinsic functions be printed? 32 /// pretty: Format output nicely (e.g., uses unmangled names, etc.). 33 /// generateC: Make sure the output only consists of C code (allows some assertions, etc.) 34 /// lineMarks: Output line marks (processed line directives) in the output. 35 /// printExprTypes: Print the types of expressions in comments. 36 void generate( ast::TranslationUnit & transUnit, std::ostream &os, bool doIntrinsics, 37 bool pretty, bool generateC, bool lineMarks, bool printExprTypes ); 38 30 39 } // namespace CodeGen 31 40 -
src/CodeGen/LinkOnce.cc
r0030b508 rfc12f05 22 22 #include "AST/Expr.hpp" 23 23 #include "AST/Pass.hpp" 24 #include "Common/PassVisitor.h" // for PassVisitor, WithShortCircuiting25 24 26 25 namespace CodeGen { 27 26 28 27 namespace { 29 30 bool is_cfa_linkonce_old( Attribute const * attr ) {31 return std::string("cfa_linkonce") == attr->name;32 }33 34 bool is_section_attribute_old( Attribute const * attr ) {35 return std::string("section") == attr->name;36 }37 38 class LinkOnceVisitorCore : public WithShortCircuiting {39 public:40 void previsit( Declaration * ) {41 visit_children = false;42 }43 44 void previsit( DeclarationWithType * decl ) {45 std::list< Attribute * > & attributes = decl->attributes;46 // See if we can find the element:47 auto found = std::find_if(attributes.begin(), attributes.end(), is_cfa_linkonce_old );48 if ( attributes.end() != found ) {49 // Remove any other sections:50 attributes.remove_if( is_section_attribute_old );51 // Iterator to the cfa_linkonce attribute should still be valid.52 Attribute * attribute = *found;53 assert( attribute->parameters.empty() );54 assert( !decl->mangleName.empty() );55 // Overwrite the attribute in place.56 const std::string section_name = ".gnu.linkonce." + decl->mangleName;57 attribute->name = "section";58 attribute->parameters.push_back(59 new ConstantExpr( Constant::from_string( section_name ) )60 );61 62 // Unconditionnaly add "visibility(default)" to anything with gnu.linkonce63 // visibility is a mess otherwise64 attributes.push_back(new Attribute("visibility", {new ConstantExpr( Constant::from_string( "default" ) )}));65 66 }67 visit_children = false;68 }69 };70 28 71 29 bool is_cfa_linkonce( ast::Attribute const * attr ) { … … 122 80 } // namespace 123 81 124 void translateLinkOnce( std::list< Declaration *> & translationUnit ) {125 PassVisitor<LinkOnceVisitorCore> translator;126 acceptAll( translationUnit, translator );127 }128 129 82 void translateLinkOnce( ast::TranslationUnit & translationUnit ) { 130 83 ast::Pass<LinkOnceCore>::run( translationUnit ); -
src/CodeGen/LinkOnce.h
r0030b508 rfc12f05 20 20 // for now its almost the only attribute we handle. 21 21 22 #include <list> // for list23 22 24 class Declaration;25 23 namespace ast { 26 24 class TranslationUnit; … … 29 27 namespace CodeGen { 30 28 31 void translateLinkOnce( std::list< Declaration *> & translationUnit );32 29 void translateLinkOnce( ast::TranslationUnit & translationUnit ); 33 30 /* Convert the cfa_linkonce attribute on top level declaration into -
src/CodeGen/OperatorTable.cc
r0030b508 rfc12f05 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Tue Feb 18 15:55:01 202013 // Update Count : 5 511 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Nov 3 16:00:00 2023 13 // Update Count : 56 14 14 // 15 15 16 #include <algorithm> // for any_of 17 #include <map> // for map, _Rb_tree_const_iterator, map<>::const_iterator 18 #include <utility> // for pair 19 using namespace std; 16 #include "OperatorTable.h" 20 17 21 #include "OperatorTable.h"22 #include "Common/utility.h"18 #include <cassert> // for assert 19 #include <unordered_map> // for unordered_map 23 20 24 21 namespace CodeGen { 25 const OperatorInfo CodeGen::tableValues[] = {26 // inputName symbol outputName friendlyName type27 { "?[?]", "", "_operator_index", "Index", OT_INDEX },28 { "?{}", "=", "_constructor", "Constructor", OT_CTOR },29 { "^?{}", "", "_destructor", "Destructor", OT_DTOR },30 { "?()", "", "_operator_call", "Call Operator", OT_CALL },31 { "?++", "++", "_operator_postincr", "Postfix Increment", OT_POSTFIXASSIGN },32 { "?--", "--", "_operator_postdecr", "Postfix Decrement", OT_POSTFIXASSIGN },33 { "*?", "*", "_operator_deref", "Dereference", OT_PREFIX },34 { "+?", "+", "_operator_unaryplus", "Plus", OT_PREFIX },35 { "-?", "-", "_operator_unaryminus", "Minus", OT_PREFIX },36 { "~?", "~", "_operator_bitnot", "Bitwise Not", OT_PREFIX },37 { "!?", "!", "_operator_lognot", "Logical Not", OT_PREFIX },38 { "++?", "++", "_operator_preincr", "Prefix Increment", OT_PREFIXASSIGN },39 { "--?", "--", "_operator_predecr", "Prefix Decrement", OT_PREFIXASSIGN },40 { "?\\?", "\\", "_operator_exponential", "Exponentiation", OT_INFIX },41 { "?*?", "*", "_operator_multiply", "Multiplication", OT_INFIX },42 { "?/?", "/", "_operator_divide", "Division", OT_INFIX },43 { "?%?", "%", "_operator_modulus", "Modulo", OT_INFIX },44 { "?+?", "+", "_operator_add", "Addition", OT_INFIX },45 { "?-?", "-", "_operator_subtract", "Substraction", OT_INFIX },46 { "?<<?", "<<", "_operator_shiftleft", "Shift Left", OT_INFIX },47 { "?>>?", ">>", "_operator_shiftright", "Shift Right", OT_INFIX },48 { "?<?", "<", "_operator_less", "Less-than", OT_INFIX },49 { "?>?", ">", "_operator_greater", "Greater-than", OT_INFIX },50 { "?<=?", "<=", "_operator_lessequal", "Less-than-or-Equal", OT_INFIX },51 { "?>=?", ">=", "_operator_greaterequal", "Greater-than-or-Equal", OT_INFIX },52 { "?==?", "==", "_operator_equal", "Equality", OT_INFIX },53 { "?!=?", "!=", "_operator_notequal", "Not-Equal", OT_INFIX },54 { "?&?", "&", "_operator_bitand", "Bitwise And", OT_INFIX },55 { "?^?", "^", "_operator_bitxor", "Bitwise Xor", OT_INFIX },56 { "?|?", "|", "_operator_bitor", "Bitwise Or", OT_INFIX },57 { "?=?", "=", "_operator_assign", "Assignment", OT_INFIXASSIGN },58 { "?\\=?", "\\=", "_operator_expassign", "Exponentiation Assignment", OT_INFIXASSIGN },59 { "?*=?", "*=", "_operator_multassign", "Multiplication Assignment", OT_INFIXASSIGN },60 { "?/=?", "/=", "_operator_divassign", "Division Assignment", OT_INFIXASSIGN },61 { "?%=?", "%=", "_operator_modassign", "Modulo Assignment", OT_INFIXASSIGN },62 { "?+=?", "+=", "_operator_addassign", "Addition Assignment", OT_INFIXASSIGN },63 { "?-=?", "-=", "_operator_subassign", "Substrction Assignment", OT_INFIXASSIGN },64 { "?<<=?", "<<=", "_operator_shiftleftassign", "Shift Left Assignment", OT_INFIXASSIGN },65 { "?>>=?", ">>=", "_operator_shiftrightassign", "Shift Right Assignment", OT_INFIXASSIGN },66 { "?&=?", "&=", "_operator_bitandassign", "Bitwise And Assignment", OT_INFIXASSIGN },67 { "?^=?", "^=", "_operator_bitxorassign", "Bitwise Xor Assignment", OT_INFIXASSIGN },68 { "?|=?", "|=", "_operator_bitorassign", "Bitwise Or Assignment", OT_INFIXASSIGN },69 }; // tableValues70 22 71 std::map< std::string, OperatorInfo > CodeGen::table; 23 static const OperatorInfo tableValues[] = { 24 // inputName symbol outputName friendlyName type 25 { "?[?]", "", "_operator_index", "Index", OT_INDEX }, 26 { "?{}", "=", "_constructor", "Constructor", OT_CTOR }, 27 { "^?{}", "", "_destructor", "Destructor", OT_DTOR }, 28 { "?()", "", "_operator_call", "Call Operator", OT_CALL }, 29 { "?++", "++", "_operator_postincr", "Postfix Increment", OT_POSTFIXASSIGN }, 30 { "?--", "--", "_operator_postdecr", "Postfix Decrement", OT_POSTFIXASSIGN }, 31 { "*?", "*", "_operator_deref", "Dereference", OT_PREFIX }, 32 { "+?", "+", "_operator_unaryplus", "Plus", OT_PREFIX }, 33 { "-?", "-", "_operator_unaryminus", "Minus", OT_PREFIX }, 34 { "~?", "~", "_operator_bitnot", "Bitwise Not", OT_PREFIX }, 35 { "!?", "!", "_operator_lognot", "Logical Not", OT_PREFIX }, 36 { "++?", "++", "_operator_preincr", "Prefix Increment", OT_PREFIXASSIGN }, 37 { "--?", "--", "_operator_predecr", "Prefix Decrement", OT_PREFIXASSIGN }, 38 { "?\\?", "\\", "_operator_exponential", "Exponentiation", OT_INFIX }, 39 { "?*?", "*", "_operator_multiply", "Multiplication", OT_INFIX }, 40 { "?/?", "/", "_operator_divide", "Division", OT_INFIX }, 41 { "?%?", "%", "_operator_modulus", "Modulo", OT_INFIX }, 42 { "?+?", "+", "_operator_add", "Addition", OT_INFIX }, 43 { "?-?", "-", "_operator_subtract", "Substraction", OT_INFIX }, 44 { "?<<?", "<<", "_operator_shiftleft", "Shift Left", OT_INFIX }, 45 { "?>>?", ">>", "_operator_shiftright", "Shift Right", OT_INFIX }, 46 { "?<?", "<", "_operator_less", "Less-than", OT_INFIX }, 47 { "?>?", ">", "_operator_greater", "Greater-than", OT_INFIX }, 48 { "?<=?", "<=", "_operator_lessequal", "Less-than-or-Equal", OT_INFIX }, 49 { "?>=?", ">=", "_operator_greaterequal", "Greater-than-or-Equal", OT_INFIX }, 50 { "?==?", "==", "_operator_equal", "Equality", OT_INFIX }, 51 { "?!=?", "!=", "_operator_notequal", "Not-Equal", OT_INFIX }, 52 { "?&?", "&", "_operator_bitand", "Bitwise And", OT_INFIX }, 53 { "?^?", "^", "_operator_bitxor", "Bitwise Xor", OT_INFIX }, 54 { "?|?", "|", "_operator_bitor", "Bitwise Or", OT_INFIX }, 55 { "?=?", "=", "_operator_assign", "Assignment", OT_INFIXASSIGN }, 56 { "?\\=?", "\\=", "_operator_expassign", "Exponentiation Assignment", OT_INFIXASSIGN }, 57 { "?*=?", "*=", "_operator_multassign", "Multiplication Assignment", OT_INFIXASSIGN }, 58 { "?/=?", "/=", "_operator_divassign", "Division Assignment", OT_INFIXASSIGN }, 59 { "?%=?", "%=", "_operator_modassign", "Modulo Assignment", OT_INFIXASSIGN }, 60 { "?+=?", "+=", "_operator_addassign", "Addition Assignment", OT_INFIXASSIGN }, 61 { "?-=?", "-=", "_operator_subassign", "Substrction Assignment", OT_INFIXASSIGN }, 62 { "?<<=?", "<<=", "_operator_shiftleftassign", "Shift Left Assignment", OT_INFIXASSIGN }, 63 { "?>>=?", ">>=", "_operator_shiftrightassign", "Shift Right Assignment", OT_INFIXASSIGN }, 64 { "?&=?", "&=", "_operator_bitandassign", "Bitwise And Assignment", OT_INFIXASSIGN }, 65 { "?^=?", "^=", "_operator_bitxorassign", "Bitwise Xor Assignment", OT_INFIXASSIGN }, 66 { "?|=?", "|=", "_operator_bitorassign", "Bitwise Or Assignment", OT_INFIXASSIGN }, 67 }; // tableValues 72 68 73 CodeGen::CodeGen() { 74 enum { numOps = sizeof( tableValues ) / sizeof( OperatorInfo ) }; 75 for ( int i = 0; i < numOps; i += 1 ) { 76 table[ tableValues[i].inputName ] = tableValues[i]; 77 } // for 69 enum { numOps = sizeof( tableValues ) / sizeof( OperatorInfo ) }; 70 71 const OperatorInfo * operatorLookup( const std::string & inputName ) { 72 // Static information set up: 73 static std::unordered_map<std::string, const OperatorInfo *> inputTable; 74 if ( inputTable.empty() ) for ( const OperatorInfo & op : tableValues ) { 75 inputTable[ op.inputName ] = &op; 78 76 } 79 77 80 const OperatorInfo * operatorLookup( const string & funcName ) { 81 if ( funcName.find_first_of( "?^*+-!", 0, 1 ) == string::npos ) return nullptr; // prefilter 82 const OperatorInfo * ret = &CodeGen::table.find( funcName )->second; // must be in the table 83 assert( ret ); 84 return ret; 78 if ( inputName.find_first_of( "?^*+-!", 0, 1 ) == std::string::npos ) return nullptr; // prefilter 79 const OperatorInfo * ret = inputTable.find( inputName )->second; 80 // This can only happen if an invalid identifier name has been used. 81 assert( ret ); 82 return ret; 83 } 84 85 bool isOperator( const std::string & inputName ) { 86 return operatorLookup( inputName ) != nullptr; 87 } 88 89 std::string operatorFriendlyName( const std::string & inputName ) { 90 const OperatorInfo * info = operatorLookup( inputName ); 91 if ( info ) return info->friendlyName; 92 return ""; 93 } 94 95 // This is only used in the demangler, so it is smaller (and only maybe slow). 96 const OperatorInfo * operatorLookupByOutput( const std::string & outputName ) { 97 if ( '_' != outputName[0] ) return nullptr; 98 for ( const OperatorInfo & op : tableValues ) { 99 if ( outputName == op.outputName ) { 100 return &op; 101 } 85 102 } 103 return nullptr; 104 } 86 105 87 bool isOperator( const string & funcName ) { 88 return operatorLookup( funcName ) != nullptr; 89 } 106 bool isConstructor( const std::string & inputName ) { 107 const OperatorInfo * info = operatorLookup( inputName ); 108 if ( info ) return info->type == OT_CTOR; 109 return false; 110 } 90 111 91 string operatorFriendlyName( const string & funcName ) {92 const OperatorInfo * info = operatorLookup( funcName );93 if ( info ) return info->friendlyName;94 return "";95 112 bool isDestructor( const std::string & inputName ) { 113 const OperatorInfo * info = operatorLookup( inputName ); 114 if ( info ) return info->type == OT_DTOR; 115 return false; 116 } 96 117 97 bool isConstructor( const string & funcName ) {98 const OperatorInfo * info = operatorLookup( funcName );99 if ( info ) return info->type == OT_CTOR;100 101 118 bool isCtorDtor( const std::string & inputName ) { 119 const OperatorInfo * info = operatorLookup( inputName ); 120 if ( info ) return info->type <= OT_CONSTRUCTOR; 121 return false; 122 } 102 123 103 bool isDestructor( const string & funcName ) {104 const OperatorInfo * info = operatorLookup( funcName );105 if ( info ) return info->type == OT_DTOR;106 107 124 bool isAssignment( const std::string & inputName ) { 125 const OperatorInfo * info = operatorLookup( inputName ); 126 if ( info ) return info->type > OT_CONSTRUCTOR && info->type <= OT_ASSIGNMENT; 127 return false; 128 } 108 129 109 bool isCtorDtor( const string & funcName ) {110 const OperatorInfo * info = operatorLookup( funcName );111 if ( info ) return info->type <= OT_CONSTRUCTOR;112 113 130 bool isCtorDtorAssign( const std::string & inputName ) { 131 const OperatorInfo * info = operatorLookup( inputName ); 132 if ( info ) return info->type <= OT_ASSIGNMENT; 133 return false; 134 } 114 135 115 bool isAssignment( const string & funcName ) {116 const OperatorInfo * info = operatorLookup( funcName );117 if ( info ) return info->type > OT_CONSTRUCTOR && info->type <= OT_ASSIGNMENT;118 return false;119 }120 121 bool isCtorDtorAssign( const string & funcName ) {122 const OperatorInfo * info = operatorLookup( funcName );123 if ( info ) return info->type <= OT_ASSIGNMENT;124 return false;125 }126 127 CodeGen codegen; // initialize singleton package128 136 } // namespace CodeGen 129 137 -
src/CodeGen/OperatorTable.h
r0030b508 rfc12f05 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : Sun Feb 16 08:13:34 202013 // Update Count : 2 611 // Last Modified By : Andrew Beach 12 // Last Modified On : Fri Nov 3 14:53:00 2023 13 // Update Count : 27 14 14 // 15 15 … … 17 17 18 18 #include <string> 19 #include <map>20 19 21 20 namespace CodeGen { 22 enum OperatorType {23 OT_CTOR,24 OT_DTOR,25 OT_CONSTRUCTOR = OT_DTOR,26 OT_PREFIXASSIGN,27 OT_POSTFIXASSIGN,28 OT_INFIXASSIGN,29 OT_ASSIGNMENT = OT_INFIXASSIGN,30 OT_CALL,31 OT_PREFIX,32 OT_INFIX,33 OT_POSTFIX,34 OT_INDEX,35 OT_LABELADDRESS,36 OT_CONSTANT37 };38 21 39 struct OperatorInfo { 40 std::string inputName; 41 std::string symbol; 42 std::string outputName; 43 std::string friendlyName; 44 OperatorType type; 45 }; 22 enum OperatorType { 23 OT_CTOR, 24 OT_DTOR, 25 OT_CONSTRUCTOR = OT_DTOR, 26 OT_PREFIXASSIGN, 27 OT_POSTFIXASSIGN, 28 OT_INFIXASSIGN, 29 OT_ASSIGNMENT = OT_INFIXASSIGN, 30 OT_CALL, 31 OT_PREFIX, 32 OT_INFIX, 33 OT_POSTFIX, 34 OT_INDEX, 35 OT_LABELADDRESS, 36 OT_CONSTANT 37 }; 46 38 47 class CodeGen { 48 friend const OperatorInfo * operatorLookup( const std::string & funcName ); 39 struct OperatorInfo { 40 // The Cforall special function name. 41 std::string inputName; 42 // The string used when the operator is used as an operator. 43 std::string symbol; 44 // The base name used in the mangled name. 45 std::string outputName; 46 // Human-readable name of the operator. 47 std::string friendlyName; 48 // The type of operator shows how it is used as an operator. 49 OperatorType type; 50 }; 49 51 50 static const OperatorInfo tableValues[]; 51 static std::map< std::string, OperatorInfo > table; 52 public: 53 CodeGen(); 54 }; // CodeGen 52 // Look up the operator (by inputName), return nullptr if no such operator. 53 const OperatorInfo * operatorLookup( const std::string & inputName ); 54 // Is there an operator with this name? 55 bool isOperator( const std::string & inputName ); 56 // Get the friendlyName of the operator with the inputName 57 std::string operatorFriendlyName( const std::string & inputName ); 58 // Get the OperatorInfo with the given outputName, if one exists. 59 const OperatorInfo * operatorLookupByOutput( const std::string & outputName ); 55 60 56 bool isOperator( const std::string & funcName ); 57 const OperatorInfo * operatorLookup( const std::string & funcName ); 58 std::string operatorFriendlyName( const std::string & funcName ); 61 // Is the operator a constructor, destructor or any form of assignment. 62 // (Last two are "or" combinations of the first three.) 63 bool isConstructor( const std::string & ); 64 bool isDestructor( const std::string & ); 65 bool isAssignment( const std::string & ); 66 bool isCtorDtor( const std::string & ); 67 bool isCtorDtorAssign( const std::string & ); 59 68 60 bool isConstructor( const std::string & );61 bool isDestructor( const std::string & );62 bool isAssignment( const std::string & );63 bool isCtorDtor( const std::string & );64 bool isCtorDtorAssign( const std::string & );65 69 } // namespace CodeGen 66 70 -
src/CodeGen/module.mk
r0030b508 rfc12f05 16 16 17 17 SRC_CODEGEN = \ 18 CodeGen/FixMain2.cc \ 19 CodeGen/FixMain.h \ 18 CodeGen/CodeGeneratorNew.cpp \ 19 CodeGen/CodeGeneratorNew.hpp \ 20 CodeGen/GenType.cc \ 21 CodeGen/GenType.h \ 20 22 CodeGen/OperatorTable.cc \ 21 23 CodeGen/OperatorTable.h 22 24 23 25 SRC += $(SRC_CODEGEN) \ 24 CodeGen/CodeGenerator.cc \25 CodeGen/CodeGenerator.h \26 26 CodeGen/Generate.cc \ 27 27 CodeGen/Generate.h \ 28 28 CodeGen/FixMain.cc \ 29 CodeGen/FixMain.h \ 29 30 CodeGen/FixNames.cc \ 30 31 CodeGen/FixNames.h \ 31 CodeGen/GenType.cc \32 CodeGen/GenType.h \33 32 CodeGen/LinkOnce.cc \ 34 33 CodeGen/LinkOnce.h \
Note:
See TracChangeset
for help on using the changeset viewer.