/
metadata.go
178 lines (164 loc) · 5.3 KB
/
metadata.go
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
package asm
import (
"fmt"
"github.com/llir/ll/ast"
"github.com/llir/llvm/internal/enc"
"github.com/llir/llvm/ir/metadata"
"github.com/pkg/errors"
)
// irMetadataAttachments returns the IR metadata attachments corresponding to
// the given AST metadata attachments.
func (gen *generator) irMetadataAttachments(olds []ast.MetadataAttachment) ([]*metadata.Attachment, error) {
if len(olds) == 0 {
return nil, nil
}
mds := make([]*metadata.Attachment, len(olds))
for i, old := range olds {
md, err := gen.irMetadataAttachment(old)
if err != nil {
return nil, errors.WithStack(err)
}
mds[i] = md
}
return mds, nil
}
// irMetadataAttachment returns the IR metadata attachment corresponding to
// the given AST metadata attachment.
func (gen *generator) irMetadataAttachment(old ast.MetadataAttachment) (*metadata.Attachment, error) {
// Name.
name := metadataName(old.Name())
// Node.
node, err := gen.irMDNode(old.MDNode())
if err != nil {
return nil, errors.WithStack(err)
}
md := &metadata.Attachment{
Name: name,
Node: node,
}
return md, nil
}
// irMDNode returns the IR metadata node corresponding to the given AST metadata
// node.
func (gen *generator) irMDNode(old ast.MDNode) (metadata.MDNode, error) {
switch old := old.(type) {
case *ast.MDTuple:
return gen.irMDTuple(nil, old)
case *ast.MetadataID:
return gen.metadataDefFromID(*old)
case ast.SpecializedMDNode:
return gen.irSpecializedMDNode(nil, old)
default:
panic(fmt.Errorf("support for metadata node %T not yet implemented", old))
}
}
// irMDTuple returns the IR metadata tuple corresponding to the given AST
// metadata tuple. A new IR metadata tuple correspoding to the AST metadata
// tuple is created if new is nil, otherwise the body of new is populated.
func (gen *generator) irMDTuple(new metadata.Definition, old *ast.MDTuple) (*metadata.Tuple, error) {
tuple, ok := new.(*metadata.Tuple)
if new == nil {
tuple = &metadata.Tuple{}
tuple.SetID(-1) // tuple literal has no ID.
} else if !ok {
panic(fmt.Errorf("invalid IR metadata tuple for AST metadata tuple; expected *metadata.Tuple, got %T", new))
}
if oldFields := old.MDFields(); len(oldFields) > 0 {
tuple.Fields = make([]metadata.Field, len(oldFields))
for i, oldField := range oldFields {
field, err := gen.irMDField(oldField)
if err != nil {
return nil, errors.WithStack(err)
}
tuple.Fields[i] = field
}
}
return tuple, nil
}
// irMDField returns the IR metadata field corresponding to the given AST
// metadata field.
func (gen *generator) irMDField(old ast.MDField) (metadata.Field, error) {
switch old := old.(type) {
case *ast.NullLit:
return metadata.Null, nil
case ast.Metadata:
return gen.irMetadata(old)
default:
panic(fmt.Errorf("support for metadata field %T not yet implemented", old))
}
}
// irMetadata returns the IR metadata corresponding to the given AST metadata.
func (fgen *funcGen) irMetadata(old ast.Metadata) (metadata.Metadata, error) {
switch old := old.(type) {
case *ast.TypeValue:
return fgen.irTypeValue(*old)
case *ast.DIArgList:
return fgen.irDIArgList(old)
default:
return fgen.gen.irMetadata(old)
}
}
// irMetadata returns the IR metadata corresponding to the given AST metadata.
func (gen *generator) irMetadata(old ast.Metadata) (metadata.Metadata, error) {
switch old := old.(type) {
case *ast.TypeValue:
typ, err := gen.irType(old.Typ())
if err != nil {
return nil, errors.WithStack(err)
}
switch oldVal := old.Val().(type) {
case ast.Constant:
return gen.irConstant(typ, oldVal)
default:
panic(fmt.Errorf("support for metadata value %T not yet implemented", oldVal))
}
case *ast.MDString:
s := stringLit(old.Val())
return &metadata.String{Value: s}, nil
case *ast.MDTuple:
return gen.irMDTuple(nil, old)
case *ast.MetadataID:
return gen.metadataDefFromID(*old)
case ast.SpecializedMDNode:
return gen.irSpecializedMDNode(nil, old)
default:
panic(fmt.Errorf("support for metadata %T not yet implemented", old))
}
}
// irMetadataNode returns the IR metadata node corresponding to the given AST
// metadata node.
func (gen *generator) irMetadataNode(old ast.MetadataNode) (metadata.Node, error) {
switch old := old.(type) {
case *ast.MetadataID:
return gen.metadataDefFromID(*old)
case *ast.DIExpression:
return gen.irDIExpression(nil, old)
default:
panic(fmt.Errorf("support for metadata node %T not yet implemented", old))
}
}
// --- [ DIArgList ] ---------------------------------------------------------
// irDIArgList returns the IR DIArgList metadata node corresponding to the given
// AST DIArgList metadata node.
func (fgen *funcGen) irDIArgList(old *ast.DIArgList) (*metadata.DIArgList, error) {
md := &metadata.DIArgList{}
for _, oldField := range old.Fields() {
field, err := fgen.irTypeValue(oldField)
if err != nil {
return nil, errors.WithStack(err)
}
md.Fields = append(md.Fields, field)
}
return md, nil
}
// ### [ Helper functions ] ####################################################
// metadataDefFromID returns the IR metadata definition associated with the
// given AST metadata ID.
func (gen *generator) metadataDefFromID(old ast.MetadataID) (metadata.Definition, error) {
id := metadataID(old)
node, ok := gen.new.metadataDefs[id]
if !ok {
return nil, errors.Errorf("unable to locate metadata ID %q", enc.MetadataID(id))
}
return node, nil
}