summaryrefslogtreecommitdiff
path: root/vendor/github.com/mmcloughlin/avo/attr/attr.go
blob: 016e0a4c37f2daae70f419ab8144adcc388135ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Package attr provides attributes for text and data sections.
package attr

import (
	"fmt"
	"math/bits"
	"strings"
)

// Attribute represents TEXT or DATA flags.
type Attribute uint16

// Reference: https://github.com/golang/go/blob/aafe257390cc9048e8b5df898fabd79a9e0d4c39/src/runtime/textflag.h#L11-L37
//
//	// Don't profile the marked routine. This flag is deprecated.
//	#define NOPROF	1
//	// It is ok for the linker to get multiple of these symbols. It will
//	// pick one of the duplicates to use.
//	#define DUPOK	2
//	// Don't insert stack check preamble.
//	#define NOSPLIT	4
//	// Put this data in a read-only section.
//	#define RODATA	8
//	// This data contains no pointers.
//	#define NOPTR	16
//	// This is a wrapper function and should not count as disabling 'recover'.
//	#define WRAPPER 32
//	// This function uses its incoming context register.
//	#define NEEDCTXT 64
//	// Allocate a word of thread local storage and store the offset from the
//	// thread local base to the thread local storage in this variable.
//	#define TLSBSS	256
//	// Do not insert instructions to allocate a stack frame for this function.
//	// Only valid on functions that declare a frame size of 0.
//	// TODO(mwhudson): only implemented for ppc64x at present.
//	#define NOFRAME 512
//	// Function can call reflect.Type.Method or reflect.Type.MethodByName.
//	#define REFLECTMETHOD 1024
//	// Function is the top of the call stack. Call stack unwinders should stop
//	// at this function.
//	#define TOPFRAME 2048
//
const (
	NOPROF Attribute = 1 << iota
	DUPOK
	NOSPLIT
	RODATA
	NOPTR
	WRAPPER
	NEEDCTXT
	_
	TLSBSS
	NOFRAME
	REFLECTMETHOD
	TOPFRAME
)

// Asm returns a representation of the attributes in assembly syntax. This may use macros from "textflags.h"; see ContainsTextFlags() to determine if this header is required.
func (a Attribute) Asm() string {
	parts, rest := a.split()
	if len(parts) == 0 || rest != 0 {
		parts = append(parts, fmt.Sprintf("%d", rest))
	}
	return strings.Join(parts, "|")
}

// ContainsTextFlags returns whether the Asm() representation requires macros in "textflags.h".
func (a Attribute) ContainsTextFlags() bool {
	flags, _ := a.split()
	return len(flags) > 0
}

// split splits a into known flags and any remaining bits.
func (a Attribute) split() ([]string, Attribute) {
	var flags []string
	var rest Attribute
	for a != 0 {
		i := uint(bits.TrailingZeros16(uint16(a)))
		bit := Attribute(1) << i
		if flag := attrname[bit]; flag != "" {
			flags = append(flags, flag)
		} else {
			rest |= bit
		}
		a ^= bit
	}
	return flags, rest
}

var attrname = map[Attribute]string{
	NOPROF:        "NOPROF",
	DUPOK:         "DUPOK",
	NOSPLIT:       "NOSPLIT",
	RODATA:        "RODATA",
	NOPTR:         "NOPTR",
	WRAPPER:       "WRAPPER",
	NEEDCTXT:      "NEEDCTXT",
	TLSBSS:        "TLSBSS",
	NOFRAME:       "NOFRAME",
	REFLECTMETHOD: "REFLECTMETHOD",
	TOPFRAME:      "TOPFRAME",
}