source: src/ControlStruct/FixLabels.cpp @ 6740533e

Last change on this file since 6740533e was b1f2007, checked in by Peter A. Buhr <pabuhr@…>, 11 months ago

first attempt at simplifying SemanticError? and its usage

  • Property mode set to 100644
File size: 3.0 KB
RevLine 
[b8ab91a]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
[37eb41b]11// Last Modified By : Peter A. Buhr
[b1f2007]12// Last Modified On : Sun Nov 26 15:06:51 2023
13// Update Count     : 10
[b8ab91a]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/MultiLevelExit.hpp"
[37eb41b]22using namespace ast;
[b8ab91a]23
24namespace ControlStruct {
[37eb41b]25class FixLabelsCore final : public WithGuards {
[21fe17f]26        LabelToStmt labelTable;
[37eb41b]27  public:
[a5a08a05]28        FixLabelsCore() : labelTable() {}
[b8ab91a]29
[37eb41b]30        void previsit( const FunctionDecl * );
31        const FunctionDecl * postvisit( const FunctionDecl * );
32        void previsit( const Stmt * );
33        void previsit( const BranchStmt * );
34        void previsit( const LabelAddressExpr * );
[b8ab91a]35
[37eb41b]36        void setLabelsDef( const std::vector<Label> &, const Stmt * );
37        void setLabelsUsage( const Label & );
[b8ab91a]38};
39
[37eb41b]40void FixLabelsCore::previsit( const FunctionDecl * ) {
[b8ab91a]41        GuardValue( labelTable ).clear();
42}
43
[37eb41b]44const FunctionDecl * FixLabelsCore::postvisit(
45        const FunctionDecl * decl ) {
[b8ab91a]46        if ( nullptr == decl->stmts ) return decl;
[21fe17f]47        for ( auto kvp : labelTable ) {
48                if ( nullptr == kvp.second ) {
[b1f2007]49                        SemanticError( kvp.first.location, "Use of undefined label %s.", kvp.first.name.c_str() );
[21fe17f]50                }
51        }
[37eb41b]52        return mutate_field( decl, &FunctionDecl::stmts,
53                                                 multiLevelExitUpdate( decl->stmts.get(), labelTable ) );
[b8ab91a]54}
55
[37eb41b]56void FixLabelsCore::previsit( const Stmt * stmt ) {
[21fe17f]57        if ( !stmt->labels.empty() ) {
58                setLabelsDef( stmt->labels, stmt );
[b8ab91a]59        }
60}
61
[37eb41b]62void FixLabelsCore::previsit( const BranchStmt * stmt ) {
[b8ab91a]63        if ( !stmt->labels.empty() ) {
[21fe17f]64                setLabelsDef( stmt->labels, stmt );
[b8ab91a]65        }
66        if ( !stmt->target.empty() ) {
[21fe17f]67                setLabelsUsage( stmt->target );
[b8ab91a]68        }
69}
70
[37eb41b]71void FixLabelsCore::previsit( const LabelAddressExpr * expr ) {
[b8ab91a]72        assert( !expr->arg.empty() );
[21fe17f]73        setLabelsUsage( expr->arg );
[b8ab91a]74}
75
[21fe17f]76void FixLabelsCore::setLabelsDef(
[37eb41b]77        const std::vector<Label> & labels, const Stmt * stmt ) {
[b8ab91a]78        assert( !labels.empty() );
79        assert( stmt );
80
81        for ( auto label : labels ) {
82                if ( labelTable.find( label ) == labelTable.end() ) {
83                        // Make sure to only create the entry once.
[21fe17f]84                        labelTable[ label ] = stmt;
85                } else if ( nullptr != labelTable[ label ] ) {
[b8ab91a]86                        // Duplicate definition, this is an error.
87                        SemanticError( label.location,
[37eb41b]88                                                   "Duplicate definition of label: " + label.name );
[b8ab91a]89                } else {
90                        // Perviously used, but not defined until now.
[21fe17f]91                        labelTable[ label ] = stmt;
[b8ab91a]92                }
93        }
94}
95
96// Label was used, if it is new add it to the table.
[37eb41b]97void FixLabelsCore::setLabelsUsage( const Label & label ) {
[b8ab91a]98        if ( labelTable.find( label ) == labelTable.end() ) {
[21fe17f]99                labelTable[ label ] = nullptr;
[b8ab91a]100        }
101}
102
[37eb41b]103void fixLabels( TranslationUnit & translationUnit ) {
104        Pass<FixLabelsCore>::run( translationUnit );
[b8ab91a]105}
106} // namespace ControlStruct
107
108// Local Variables: //
109// tab-width: 4 //
110// mode: c++ //
111// compile-command: "make install" //
112// End: //
Note: See TracBrowser for help on using the repository browser.