Changeset 815943f


Ignore:
Timestamp:
Oct 5, 2022, 10:10:59 PM (19 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, ast-experimental, master
Children:
265e460
Parents:
ae151cf (diff), 0deeaad (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.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Files:
11 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/io.cfa

    rae151cf r815943f  
    243243                                /* paranoid */ verify( io.tscs[target].t.tv != ULLONG_MAX );
    244244                                HELP: if(target < ctxs_count) {
    245                                         const unsigned long long cutoff = calc_cutoff(ctsc, ctx->cq.id, ctxs_count, io.data, io.tscs, __shard_factor.io, false);
    246                                         const unsigned long long age = moving_average(ctsc, io.tscs[target].t.tv, io.tscs[target].t.ma, false);
     245                                        const __readyQ_avg_t cutoff = calc_cutoff(ctsc, ctx->cq.id, ctxs_count, io.data, io.tscs, __shard_factor.io, false);
     246                                        const __readyQ_avg_t age = moving_average(ctsc, io.tscs[target].t.tv, io.tscs[target].t.ma, false);
    247247                                        __cfadbg_print_safe(io, "Kernel I/O: Help attempt on %u from %u, age %'llu vs cutoff %'llu, %s\n", target, ctx->cq.id, age, cutoff, age > cutoff ? "yes" : "no");
    248248                                        if(age <= cutoff) break HELP;
  • libcfa/src/concurrency/kernel.hfa

    rae151cf r815943f  
    181181
    182182// Aligned timestamps which are used by the ready queue and io subsystem
    183 union __attribute__((aligned(64))) __timestamp_t {
    184         struct {
    185                 volatile unsigned long long tv;
    186                 volatile unsigned long long ma;
    187         } t;
    188         char __padding[192];
    189 };
    190 
    191 static inline void  ?{}(__timestamp_t & this) { this.t.tv = 0; this.t.ma = 0; }
    192 static inline void ^?{}(__timestamp_t &) {}
     183union __attribute__((aligned(64))) __timestamp_t;
     184
     185void  ?{}(__timestamp_t & this);
     186void ^?{}(__timestamp_t &);
    193187
    194188
  • libcfa/src/concurrency/kernel/cluster.cfa

    rae151cf r815943f  
    221221static const unsigned __readyq_single_shard = 2;
    222222
     223void  ?{}(__timestamp_t & this) { this.t.tv = 0; this.t.ma = 0; }
     224void ^?{}(__timestamp_t &) {}
     225
    223226//-----------------------------------------------------------------------
    224227// Check that all the intrusive queues in the data structure are still consistent
  • libcfa/src/concurrency/kernel/cluster.hfa

    rae151cf r815943f  
    1818#include "device/cpu.hfa"
    1919#include "kernel/private.hfa"
     20#include "math.hfa"
    2021
    2122#include <limits.h>
     
    2324#include "clock.hfa"
    2425
     26#if   defined(READYQ_USE_LINEAR_AVG)
     27
     28// no conversion needed in this case
     29static inline __readyQ_avg_t __to_readyQ_avg(unsigned long long intsc) { return intsc; }
     30
     31// warn normally all ints
     32#define warn_large_before warnf( !strict || old_avg < 33_000_000_000, "Suspiciously large previous average: %'llu (%llx), %'ldms \n", old_avg, old_avg, program()`ms )
     33#define warn_large_after warnf( !strict || ret < 33_000_000_000, "Suspiciously large new average after %'ldms cputime: %'llu (%llx) from %'llu-%'llu (%'llu, %'llu) and %'llu\n", program()`ms, ret, ret, currtsc, intsc, new_val, new_val / 1000000, old_avg )
     34
     35// 8X linear factor is just 8 * x
     36#define AVG_FACTOR( x ) (8 * (x))
     37
     38#elif defined(READYQ_USE_LOGDBL_AVG)
     39
     40// convert to log2 scale but using double
     41static inline __readyQ_avg_t __to_readyQ_avg(unsigned long long intsc) { if(unlikely(0 == intsc)) return 0.0; else return log2(intsc); }
     42
     43#define warn_large_before warnf( !strict || old_avg < 35.0, "Suspiciously large previous average: %'lf, %'ldms \n", old_avg, program()`ms )
     44#define warn_large_after warnf( !strict || ret < 35.3, "Suspiciously large new average after %'ldms cputime: %'lf from %'llu-%'llu (%'llu, %'llu) and %'lf\n", program()`ms, ret, currtsc, intsc, new_val, new_val / 1000000, old_avg ); \
     45verify(ret >= 0)
     46
     47// 8X factor in logscale is log2(8X) = log2(8) + log2(X) = 3 + log2(X)
     48#define AVG_FACTOR( x ) (3.0 + (x))
     49
     50// we need to overload the __atomic_load_n because they don't support double
     51static inline double __atomic_load_n(volatile double * ptr, int mem) {
     52        volatile uint64_t * uptr = (volatile uint64_t *)ptr;
     53        _Static_assert(sizeof(*uptr) == sizeof(*ptr));
     54        uint64_t ret = 0;
     55        ret = __atomic_load_n(uptr, mem);
     56        uint64_t *rp = &ret;
     57        double ret = *(volatile double *)rp;
     58        /* paranoid */ verify( ret == 0 || ret > 3e-100 );
     59        return ret;
     60}
     61
     62// we need to overload the __atomic_store_n because they don't support double
     63static inline void __atomic_store_n(volatile double * ptr, double val, int mem) {
     64        /* paranoid */ verify( val == 0 || val > 3e-100 );
     65        volatile uint64_t * uptr = (volatile uint64_t *)ptr;
     66        _Static_assert(sizeof(*uptr) == sizeof(*ptr));
     67        uint64_t * valp = (uint64_t *)&val;
     68        __atomic_store_n(uptr, *valp, mem);
     69}
     70
     71#elif defined(READYQ_USE_LOGDBL_AVG)
     72
     73//convert to log2 scale but with fix point u32.32 values
     74static inline __readyQ_avg_t __to_readyQ_avg(unsigned long long intsc) { return ulog2_32_32(tsc); }
     75
     76// 8X factor, +3 in logscale (see above) is + 0x3.00000000
     77#define AVG_FACTOR( x ) (0x3_00000000ull + (x))
     78
     79#else
     80#error must pick a scheme for averaging
     81#endif
     82
    2583//-----------------------------------------------------------------------
    2684// Calc moving average based on existing average, before and current time.
    27 static inline unsigned long long moving_average(unsigned long long currtsc, unsigned long long instsc, unsigned long long old_avg, bool strict) {
     85static inline __readyQ_avg_t moving_average(unsigned long long currtsc, unsigned long long intsc, __readyQ_avg_t old_avg, bool strict) {
    2886        (void)strict; // disable the warning around the fact this is unused in release.
    29         /* paranoid */ warnf( !strict || old_avg < 33_000_000_000, "Suspiciously large previous average: %'llu (%llx), %'ldms \n", old_avg, old_avg, program()`ms );
     87        /* paranoid */ warn_large_before;
    3088
    31         const unsigned long long new_val = currtsc > instsc ? currtsc - instsc : 0;
    32         const unsigned long long total_weight = 16;
    33         const unsigned long long new_weight   = 4;
    34         const unsigned long long old_weight = total_weight - new_weight;
    35         const unsigned long long ret = ((new_weight * new_val) + (old_weight * old_avg)) / total_weight;
     89        const unsigned long long new_val = currtsc > intsc ? currtsc - intsc : 0;
     90        const __readyQ_avg_t total_weight = 16;
     91        const __readyQ_avg_t new_weight   = 12;
     92        const __readyQ_avg_t old_weight = total_weight - new_weight;
     93        const __readyQ_avg_t ret = ((new_weight * __to_readyQ_avg(new_val)) + (old_weight * old_avg)) / total_weight;
    3694
    37         /* paranoid */ warnf( !strict || ret < 33_000_000_000, "Suspiciously large new average after %'ldms cputime: %'llu (%llx) from %'llu-%'llu (%'llu, %'llu) and %'llu\n", program()`ms, ret, ret, currtsc, instsc, new_val, new_val / 1000000, old_avg );
     95        /* paranoid */ warn_large_after;
    3896        return ret;
    3997}
     
    42100        if (ts_next == ULLONG_MAX) return;
    43101        unsigned long long now = rdtscl();
    44         unsigned long long pma = __atomic_load_n(&tscs[ idx ].t.ma, __ATOMIC_RELAXED);
     102        __readyQ_avg_t pma = __atomic_load_n(&tscs[ idx ].t.ma, __ATOMIC_RELAXED);
    45103        __atomic_store_n(&tscs[ idx ].t.tv, ts_next, __ATOMIC_RELAXED);
    46104        __atomic_store_n(&tscs[ idx ].t.ma, moving_average(now, ts_prev, pma, strict), __ATOMIC_RELAXED);
     
    50108// Calc age a timestamp should be before needing help.
    51109forall(Data_t * | { unsigned long long ts(Data_t & this); })
    52 static inline unsigned long long calc_cutoff(
     110static inline __readyQ_avg_t calc_cutoff(
    53111        const unsigned long long ctsc,
    54112        unsigned procid,
     
    60118) {
    61119        unsigned start = procid;
    62         unsigned long long max = 0;
     120        __readyQ_avg_t max = 0;
    63121        for(i; shard_factor) {
    64122                unsigned long long ptsc = ts(data[start + i]);
    65123                if(ptsc != ULLONG_MAX) {
    66124                        /* paranoid */ verify( start + i < count );
    67                         unsigned long long tsc = moving_average(ctsc, ptsc, tscs[start + i].t.ma, strict);
    68                         if(tsc > max) max = tsc;
     125                        __readyQ_avg_t avg = moving_average(ctsc, ptsc, tscs[start + i].t.ma, strict);
     126                        if(avg > max) max = avg;
    69127                }
    70128        }
    71         return 8 * max;
     129        return AVG_FACTOR( max );
    72130}
    73131
  • libcfa/src/concurrency/kernel/private.hfa

    rae151cf r815943f  
    4949#endif
    5050
     51// #define READYQ_USE_LINEAR_AVG
     52#define READYQ_USE_LOGDBL_AVG
     53// #define READYQ_USE_LOGINT_AVG
     54
     55#if   defined(READYQ_USE_LINEAR_AVG)
     56typedef unsigned long long __readyQ_avg_t;
     57#elif defined(READYQ_USE_LOGDBL_AVG)
     58typedef double __readyQ_avg_t;
     59#elif defined(READYQ_USE_LOGDBL_AVG)
     60typedef unsigned long long __readyQ_avg_t;
     61#else
     62#error must pick a scheme for averaging
     63#endif
     64
    5165//-----------------------------------------------------------------------------
    5266// Scheduler
     67union __attribute__((aligned(64))) __timestamp_t {
     68        struct {
     69                volatile unsigned long long tv;
     70                volatile __readyQ_avg_t ma;
     71        } t;
     72        char __padding[192];
     73};
     74
    5375extern "C" {
    5476        void disable_interrupts() OPTIONAL_THREAD;
  • libcfa/src/concurrency/ready_queue.cfa

    rae151cf r815943f  
    139139                /* paranoid */ verify( readyQ.tscs[target].t.tv != ULLONG_MAX );
    140140                if(target < lanes_count) {
    141                         const unsigned long long cutoff = calc_cutoff(ctsc, proc->rdq.id, lanes_count, cltr->sched.readyQ.data, cltr->sched.readyQ.tscs, __shard_factor.readyq, true);
    142                         const unsigned long long age = moving_average(ctsc, readyQ.tscs[target].t.tv, readyQ.tscs[target].t.ma, false);
     141                        const __readyQ_avg_t cutoff = calc_cutoff(ctsc, proc->rdq.id, lanes_count, cltr->sched.readyQ.data, cltr->sched.readyQ.tscs, __shard_factor.readyq, true);
     142                        const __readyQ_avg_t age = moving_average(ctsc, readyQ.tscs[target].t.tv, readyQ.tscs[target].t.ma, false);
    143143                        __cfadbg_print_safe(ready_queue, "Kernel : Help attempt on %u from %u, age %'llu vs cutoff %'llu, %s\n", target, this, age, cutoff, age > cutoff ? "yes" : "no");
    144144                        if(age > cutoff) {
  • libcfa/src/math.hfa

    rae151cf r815943f  
    2222
    2323#include "common.hfa"
     24#include "bits/debug.hfa"
    2425
    2526//---------------------- General ----------------------
     
    307308        // forall( T | { T ?+?( T, T ); T ?-?( T, T ); T ?%?( T, T ); } )
    308309        // T ceiling_div( T n, T align ) { verify( is_pow2( align ) );return (n + (align - 1)) / align; }
    309        
     310
    310311        // gcc notices the div/mod pair and saves both so only one div.
    311312        signed char ceiling( signed char n, signed char align ) { return floor( n + (n % align != 0 ? align - 1 : 0), align ); }
     
    429430} // distribution
    430431
     432static inline unsigned long long log2_u32_32(unsigned long long val) {
     433        enum {
     434                TABLE_BITS = 6,
     435                TABLE_SIZE = (1 << TABLE_BITS) + 2,
     436        };
     437        // for(i; TABLE_SIZE) {
     438        //      table[i] = (unsigned long long)(log2(1.0 + i / pow(2, TABLE_BITS)) * pow(2, 32)));
     439        // }
     440        static const unsigned long long table[] = {
     441                0x0000000000, 0x0005b9e5a1, 0x000b5d69ba, 0x0010eb389f,
     442                0x001663f6fa, 0x001bc84240, 0x002118b119, 0x002655d3c4,
     443                0x002b803473, 0x00309857a0, 0x00359ebc5b, 0x003a93dc98,
     444                0x003f782d72, 0x00444c1f6b, 0x0049101eac, 0x004dc4933a,
     445                0x005269e12f, 0x00570068e7, 0x005b888736, 0x006002958c,
     446                0x00646eea24, 0x0068cdd829, 0x006d1fafdc, 0x007164beb4,
     447                0x00759d4f80, 0x0079c9aa87, 0x007dea15a3, 0x0081fed45c,
     448                0x0086082806, 0x008a064fd5, 0x008df988f4, 0x0091e20ea1,
     449                0x0095c01a39, 0x009993e355, 0x009d5d9fd5, 0x00a11d83f4,
     450                0x00a4d3c25e, 0x00a8808c38, 0x00ac241134, 0x00afbe7fa0,
     451                0x00b3500472, 0x00b6d8cb53, 0x00ba58feb2, 0x00bdd0c7c9,
     452                0x00c1404ead, 0x00c4a7ba58, 0x00c80730b0, 0x00cb5ed695,
     453                0x00ceaecfea, 0x00d1f73f9c, 0x00d53847ac, 0x00d8720935,
     454                0x00dba4a47a, 0x00ded038e6, 0x00e1f4e517, 0x00e512c6e5,
     455                0x00e829fb69, 0x00eb3a9f01, 0x00ee44cd59, 0x00f148a170,
     456                0x00f446359b, 0x00f73da38d, 0x00fa2f045e, 0x00fd1a708b,
     457                0x0100000000, 0x0102dfca16,
     458        };
     459        _Static_assert((sizeof(table) / sizeof(table[0])) == TABLE_SIZE, "TABLE_SIZE should be accurate");
     460        // starting from val = (2 ** i)*(1 + f) where 0 <= f < 1
     461        // log identities mean log2(val) = log2((2 ** i)*(1 + f)) = log2(2**i) + log2(1+f)
     462        //
     463        // getting i is easy to do using builtin_clz (count leading zero)
     464        //
     465        // we want to calculate log2(1+f) independently to have a many bits of precision as possible.
     466        //     val = (2 ** i)*(1 + f) = 2 ** i   +   f * 2 ** i
     467        // isolating f we get
     468        //     val - 2 ** i = f * 2 ** i
     469        //     (val - 2 ** i) / 2 ** i = f
     470        //
     471        // we want to interpolate from the table to get the values
     472        // and compromise by doing quadratic interpolation (rather than higher degree interpolation)
     473        //
     474        // for the interpolation we want to shift everything the fist sample point
     475        // so our parabola becomes x = 0
     476        // this further simplifies the equations
     477        //
     478        // the consequence is that we need f in 2 forms:
     479        //  - finding the index of x0
     480        //  - finding the distance between f and x0
     481        //
     482        // since sample points are equidistant we can significantly simplify the equations
     483
     484        // get i
     485        const unsigned long long bits = sizeof(val) * __CHAR_BIT__;
     486        const unsigned long long lz = __builtin_clzl(val);
     487        const unsigned long long i = bits - 1 - lz;
     488
     489        // get the fractinal part as a u32.32
     490        const unsigned long long frac = (val << (lz + 1)) >> 32;
     491
     492        // get high order bits for the index into the table
     493        const unsigned long long idx0 = frac >> (32 - TABLE_BITS);
     494
     495        // get the x offset, i.e., the difference between the first sample point and the actual fractional part
     496        const long long udx = frac - (idx0 << (32 - TABLE_BITS));
     497        /* paranoid */ verify((idx0 + 2) < TABLE_SIZE);
     498
     499        const long long y0 = table[idx0 + 0];
     500        const long long y1 = table[idx0 + 1];
     501        const long long y2 = table[idx0 + 2];
     502
     503        // from there we can quadraticly interpolate to get the data, using the lagrange polynomial
     504        // normally it would look like:
     505        //     double r0 = y0 * ((x - x1) / (x0 - x1)) * ((x - x2) / (x0 - x2));
     506        //     double r1 = y1 * ((x - x0) / (x1 - x0)) * ((x - x2) / (x1 - x2));
     507        //     double r2 = y2 * ((x - x0) / (x2 - x0)) * ((x - x1) / (x2 - x1));
     508        // but since the spacing between sample points is fixed, we can simplify it and extract common expressions
     509        const long long f1 = (y1 - y0);
     510        const long long f2 = (y2 - y0);
     511        const long long a = f2 - (f1 * 2l);
     512        const long long b = (f1 * 2l) - a;
     513
     514        // Now we can compute it in the form (ax + b)x + c (which avoid repeating steps)
     515        long long sum = ((a*udx) >> (32 - TABLE_BITS))  + b;
     516        sum = (sum*udx) >> (32 - TABLE_BITS + 1);
     517        sum = y0 + sum;
     518
     519        return (i << 32) + (sum);
     520}
     521
    431522// Local Variables: //
    432523// mode: c //
  • src/AST/Inspect.cpp

    rae151cf r815943f  
    1010// Created On       : Fri Jun 24 13:16:31 2022
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Sep 22 13:50:00 2022
    13 // Update Count     : 2
     12// Last Modified On : Mon Oct  3 11:04:00 2022
     13// Update Count     : 3
    1414//
    1515
     
    1717
    1818#include <iostream>
     19#include <iterator>
    1920
    2021#include "AST/Decl.hpp"
     
    2728namespace ast {
    2829
    29 const Type * getPointerBase( const Type * t ) {
    30         if ( const auto * p = dynamic_cast< const PointerType * >( t ) ) {
     30const Type * getPointerBase( const Type * type ) {
     31        if ( const auto * p = dynamic_cast< const PointerType * >( type ) ) {
    3132                return p->base;
    32         } else if ( const auto * a = dynamic_cast< const ArrayType * >( t ) ) {
     33        } else if ( auto a = dynamic_cast< const ArrayType * >( type ) ) {
    3334                return a->base;
    34         } else if ( const auto * r = dynamic_cast< const ReferenceType * >( t ) ) {
     35        } else if ( auto r = dynamic_cast< const ReferenceType * >( type ) ) {
    3536                return r->base;
    3637        } else {
    3738                return nullptr;
    3839        }
    39 }
    40 
    41 template<typename CallExpr>
    42 static const Expr * callArg( const CallExpr * call, unsigned int pos ) {
    43         assertf( pos < call->args.size(),
    44                 "getCallArg for argument that doesn't exist: (%u); %s.",
    45                 pos, toString( call ).c_str() );
    46         for ( const Expr * arg : call->args ) {
    47                 if ( 0 == pos ) return arg;
    48                 --pos;
    49         }
    50         assert( false );
    5140}
    5241
     
    5645        std::string name = getFunctionName( expr );
    5746        assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
    58         assertf( !expr->args.empty(), "Cannot get function name from dereference with no arguments" );
     47        assertf( !expr->args.empty(), "Cannot pass through dereference with no arguments." );
    5948        return func( expr->args.front() );
    6049}
     
    6251static const DeclWithType * getCalledFunction( const Expr * expr ) {
    6352        assert( expr );
    64         if ( const ast::VariableExpr * varExpr = dynamic_cast< const ast::VariableExpr * >( expr ) ) {
     53        if ( const auto * varExpr = dynamic_cast< const VariableExpr * >( expr ) ) {
    6554                return varExpr->var;
    66         } else if ( const ast::MemberExpr * memberExpr = dynamic_cast< const ast::MemberExpr * >( expr ) ) {
     55        } else if ( auto memberExpr = dynamic_cast< const MemberExpr * >( expr ) ) {
    6756                return memberExpr->member;
    68         } else if ( const ast::CastExpr * castExpr = dynamic_cast< const ast::CastExpr * >( expr ) ) {
     57        } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
    6958                return getCalledFunction( castExpr->arg );
    70         } else if ( const ast::UntypedExpr * untypedExpr = dynamic_cast< const ast::UntypedExpr * >( expr ) ) {
     59        } else if ( auto untypedExpr = dynamic_cast< const UntypedExpr * >( expr ) ) {
    7160                return throughDeref( untypedExpr, getCalledFunction );
    72         } else if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * > ( expr ) ) {
     61        } else if ( auto appExpr = dynamic_cast< const ApplicationExpr * > ( expr ) ) {
    7362                return throughDeref( appExpr, getCalledFunction );
    74         } else if ( const ast::AddressExpr * addrExpr = dynamic_cast< const ast::AddressExpr * >( expr ) ) {
     63        } else if ( auto addrExpr = dynamic_cast< const AddressExpr * >( expr ) ) {
    7564                return getCalledFunction( addrExpr->arg );
    76         } else if ( const ast::CommaExpr * commaExpr = dynamic_cast< const ast::CommaExpr * >( expr ) ) {
     65        } else if ( auto commaExpr = dynamic_cast< const CommaExpr * >( expr ) ) {
    7766                return getCalledFunction( commaExpr->arg2 );
     67        } else {
     68                return nullptr;
    7869        }
    79         return nullptr;
    8070}
    8171
     
    8575        } else if ( auto untyped = dynamic_cast< const UntypedExpr * >( expr ) ) {
    8676                return getCalledFunction( untyped->func );
     77        } else {
     78                assertf( false, "getFunction received unknown expression: %s", toString( expr ).c_str() );
    8779        }
    88         assertf( false, "getFunction received unknown expression: %s", toString( expr ).c_str() );
    8980}
    9081
     
    9485static std::string funcName( const Expr * func ) {
    9586        assert( func );
    96         if ( const ast::NameExpr * nameExpr = dynamic_cast< const ast::NameExpr * >( func ) ) {
     87        if ( const auto * nameExpr = dynamic_cast< const NameExpr * >( func ) ) {
    9788                return nameExpr->name;
    98         } else if ( const ast::VariableExpr * varExpr = dynamic_cast< const ast::VariableExpr * >( func ) ) {
     89        } else if ( auto varExpr = dynamic_cast< const VariableExpr * >( func ) ) {
    9990                return varExpr->var->name;
    100         } else if ( const ast::CastExpr * castExpr = dynamic_cast< const ast::CastExpr * >( func ) ) {
     91        } else if ( auto castExpr = dynamic_cast< const CastExpr * >( func ) ) {
    10192                return funcName( castExpr->arg );
    102         } else if ( const ast::MemberExpr * memberExpr = dynamic_cast< const ast::MemberExpr * >( func ) ) {
     93        } else if ( auto memberExpr = dynamic_cast< const MemberExpr * >( func ) ) {
    10394                return memberExpr->member->name;
    104         } else if ( const ast::UntypedMemberExpr * memberExpr = dynamic_cast< const ast::UntypedMemberExpr * > ( func ) ) {
     95        } else if ( auto memberExpr = dynamic_cast< const UntypedMemberExpr * >( func ) ) {
    10596                return funcName( memberExpr->member );
    106         } else if ( const ast::UntypedExpr * untypedExpr = dynamic_cast< const ast::UntypedExpr * >( func ) ) {
     97        } else if ( auto untypedExpr = dynamic_cast< const UntypedExpr * >( func ) ) {
    10798                return throughDeref( untypedExpr, funcName );
    108         } else if ( const ast::ApplicationExpr * appExpr = dynamic_cast< const ast::ApplicationExpr * >( func ) ) {
     99        } else if ( auto appExpr = dynamic_cast< const ApplicationExpr * >( func ) ) {
    109100                return throughDeref( appExpr, funcName );
    110         } else if ( const ast::ConstructorExpr * ctorExpr = dynamic_cast< const ast::ConstructorExpr * >( func ) ) {
     101        } else if ( auto ctorExpr = dynamic_cast< const ConstructorExpr * >( func ) ) {
    111102                return funcName( getCallArg( ctorExpr->callExpr, 0 ) );
    112103        } else {
     
    116107
    117108std::string getFunctionName( const Expr * expr ) {
    118         // There's some unforunate overlap here with getCalledFunction. Ideally
    119         // this would be able to use getCalledFunction and return the name of the
    120         // DeclWithType, but this needs to work for NameExpr and UntypedMemberExpr,
    121         // where getCalledFunction can't possibly do anything reasonable.
     109        // There's some unforunate overlap here with getFunction. See above.
    122110        if ( auto app = dynamic_cast< const ApplicationExpr * >( expr ) ) {
    123111                return funcName( app->func );
     
    125113                return funcName( untyped->func );
    126114        } else {
    127                 assertf( false, "Unexpected expression type passed to getFunctionName: %s", toString( expr ).c_str() );
     115                assertf( false, "getFunctionName received unknown expression: %s", toString( expr ).c_str() );
    128116        }
     117}
     118
     119template<typename CallExpr>
     120static const Expr * callArg( const CallExpr * call, unsigned int pos ) {
     121        assertf( pos < call->args.size(),
     122                "callArg for argument that doesn't exist: (%u); %s.",
     123                pos, toString( call ).c_str() );
     124        auto it = call->args.begin();
     125        std::advance( it, pos );
     126        return *it;
    129127}
    130128
     
    137135                const std::list<ptr<Stmt>>& stmts = tupleAssn->stmtExpr->stmts->kids;
    138136                assertf( !stmts.empty(), "TupleAssignExpr missing statements." );
    139                 auto stmt  = strict_dynamic_cast< const ExprStmt * >( stmts.back().get() );
    140                 auto tuple = strict_dynamic_cast< const TupleExpr * >( stmt->expr.get() );
     137                auto stmt  = stmts.back().strict_as< ExprStmt >();
     138                auto tuple = stmt->expr.strict_as< TupleExpr >();
    141139                assertf( !tuple->exprs.empty(), "TupleAssignExpr has empty tuple expr." );
    142140                return getCallArg( tuple->exprs.front(), pos );
     
    144142                return getCallArg( ctor->callExpr, pos );
    145143        } else {
    146                 assertf( false, "Unexpected expression type passed to getCallArg: %s",
    147                         toString( call ).c_str() );
     144                assertf( false, "Unexpected expression type passed to getCallArg: %s", toString( call ).c_str() );
    148145        }
    149146}
     
    165162
    166163        const DeclWithType * func = getCalledFunction( appExpr->func );
    167         assertf( func,
    168                 "getCalledFunction returned nullptr: %s", toString( appExpr->func ).c_str() );
     164        assertf( func, "getCalledFunction returned nullptr: %s",
     165                toString( appExpr->func ).c_str() );
    169166
    170         return func->linkage == ast::Linkage::Intrinsic ? appExpr : nullptr;
     167        return func->linkage == Linkage::Intrinsic ? appExpr : nullptr;
    171168}
    172169
  • src/AST/SymbolTable.cpp

    rae151cf r815943f  
    316316
    317317void SymbolTable::addStruct( const std::string &id ) {
    318         addStruct( new StructDecl( CodeLocation{}, id ) );
     318        addStruct( new StructDecl( CodeLocation(), id ) );
    319319}
    320320
     
    358358
    359359void SymbolTable::addUnion( const std::string &id ) {
    360         addUnion( new UnionDecl( CodeLocation{}, id ) );
     360        addUnion( new UnionDecl( CodeLocation(), id ) );
    361361}
    362362
  • src/AST/Type.cpp

    rae151cf r815943f  
    176176        for ( const Type * ty : types ) {
    177177                members.emplace_back( new ObjectDecl{
    178                         CodeLocation{}, "", ty, new ListInit( CodeLocation{}, {}, {}, NoConstruct ),
     178                        CodeLocation(), "", ty, new ListInit( CodeLocation(), {}, {}, NoConstruct ),
    179179                        Storage::Classes{}, Linkage::Cforall } );
    180180        }
  • src/InitTweak/InitTweak.cc

    rae151cf r815943f  
    881881                static ast::ptr<ast::FunctionDecl> assign = nullptr;
    882882                if (!assign) {
    883                         auto td = new ast::TypeDecl({}, "T", {}, nullptr, ast::TypeDecl::Dtype, true);
    884                         assign = new ast::FunctionDecl({}, "?=?", {},
    885                         { new ast::ObjectDecl({}, "_dst", new ast::ReferenceType(new ast::TypeInstType("T", td))),
    886                           new ast::ObjectDecl({}, "_src", new ast::TypeInstType("T", td))},
    887                         { new ast::ObjectDecl({}, "_ret", new ast::TypeInstType("T", td))}, nullptr, {}, ast::Linkage::Intrinsic);
     883                        auto td = new ast::TypeDecl(CodeLocation(), "T", {}, nullptr, ast::TypeDecl::Dtype, true);
     884                        assign = new ast::FunctionDecl(CodeLocation(), "?=?", {},
     885                        { new ast::ObjectDecl(CodeLocation(), "_dst", new ast::ReferenceType(new ast::TypeInstType("T", td))),
     886                          new ast::ObjectDecl(CodeLocation(), "_src", new ast::TypeInstType("T", td))},
     887                        { new ast::ObjectDecl(CodeLocation(), "_ret", new ast::TypeInstType("T", td))}, nullptr, {}, ast::Linkage::Intrinsic);
    888888                }
    889889                if (dst->result.as<ast::ReferenceType>()) {
Note: See TracChangeset for help on using the changeset viewer.