github.com/llir/llvm@v0.3.6/ir/block.go (about)

     1  // The basic block API of the ir package was heavily inspired by
     2  // https://github.com/mrbenshef/goory.
     3  
     4  package ir
     5  
     6  import (
     7  	"fmt"
     8  	"strings"
     9  
    10  	"github.com/llir/llvm/internal/enc"
    11  	"github.com/llir/llvm/ir/types"
    12  )
    13  
    14  // === [ Basic blocks ] ========================================================
    15  
    16  // Block is an LLVM IR basic block; a sequence of non-branching instructions
    17  // terminated by a control flow instruction (e.g. br or ret).
    18  type Block struct {
    19  	// Name of local variable associated with the basic block.
    20  	LocalIdent
    21  	// Instructions of the basic block.
    22  	Insts []Instruction
    23  	// Terminator of the basic block.
    24  	Term Terminator
    25  
    26  	// extra.
    27  
    28  	// Parent function; field set by ir.Func.NewBlock.
    29  	Parent *Func `json:"-"`
    30  }
    31  
    32  // NewBlock returns a new basic block based on the given label name. An empty
    33  // label name indicates an unnamed basic block.
    34  func NewBlock(name string) *Block {
    35  	block := &Block{}
    36  	block.SetName(name)
    37  	return block
    38  }
    39  
    40  // String returns the LLVM syntax representation of the basic block as a
    41  // type-value pair.
    42  func (block *Block) String() string {
    43  	return fmt.Sprintf("%s %s", block.Type(), block.Ident())
    44  }
    45  
    46  // Type returns the type of the basic block.
    47  func (block *Block) Type() types.Type {
    48  	return types.Label
    49  }
    50  
    51  // LLString returns the LLVM syntax representation of the basic block
    52  // definition.
    53  //
    54  // Name=LabelIdentopt Insts=Instruction* Term=Terminator
    55  func (block *Block) LLString() string {
    56  	buf := &strings.Builder{}
    57  	if block.IsUnnamed() {
    58  		//fmt.Fprintf(buf, "; <label>:%d\n", block.LocalID)
    59  		// Explicitly print basic block label to conform with Clang 9.0, and
    60  		// because it's the sane thing to do.
    61  		fmt.Fprintf(buf, "%s\n", enc.LabelID(block.LocalID))
    62  	} else {
    63  		fmt.Fprintf(buf, "%s\n", enc.LabelName(block.LocalName))
    64  	}
    65  	for _, inst := range block.Insts {
    66  		fmt.Fprintf(buf, "\t%s\n", inst.LLString())
    67  	}
    68  	if block.Term == nil {
    69  		panic(fmt.Sprintf("missing terminator in basic block %q.\ncurrent instructions:\n%s", block.Name(), buf.String()))
    70  	}
    71  	fmt.Fprintf(buf, "\t%s", block.Term.LLString())
    72  	return buf.String()
    73  }