source: src/ControlStruct/FixLabels.cpp @ de31a1d

ADTast-experimentalenumforall-pointer-decaypthread-emulationqualifiedEnum
Last change on this file since de31a1d was de31a1d, checked in by Andrew Beach <ajbeach@…>, 2 years ago

Converted the two LabelGenerator? singletons into a single pure-static class.

  • Property mode set to 100644
File size: 3.3 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// FixLabels.cpp -- Normalizes labels and handles multi-level exit labels.
8//
9// Author           : Andrew Beach
10// Created On       : Mon Nov  1 09:39:00 2021
11// Last Modified By : Andrew Beach
12// Last Modified On : Mon Nov  5 19:20:00 2021
13// Update Count     : 2
14//
15
16#include "FixLabels.hpp"
17
18#include "AST/Label.hpp"
19#include "AST/Pass.hpp"
20#include "AST/Stmt.hpp"
21#include "ControlStruct/LabelGenerator.h"
22#include "ControlStruct/MultiLevelExit.hpp"
23
24namespace ControlStruct {
25
26namespace {
27
28class FixLabelsCore final : public ast::WithGuards {
29        LabelToStmt labelTable;
30        LabelGenerator * label_gen;
31public:
32        FixLabelsCore( LabelGenerator * gen = nullptr ) :
33                labelTable(),
34                label_gen( gen ? gen : LabelGenerator::getGenerator() )
35        {}
36
37        void previsit( const ast::FunctionDecl * );
38        const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
39        void previsit( const ast::Stmt * );
40        void previsit( const ast::BranchStmt * );
41        void previsit( const ast::LabelAddressExpr * );
42
43        void setLabelsDef( const std::vector<ast::Label> &, const ast::Stmt * );
44        void setLabelsUsage( const ast::Label & );
45};
46
47void FixLabelsCore::previsit( const ast::FunctionDecl * ) {
48        GuardValue( labelTable ).clear();
49}
50
51const ast::FunctionDecl * FixLabelsCore::postvisit(
52                const ast::FunctionDecl * decl ) {
53        if ( nullptr == decl->stmts ) return decl;
54        for ( auto kvp : labelTable ) {
55                if ( nullptr == kvp.second ) {
56                        SemanticError( kvp.first.location,
57                                "Use of undefined label: " + kvp.first.name );
58                }
59        }
60        return ast::mutate_field( decl, &ast::FunctionDecl::stmts,
61                multiLevelExitUpdate( decl->stmts.get(), labelTable, label_gen ) );
62}
63
64void FixLabelsCore::previsit( const ast::Stmt * stmt ) {
65        if ( !stmt->labels.empty() ) {
66                setLabelsDef( stmt->labels, stmt );
67        }
68}
69
70void FixLabelsCore::previsit( const ast::BranchStmt * stmt ) {
71        if ( !stmt->labels.empty() ) {
72                setLabelsDef( stmt->labels, stmt );
73        }
74        if ( !stmt->target.empty() ) {
75                setLabelsUsage( stmt->target );
76        }
77}
78
79void FixLabelsCore::previsit( const ast::LabelAddressExpr * expr ) {
80        assert( !expr->arg.empty() );
81        setLabelsUsage( expr->arg );
82}
83
84void FixLabelsCore::setLabelsDef(
85                const std::vector<ast::Label> & labels, const ast::Stmt * stmt ) {
86        assert( !labels.empty() );
87        assert( stmt );
88
89        for ( auto label : labels ) {
90                if ( labelTable.find( label ) == labelTable.end() ) {
91                        // Make sure to only create the entry once.
92                        labelTable[ label ] = stmt;
93                } else if ( nullptr != labelTable[ label ] ) {
94                        // Duplicate definition, this is an error.
95                        SemanticError( label.location,
96                                "Duplicate definition of label: " + label.name );
97                } else {
98                        // Perviously used, but not defined until now.
99                        labelTable[ label ] = stmt;
100                }
101        }
102}
103
104// Label was used, if it is new add it to the table.
105void FixLabelsCore::setLabelsUsage( const ast::Label & label ) {
106        if ( labelTable.find( label ) == labelTable.end() ) {
107                labelTable[ label ] = nullptr;
108        }
109}
110
111} // namespace
112
113void fixLabels( ast::TranslationUnit & translationUnit ) {
114        ast::Pass<FixLabelsCore>::run( translationUnit );
115}
116
117} // namespace ControlStruct
118
119// Local Variables: //
120// tab-width: 4 //
121// mode: c++ //
122// compile-command: "make install" //
123// End: //
Note: See TracBrowser for help on using the repository browser.