github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/ssa/xposmap.go (about)

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssa
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"github.com/go-asm/go/cmd/src"
    11  )
    12  
    13  type lineRange struct {
    14  	first, last uint32
    15  }
    16  
    17  // An xposmap is a map from fileindex and line of src.XPos to int32,
    18  // implemented sparsely to save space (column and statement status are ignored).
    19  // The sparse skeleton is constructed once, and then reused by ssa phases
    20  // that (re)move values with statements attached.
    21  type xposmap struct {
    22  	// A map from file index to maps from line range to integers (block numbers)
    23  	maps map[int32]*biasedSparseMap
    24  	// The next two fields provide a single-item cache for common case of repeated lines from same file.
    25  	lastIndex int32            // -1 means no entry in cache
    26  	lastMap   *biasedSparseMap // map found at maps[lastIndex]
    27  }
    28  
    29  // newXposmap constructs an xposmap valid for inputs which have a file index in the keys of x,
    30  // and line numbers in the range x[file index].
    31  // The resulting xposmap will panic if a caller attempts to set or add an XPos not in that range.
    32  func newXposmap(x map[int]lineRange) *xposmap {
    33  	maps := make(map[int32]*biasedSparseMap)
    34  	for i, p := range x {
    35  		maps[int32(i)] = newBiasedSparseMap(int(p.first), int(p.last))
    36  	}
    37  	return &xposmap{maps: maps, lastIndex: -1} // zero for the rest is okay
    38  }
    39  
    40  // clear removes data from the map but leaves the sparse skeleton.
    41  func (m *xposmap) clear() {
    42  	for _, l := range m.maps {
    43  		if l != nil {
    44  			l.clear()
    45  		}
    46  	}
    47  	m.lastIndex = -1
    48  	m.lastMap = nil
    49  }
    50  
    51  // mapFor returns the line range map for a given file index.
    52  func (m *xposmap) mapFor(index int32) *biasedSparseMap {
    53  	if index == m.lastIndex {
    54  		return m.lastMap
    55  	}
    56  	mf := m.maps[index]
    57  	m.lastIndex = index
    58  	m.lastMap = mf
    59  	return mf
    60  }
    61  
    62  // set inserts p->v into the map.
    63  // If p does not fall within the set of fileindex->lineRange used to construct m, this will panic.
    64  func (m *xposmap) set(p src.XPos, v int32) {
    65  	s := m.mapFor(p.FileIndex())
    66  	if s == nil {
    67  		panic(fmt.Sprintf("xposmap.set(%d), file index not found in map\n", p.FileIndex()))
    68  	}
    69  	s.set(p.Line(), v)
    70  }
    71  
    72  // get returns the int32 associated with the file index and line of p.
    73  func (m *xposmap) get(p src.XPos) int32 {
    74  	s := m.mapFor(p.FileIndex())
    75  	if s == nil {
    76  		return -1
    77  	}
    78  	return s.get(p.Line())
    79  }
    80  
    81  // add adds p to m, treating m as a set instead of as a map.
    82  // If p does not fall within the set of fileindex->lineRange used to construct m, this will panic.
    83  // Use clear() in between set/map interpretations of m.
    84  func (m *xposmap) add(p src.XPos) {
    85  	m.set(p, 0)
    86  }
    87  
    88  // contains returns whether the file index and line of p are in m,
    89  // treating m as a set instead of as a map.
    90  func (m *xposmap) contains(p src.XPos) bool {
    91  	s := m.mapFor(p.FileIndex())
    92  	if s == nil {
    93  		return false
    94  	}
    95  	return s.contains(p.Line())
    96  }
    97  
    98  // remove removes the file index and line for p from m,
    99  // whether m is currently treated as a map or set.
   100  func (m *xposmap) remove(p src.XPos) {
   101  	s := m.mapFor(p.FileIndex())
   102  	if s == nil {
   103  		return
   104  	}
   105  	s.remove(p.Line())
   106  }
   107  
   108  // foreachEntry applies f to each (fileindex, line, value) triple in m.
   109  func (m *xposmap) foreachEntry(f func(j int32, l uint, v int32)) {
   110  	for j, mm := range m.maps {
   111  		s := mm.size()
   112  		for i := 0; i < s; i++ {
   113  			l, v := mm.getEntry(i)
   114  			f(j, l, v)
   115  		}
   116  	}
   117  }