dmd.toir

Convert to Intermediate Representation (IR) for the back-end.

Authors

Walter Bright

Source: toir.d

  • Declaration

    struct Label;

    Our label symbol

  • Declaration

    struct IRState;

    Collect state variables needed by the intermediate representation (IR)

    • Declaration

      bool arrayBoundsCheck();

      Return Value

      true if do array bounds checking for the current function

    • Declaration

      @safe bool isNothrow();

      Return Value

      true if in a nothrow section of code

  • Declaration

    elem* incUsageElem(ref IRState irs, const ref Loc loc);

    Produce elem which increments the usage count for a particular line. Sets corresponding bit in bitmap m.covb[linnum]. Used to implement -cov switch (coverage analysis).

    Parameters

    IRState irs

    context

    Loc loc

    line and file of what line to show usage for

    Return Value

    elem that increments the line count

  • Declaration

    elem* getEthis(const ref Loc loc, ref IRState irs, Dsymbol fd, Dsymbol fdp = null, Dsymbol origSc = null);

    Return elem that evaluates to the static frame pointer for function fd. If fd is a member function, the returned expression will compute the value of fd's 'this' variable. 'fdp' is the parent of 'fd' if the frame pointer is being used to call 'fd'. 'origSc' is the original scope we inlined from. This routine is critical for implementing nested functions.

  • Declaration

    elem* fixEthis2(elem* ethis, FuncDeclaration fd, bool ctxt2 = false);

    Select one context pointer from a dual-context array

    Return Value

    *(ethis + offset);

  • Declaration

    elem* setEthis(const ref Loc loc, ref IRState irs, elem* ey, AggregateDeclaration ad, bool setthis2 = false);

    Initialize the hidden aggregate member, vthis, with the context pointer.

    Return Value

    *(ey + (ethis2 ? ad.vthis2 : ad.vthis).offset) = this;

  • Declaration

    int intrinsic_op(FuncDeclaration fd);

    Convert intrinsic function to operator.

    Return Value

    the operator as backend OPER, NotIntrinsic if not an intrinsic function, OPtoPrec if frontend-only intrinsic

  • Declaration

    elem* resolveLengthVar(VarDeclaration lengthVar, elem** pe, Type t1);

    Given an expression e that is an array, determine and set the 'length' variable.

    Input: lengthVar Symbol of 'length' variable &e expression that is the array t1 Type of the array

    Output: e is rewritten to avoid side effects

    Return Value

    expression that initializes 'length'

  • Declaration

    TYPE* getParentClosureType(Symbol* sthis, FuncDeclaration fd);

    for a nested function 'fd' return the type of the closure of an outer function or aggregate. If the function is a member function the 'this' type is expected to be stored in 'sthis.Sthis'. It is always returned if it is not a void pointer. buildClosure() must have been called on the outer function before.

    Parameters

    Symbol* sthis

    the symbol of the current 'this' derived from fd.vthis

    FuncDeclaration fd

    the nested function

  • Declaration

    uint setClosureVarOffset(FuncDeclaration fd);

    Go through the variables in function fd that are to be allocated in a closure, and set the .offset fields for those variables to their positions relative to the start of the closure instance. Also turns off nrvo for closure variables.

    Parameters

    FuncDeclaration fd

    function

    Return Value

    overall alignment of the closure

  • Declaration

    void buildClosure(FuncDeclaration fd, ref IRState irs);

    Closures are implemented by taking the local variables that need to survive the scope of the function, and copying them into a gc allocated chuck of memory. That chunk, called the closure here, is inserted into the linked list of stack frames instead of the usual stack frame.

    Discussion

    buildClosure() inserts code just after the function prolog is complete. It allocates memory for the closure, allocates a local variable (sclosure) to point to it, inserts into it the link to the enclosing frame, and copies into it the parameters that are referred to in nested functions. In VarExp::toElem and SymOffExp::toElem, when referring to a variable that is in a closure, takes the offset from sclosure rather than from the frame pointer.

    getEthis() and NewExp::toElem need to use sclosure, if set, rather than the current frame pointer.

  • Declaration

    void buildAlignSection(FuncDeclaration fd, ref IRState irs);

    Aligned sections are implemented by taking the local variables that need alignment that is larger than the stack alignment. They are allocated into a separate chunk of memory on the stack called an align section, which is aligned on function entry.

    Discussion

    buildAlignSection() inserts code just after the function prolog is complete. It allocates memory for the align closure by making a local stack variable to contain that memory, allocates a local variable (salignSection) to point to it. In VarExp::toElem and SymOffExp::toElem, when referring to a variable that is in an align closure, take the offset from salignSection rather than from the frame pointer. A variable cannot be in both a closure and an align section. They go in the closure and then that closure is aligned.

    getEthis() and NewExp::toElem need to use sclosure, if set, rather than the current frame pointer??

    Run after buildClosure, as buildClosure gets first dibs on inAlignSection variables

    Parameters

    FuncDeclaration fd

    function in which all this occurs

    IRState irs

    state of the intermediate code generation

    Reference: buildClosure() is very similar.

    https://github.com/dlang/dmd/pull/9143 was an incomplete attempt to solve this problem that was merged. It should probably be removed.

  • Declaration

    void buildCapture(FuncDeclaration fd);

    build a debug info struct for variables captured by nested functions, but not in a closure. must be called after generating the function to fill stack offsets

    Parameters

    FuncDeclaration fd

    function

  • Declaration

    RET retStyle(TypeFunction tf, bool needsThis);

    Determine return style of function - whether in registers or through a hidden pointer to the caller's stack.

    Parameters

    TypeFunction tf

    function type to check

    bool needsThis

    true if the function type is for a non-static member function

    Return Value

    RET.stack if return value from function is on the stack, RET.regs otherwise