source: src/ControlStruct/ExceptTranslateNew.cpp @ 5ee153d

enumforall-pointer-decaypthread-emulation
Last change on this file since 5ee153d was 5ee153d, checked in by Andrew Beach <ajbeach@…>, 9 months ago

Translated the Translate Throws pass to the new ast.

  • Property mode set to 100644
File size: 4.2 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// ExceptTranslateNew.cpp -- Conversion of exception control flow structures.
8//
9// Author           : Andrew Beach
10// Created On       : Mon Nov  8 11:53:00 2021
11// Last Modified By : Andrew Beach
12// Last Modified On : Mon Nov  8 16:50:00 2021
13// Update Count     : 0
14//
15
16#include "ExceptTranslate.h"
17
18#include "AST/Expr.hpp"
19#include "AST/Pass.hpp"
20#include "AST/Stmt.hpp"
21#include "AST/TranslationUnit.hpp"
22
23namespace ControlStruct {
24
25namespace {
26
27class TranslateThrowsCore : public ast::WithGuards {
28        const ast::ObjectDecl * terminateHandlerExcept;
29        enum Context { NoHandler, TerHandler, ResHandler } currentContext;
30
31        const ast::Stmt * createEitherThrow(
32                const ast::ThrowStmt * throwStmt, const char * funcName );
33        const ast::Stmt * createTerminateRethrow( const ast::ThrowStmt * );
34
35public:
36        TranslateThrowsCore() :
37                terminateHandlerExcept( nullptr ), currentContext( NoHandler )
38        {}
39
40        void previsit( const ast::CatchStmt * stmt );
41        const ast::Stmt * postvisit( const ast::ThrowStmt * stmt );
42};
43
44const ast::Stmt * TranslateThrowsCore::createEitherThrow(
45                const ast::ThrowStmt * throwStmt, const char * funcName ) {
46        // `throwFunc`( `throwStmt->name` );
47        ast::UntypedExpr * call = new ast::UntypedExpr( throwStmt->location,
48                new ast::NameExpr( throwStmt->location, funcName )
49        );
50        call->args.push_back( throwStmt->expr );
51        return new ast::ExprStmt( throwStmt->location, call );
52}
53
54ast::VariableExpr * varOf( const ast::DeclWithType * decl ) {
55        return new ast::VariableExpr( decl->location, decl );
56}
57
58const ast::Stmt * TranslateThrowsCore::createTerminateRethrow(
59                const ast::ThrowStmt * stmt ) {
60        // { `terminate_handler_except` = 0p; __rethrow_terminate(); }
61        assert( nullptr == stmt->expr );
62        assert( terminateHandlerExcept );
63
64        ast::CompoundStmt * result = new ast::CompoundStmt(
65                stmt->location, {}, std::vector<ast::Label>( stmt->labels ) );
66        result->push_back( new ast::ExprStmt( stmt->location,
67                ast::UntypedExpr::createAssign(
68                        stmt->location,
69                        varOf( terminateHandlerExcept ),
70                        ast::ConstantExpr::null(
71                                stmt->location,
72                                terminateHandlerExcept->type
73                        )
74                )
75        ) );
76        result->push_back( new ast::ExprStmt( stmt->location, new ast::UntypedExpr(
77                stmt->location,
78                new ast::NameExpr( stmt->location, "__cfaehm_rethrow_terminate" )
79        ) ) );
80        return result;
81}
82
83void TranslateThrowsCore::previsit( const ast::CatchStmt * stmt ) {
84        // Validate the statement's form.
85        const ast::ObjectDecl * decl = stmt->decl.as<ast::ObjectDecl>();
86        // Also checking the type would be nice.
87        if ( !decl || !decl->type.as<ast::PointerType>() ) {
88                std::string kind = (ast::Terminate == stmt->kind) ? "catch" : "catchResume";
89                SemanticError( stmt->location, kind + " must have pointer to an exception type" );
90        }
91
92        // Track the handler context.
93        if ( ast::Terminate == stmt->kind ) {
94                GuardValue( currentContext ) = TerHandler;
95                GuardValue( terminateHandlerExcept ) = decl;
96        } else {
97                GuardValue( currentContext ) = ResHandler;
98        }
99}
100
101const ast::Stmt * TranslateThrowsCore::postvisit(
102                const ast::ThrowStmt * stmt ) {
103        // Ignoring ThrowStmt::target for now.
104        // Handle Termination (Raise, Reraise, Error):
105        if ( ast::Terminate == stmt->kind ) {
106                if ( stmt->expr ) {
107                        return createEitherThrow( stmt, "$throw" );
108                } else if ( TerHandler == currentContext ) {
109                        return createTerminateRethrow( stmt );
110                } else {
111                        abort( "Invalid throw in %s at %i\n",
112                                stmt->location.filename.c_str(),
113                                stmt->location.first_line);
114                }
115        // Handle Resumption (Raise, Reraise, Error):
116        } else {
117                if ( stmt->expr ) {
118                        return createEitherThrow( stmt, "$throwResume" );
119                } else if ( ResHandler == currentContext ) {
120                        // This has to be handled later.
121                        return stmt;
122                } else {
123                        abort( "Invalid throwResume in %s at %i\n",
124                                stmt->location.filename.c_str(),
125                                stmt->location.first_line);
126                }
127        }
128}
129
130} // namespace
131
132void translateThrows( ast::TranslationUnit & transUnit ) {
133        ast::Pass<TranslateThrowsCore>::run( transUnit );
134}
135
136} // namespace ControlStruct
137
138// Local Variables: //
139// tab-width: 4 //
140// mode: c++ //
141// compile-command: "make install" //
142// End: //
Note: See TracBrowser for help on using the repository browser.