aliases

Search:
Group by:
Source   Edit  

Simple alias analysis for the HLO and the code generators.

Types

PartFlag = enum
  pfStructural,             ## use structural prefix-chain detection and tree-walk
  pfBidirectional            ## also check reverse direction per field in nkObjConstr
Source   Edit  
TAnalysisResult = enum
  arNo, arMaybe, arYes
Source   Edit  

Procs

proc isPartOf(a, b: PNode; flags: set[PartFlag] = {}): TAnalysisResult {.
    ...raises: [KeyError, OSError, Exception, ValueError, ERecoverableError],
    tags: [ReadEnvEffect, ReadIOEffect, ReadDirEffect, RootEffect], forbids: [].}

Checks if location a can be part of location b: i.e. whether writing to b could affect what a reads. We treat seqs and strings as pointers because the code gen often just passes them as such.

Note: a can only be part of b, if a's type can be part of b's type. Since however type analysis is more expensive, we perform it only if necessary.

When pfStructural is set additional aliasing is detected:

  • a structural prefix of an accessor chain is considered part of it (e.g. x.f <| x.f.g). Normally x.f !<| x.f.g because the same-kind nkDotExpr comparison treats the differing field names as siblings, but pfStructural walks the chain to recognise the relationship.
  • Unrecognised node kinds are traversed recursively.

When pfBidirectional is set:

  • In nkObjConstr the reverse direction isPartOf(value, a) is also checked per field value so that reads hidden behind calls/closures are detected.

cases:

YES-cases:

x    <| x   # for general trees
x[]  <| x
x[i] <| x
x.f  <| x
x.f  <| x.f.g   # when pfStructural (prefix chain)

NO-cases:

x           !<| y    # depending on type and symbol kind
x[constA]   !<| x[constB]
x.f         !<| x.g          # sibling fields at same level
x.f         !<| y.f  iff x !<= y

MAYBE-cases:

x[] ?<| y[]   iff compatible type


x[]  ?<| y  depending on type

Source   Edit