source: src/ControlStruct/TranslateEnumRange.cpp @ 4dab7e8

Last change on this file since 4dab7e8 was 5f210c0, checked in by JiadaL <j82liang@…>, 4 months ago

Change enum pos to signed int to avoid underflow; operator on enum will not have range check (but succ and pred still have range check

  • Property mode set to 100644
File size: 2.9 KB
Line 
1#include "TranslateEnumRange.hpp"
2
3#include "AST/Pass.hpp"
4#include "AST/TranslationUnit.hpp"
5
6namespace ControlStruct {
7
8struct addInit {
9    const ast::Stmt * postvisit( const ast::ForStmt * stmt );
10};
11
12struct translateEnumRangeCore {
13    const ast::Stmt * postvisit( const ast::ForStmt * stmt );
14};
15
16const ast::Stmt* addInit::postvisit( const ast::ForStmt * stmt ) {
17    if ( stmt->range_over ) {
18        auto inits = stmt->inits;
19        auto init = stmt->inits.front();
20
21        if (auto declStmt = init.as<ast::DeclStmt>()) {
22            auto decl = declStmt->decl;
23            if ( auto objDecl = decl.as<ast::ObjectDecl>()) {
24                if ( !objDecl->init ) {
25                    auto location = stmt->location;
26                    ast::SingleInit * newInit = new ast::SingleInit( location, 
27                        stmt->is_inc?
28                        ast::UntypedExpr::createCall( location, "lowerBound", {} ):
29                        ast::UntypedExpr::createCall( location, "upperBound", {} ),
30                        ast::ConstructFlag::MaybeConstruct
31                    );
32                    auto objDeclWithInit = ast::mutate_field( objDecl, &ast::ObjectDecl::init, newInit );
33                    auto declWithInit = ast::mutate_field( declStmt, &ast::DeclStmt::decl, objDeclWithInit );
34                    stmt = ast::mutate_field_index( stmt, &ast::ForStmt::inits, 0, declWithInit );
35                }
36            }
37        }
38    }
39    return stmt;
40}
41
42const ast::Stmt* translateEnumRangeCore::postvisit( const ast::ForStmt * stmt ) {
43    if ( !stmt->range_over ) return stmt;
44    auto location = stmt->location;
45    auto declStmt = stmt->inits.front().strict_as<ast::DeclStmt>();
46    auto initDecl = declStmt->decl.strict_as<ast::ObjectDecl>();
47    auto indexName = initDecl->name;
48
49    // Both inc and dec check if the current posn less than the number of enumerator
50    // for dec, it keeps call pred until it passes 0 (the first enumerator) and underflow,
51    // it wraps around and become unsigned max
52    ast::UntypedExpr * condition = ast::UntypedExpr::createCall( location,
53        stmt->is_inc? "?<=?": "?>=?",
54        {   new ast::NameExpr( location, indexName ),
55            stmt->is_inc?
56                ast::UntypedExpr::createCall( location, "upperBound", {} ):
57                ast::UntypedExpr::createCall( location, "lowerBound", {} )
58        });
59    auto increment = ast::UntypedExpr::createCall( location, 
60        stmt->is_inc? "succ_unsafe": "pred_unsafe",
61        { new ast::NameExpr( location, indexName ) });
62    auto assig = ast::UntypedExpr::createAssign( location, new ast::NameExpr( location, indexName ), increment );
63    auto mut = ast::mutate_field( stmt, &ast::ForStmt::cond, condition );
64    mut = ast::mutate_field(stmt, &ast::ForStmt::inc, assig );
65    return mut;
66} 
67
68void translateEnumRange( ast::TranslationUnit & translationUnit ) {
69    ast::Pass<addInit>::run( translationUnit );
70    ast::Pass<translateEnumRangeCore>::run( translationUnit );
71}
72}
Note: See TracBrowser for help on using the repository browser.