github.com/llir/llvm@v0.3.6/asm/module.go (about) 1 package asm 2 3 import ( 4 "fmt" 5 6 "github.com/llir/ll/ast" 7 asmenum "github.com/llir/llvm/asm/enum" 8 "github.com/llir/llvm/internal/enc" 9 "github.com/llir/llvm/ir" 10 "github.com/llir/llvm/ir/metadata" 11 "github.com/pkg/errors" 12 ) 13 14 // === [ Index AST ] =========================================================== 15 16 // indexTopLevelEntities indexes the AST top-level entities of the given module. 17 func (gen *generator) indexTopLevelEntities(old *ast.Module) error { 18 id := int64(0) 19 // 1. Index AST top-level entities. 20 for _, entity := range old.TopLevelEntities() { 21 switch entity := entity.(type) { 22 case *ast.ModuleAsm: 23 asm := unquote(entity.Asm().Text()) 24 gen.m.ModuleAsms = append(gen.m.ModuleAsms, asm) 25 case *ast.TypeDef: 26 ident := localIdent(entity.Name()) 27 name := getTypeName(ident) 28 if prev, ok := gen.old.typeDefs[name]; ok { 29 if _, ok := prev.Typ().(*ast.OpaqueType); !ok { 30 return errors.Errorf("type identifier %q already present; prev `%s`, new `%s`", enc.TypeName(name), text(prev), text(entity)) 31 } 32 } 33 gen.old.typeDefs[name] = entity 34 case *ast.ComdatDef: 35 name := comdatName(entity.Name()) 36 if prev, ok := gen.old.comdatDefs[name]; ok { 37 return errors.Errorf("comdat name %q already present; prev `%s`, new `%s`", enc.ComdatName(name), text(prev), text(entity)) 38 } 39 gen.old.comdatDefs[name] = entity 40 case *ast.GlobalDecl: 41 ident := giveUnnamedIdentID(globalIdent(entity.Name()), &id) 42 if prev, ok := gen.old.globals[ident]; ok { 43 return errors.Errorf("global identifier %q already present; prev `%s`, new `%s`", ident.Ident(), text(prev), text(entity)) 44 } 45 gen.old.globals[ident] = entity 46 gen.old.globalOrder = append(gen.old.globalOrder, ident) 47 case *ast.IndirectSymbolDef: 48 ident := giveUnnamedIdentID(globalIdent(entity.Name()), &id) 49 if prev, ok := gen.old.globals[ident]; ok { 50 return errors.Errorf("global identifier %q already present; prev `%s`, new `%s`", ident.Ident(), text(prev), text(entity)) 51 } 52 gen.old.globals[ident] = entity 53 gen.old.globalOrder = append(gen.old.globalOrder, ident) 54 case *ast.FuncDecl: 55 ident := giveUnnamedIdentID(globalIdent(entity.Header().Name()), &id) 56 if prev, ok := gen.old.globals[ident]; ok { 57 return errors.Errorf("global identifier %q already present; prev `%s`, new `%s`", ident.Ident(), text(prev), text(entity)) 58 } 59 gen.old.globals[ident] = entity 60 gen.old.globalOrder = append(gen.old.globalOrder, ident) 61 case *ast.FuncDef: 62 ident := giveUnnamedIdentID(globalIdent(entity.Header().Name()), &id) 63 if prev, ok := gen.old.globals[ident]; ok { 64 return errors.Errorf("global identifier %q already present; prev `%s`, new `%s`", ident.Ident(), text(prev), text(entity)) 65 } 66 gen.old.globals[ident] = entity 67 gen.old.globalOrder = append(gen.old.globalOrder, ident) 68 case *ast.AttrGroupDef: 69 id := attrGroupID(entity.ID()) 70 // Append attribute group definition, and merge at later stage if ID 71 // maps to more than one attribute group definition. 72 gen.old.attrGroupDefs[id] = append(gen.old.attrGroupDefs[id], entity) 73 case *ast.NamedMetadataDef: 74 name := metadataName(entity.Name()) 75 // Multiple named metadata definitions of the same name are allowed. 76 // They are merged into a single named metadata definition with the 77 // nodes of each definition appended. 78 gen.old.namedMetadataDefs[name] = append(gen.old.namedMetadataDefs[name], entity) 79 case *ast.MetadataDef: 80 id := metadataID(entity.ID()) 81 if prev, ok := gen.old.metadataDefs[id]; ok { 82 return errors.Errorf("metadata ID %q already present; prev `%s`, new `%s`", enc.MetadataID(id), text(prev), text(entity)) 83 } 84 gen.old.metadataDefs[id] = entity 85 case *ast.UseListOrder: 86 gen.old.useListOrders = append(gen.old.useListOrders, entity) 87 case *ast.UseListOrderBB: 88 gen.old.useListOrderBBs = append(gen.old.useListOrderBBs, entity) 89 default: 90 panic(fmt.Errorf("support for AST top-level entity %T not yet implemented", entity)) 91 } 92 } 93 return nil 94 } 95 96 // giveUnnamedIdentID assigns an unused ID to the global identifier if unnamed. 97 func giveUnnamedIdentID(ident ir.GlobalIdent, id *int64) ir.GlobalIdent { 98 if ident.IsUnnamed() { 99 // Assign next unused ID to unnamed global identifier. 100 ident.SetID(*id) 101 *id++ 102 } 103 return ident 104 } 105 106 // === [ Create and index IR ] ================================================= 107 108 // createTopLevelEntities indexes IR top-level identifiers and creates 109 // scaffolding IR top-level declarations and definitions (without bodies but 110 // with types) of the given module. 111 func (gen *generator) createTopLevelEntities() error { 112 // 4a. Index top-level identifiers and create scaffolding IR top-level 113 // declarations and definitions (without bodies but with types). 114 // 115 // Note: the substeps of 4a can be done concurrently. 116 // 117 // 4a1. Index global identifiers and create scaffolding IR global 118 // declarations and definitions, indirect symbol definitions (aliases 119 // and indirect functions), and function declarations and definitions 120 // (without bodies but with types). 121 if err := gen.createGlobalEntities(); err != nil { 122 return errors.WithStack(err) 123 } 124 // 4a2. Index attribute group IDs and create scaffolding IR attribute group 125 // definitions (without bodies). 126 gen.createAttrGroupDefs() 127 // 4a3. Index metadata names and create scaffolding IR named metadata 128 // definitions (without bodies). 129 gen.createNamedMetadataDefs() 130 // 4a4. Index metadata IDs and create scaffolding IR metadata definitions 131 // (without bodies). 132 gen.createMetadataDefs() 133 return nil 134 } 135 136 // --- [ Attribute group definitions ] ----------------------------------------- 137 138 // createAttrGroupDefs indexes IR attribute group IDs and creates scaffolding IR 139 // attribute group definitions (without bodies) of the given module. 140 // 141 // post-condition: gen.new.attrGroupDefs maps from attribute group ID (without 142 // '#' prefix) to corresponding skeleton IR value. 143 func (gen *generator) createAttrGroupDefs() { 144 // 4a2. Index attribute group IDs and create scaffolding IR attribute group 145 // definitions (without bodies). 146 for id := range gen.old.attrGroupDefs { 147 new := &ir.AttrGroupDef{ID: id} 148 gen.new.attrGroupDefs[id] = new 149 } 150 } 151 152 // --- [ Named metadata definitions ] ------------------------------------------ 153 154 // createNamedMetadataDefs indexes IR metadata names and creates scaffolding IR 155 // named metadata definitions (without bodies) of the given module. 156 // 157 // post-condition: gen.new.namedMetadataDefs maps from metadata name (without 158 // '!' prefix) to corresponding skeleton IR value. 159 func (gen *generator) createNamedMetadataDefs() { 160 // 4a3. Index metadata names and create scaffolding IR named metadata 161 // definitions (without bodies). 162 for name := range gen.old.namedMetadataDefs { 163 new := &metadata.NamedDef{Name: name} 164 gen.new.namedMetadataDefs[name] = new 165 } 166 } 167 168 // --- [ Metadata definitions ] ------------------------------------------------ 169 170 // createMetadataDefs indexes IR metadata IDs and creates scaffolding IR 171 // metadata definitions (without bodies) of the given module. 172 // 173 // post-condition: gen.new.metadataDefs maps from metadata ID (without '!' 174 // prefix) to corresponding skeleton IR value. 175 func (gen *generator) createMetadataDefs() { 176 // 4a4. Index metadata IDs and create scaffolding IR metadata definitions 177 // (without bodies). 178 for id, md := range gen.old.metadataDefs { 179 new := newMetadataDef(id, md) 180 gen.new.metadataDefs[id] = new 181 } 182 } 183 184 // newMetadataDef returns a new IR metadata definition (without body) based on 185 // the given AST metadata definition. 186 func newMetadataDef(id int64, old *ast.MetadataDef) metadata.Definition { 187 switch oldNode := old.MDNode().(type) { 188 case *ast.MDTuple: 189 new := &metadata.Tuple{} 190 new.SetID(id) 191 return new 192 case ast.SpecializedMDNode: 193 new := newSpecializedMDNode(oldNode) 194 new.SetID(id) 195 return new 196 default: 197 panic(fmt.Errorf("support for metadata node %T not yet implemented", oldNode)) 198 } 199 } 200 201 // newSpecializedMDNode returns a new IR specialized metadata node (without 202 // body) based on the given AST specialized metadata node. 203 func newSpecializedMDNode(old ast.SpecializedMDNode) metadata.SpecializedNode { 204 switch old := old.(type) { 205 case *ast.DIBasicType: 206 return &metadata.DIBasicType{} 207 case *ast.DICommonBlock: 208 return &metadata.DICommonBlock{} 209 case *ast.DICompileUnit: 210 return &metadata.DICompileUnit{} 211 case *ast.DICompositeType: 212 return &metadata.DICompositeType{} 213 case *ast.DIDerivedType: 214 return &metadata.DIDerivedType{} 215 case *ast.DIEnumerator: 216 return &metadata.DIEnumerator{} 217 case *ast.DIExpression: 218 return &metadata.DIExpression{} 219 case *ast.DIFile: 220 return &metadata.DIFile{} 221 case *ast.DIGlobalVariable: 222 return &metadata.DIGlobalVariable{} 223 case *ast.DIGlobalVariableExpression: 224 return &metadata.DIGlobalVariableExpression{} 225 case *ast.DIImportedEntity: 226 return &metadata.DIImportedEntity{} 227 case *ast.DILabel: 228 return &metadata.DILabel{} 229 case *ast.DILexicalBlock: 230 return &metadata.DILexicalBlock{} 231 case *ast.DILexicalBlockFile: 232 return &metadata.DILexicalBlockFile{} 233 case *ast.DILocalVariable: 234 return &metadata.DILocalVariable{} 235 case *ast.DILocation: 236 return &metadata.DILocation{} 237 case *ast.DIMacro: 238 return &metadata.DIMacro{} 239 case *ast.DIMacroFile: 240 return &metadata.DIMacroFile{} 241 case *ast.DIModule: 242 return &metadata.DIModule{} 243 case *ast.DINamespace: 244 return &metadata.DINamespace{} 245 case *ast.DIObjCProperty: 246 return &metadata.DIObjCProperty{} 247 case *ast.DIStringType: 248 return &metadata.DIStringType{} 249 case *ast.DISubprogram: 250 return &metadata.DISubprogram{} 251 case *ast.DISubrange: 252 return &metadata.DISubrange{} 253 case *ast.DISubroutineType: 254 return &metadata.DISubroutineType{} 255 case *ast.DITemplateTypeParameter: 256 return &metadata.DITemplateTypeParameter{} 257 case *ast.DITemplateValueParameter: 258 return &metadata.DITemplateValueParameter{} 259 case *ast.GenericDINode: 260 return &metadata.GenericDINode{} 261 default: 262 panic(fmt.Errorf("support for %T not yet implemented", old)) 263 } 264 } 265 266 // === [ Translate AST to IR ] ================================================= 267 268 // --- [ Target definitions ] -------------------------------------------------- 269 270 // translateTargetDefs translates the AST target definitions of the given module 271 // to IR. 272 func (gen *generator) translateTargetDefs(old *ast.Module) error { 273 for _, targetDef := range old.TargetDefs() { 274 switch targetDef := targetDef.(type) { 275 case *ast.SourceFilename: 276 gen.m.SourceFilename = unquote(targetDef.Name().Text()) 277 case *ast.TargetDataLayout: 278 gen.m.DataLayout = unquote(targetDef.DataLayout().Text()) 279 case *ast.TargetTriple: 280 gen.m.TargetTriple = unquote(targetDef.TargetTriple().Text()) 281 } 282 } 283 return nil 284 } 285 286 // --- [ Top-level-entities ] -------------------------------------------------- 287 288 // translateTopLevelEntities translates the AST top-level declarations and 289 // definitions of the given module to IR. 290 func (gen *generator) translateTopLevelEntities() error { 291 // TODO: make concurrent and benchmark difference in walltime. 292 293 // 4b. Translate AST top-level declarations and definitions to IR. 294 // 295 // Note: the substeps of 4b can be done concurrently. 296 // 297 // 4b1. Translate AST global declarations and definitions, alias and IFunc 298 // definitions, and function declarations and definitions to IR. 299 if err := gen.translateGlobalEntities(); err != nil { 300 return errors.WithStack(err) 301 } 302 // 4b2. Translate AST attribute group definitions to IR. 303 gen.translateAttrGroupDefs() 304 // 4b3. Translate AST named metadata definitions to IR. 305 if err := gen.translateNamedMetadataDefs(); err != nil { 306 return errors.WithStack(err) 307 } 308 // 4b4. Translate AST metadata definitions to IR. 309 return gen.translateMetadataDefs() 310 } 311 312 // --- [ Comdat definitions ] -------------------------------------------------- 313 314 // translateComdatDefs translates the AST comdat definitions of the given module 315 // to IR. 316 func (gen *generator) translateComdatDefs() { 317 // 3. Translate AST comdat definitions to IR. 318 // 319 // Note: step 3 and the substeps of 4a can be done concurrently. 320 for name, old := range gen.old.comdatDefs { 321 new := &ir.ComdatDef{ 322 Name: name, 323 Kind: asmenum.SelectionKindFromString(old.Kind().Text()), 324 } 325 gen.new.comdatDefs[name] = new 326 } 327 } 328 329 // --- [ Attribute group definitions ] ----------------------------------------- 330 331 // translateAttrGroupDefs translates the AST attribute group definitions of the 332 // given module to IR. 333 func (gen *generator) translateAttrGroupDefs() { 334 // 4b2. Translate AST attribute group definitions to IR. 335 for id, old := range gen.old.attrGroupDefs { 336 new, ok := gen.new.attrGroupDefs[id] 337 if !ok { 338 panic(fmt.Errorf("unable to locate attribute group ID %q", enc.AttrGroupID(id))) 339 } 340 gen.irAttrGroupDef(new, old) 341 } 342 } 343 344 // irAttrGroupDef translates the AST attribute group definitions (one or more) 345 // to an equivalent IR attribute group definition. Mulriple definitions of the 346 // same ID are merged into a single attribute group definition. 347 func (gen *generator) irAttrGroupDef(new *ir.AttrGroupDef, oldDefs []*ast.AttrGroupDef) { 348 // present is used to prevent duplicate attributes when merging multiple 349 // attribute group definitions. 350 present := make(map[string]bool) 351 for _, oldDef := range oldDefs { 352 for _, oldFuncAttr := range oldDef.FuncAttrs() { 353 lit := oldFuncAttr.LlvmNode().Text() 354 if present[lit] { 355 // skip duplicate attribute. 356 continue 357 } 358 funcAttr := gen.irFuncAttribute(oldFuncAttr) 359 new.FuncAttrs = append(new.FuncAttrs, funcAttr) 360 present[lit] = true 361 } 362 } 363 } 364 365 // --- [ Named metadata definitions ] ------------------------------------------ 366 367 // translateNamedMetadataDefs translates the AST named metadata definitions of 368 // the given module to IR. 369 func (gen *generator) translateNamedMetadataDefs() error { 370 // 4b3. Translate AST named metadata definitions to IR. 371 for name, old := range gen.old.namedMetadataDefs { 372 new, ok := gen.new.namedMetadataDefs[name] 373 if !ok { 374 panic(fmt.Errorf("unable to locate metadata name %q", enc.MetadataName(name))) 375 } 376 for _, oldDef := range old { 377 if err := gen.irNamedMetadataDef(new, oldDef); err != nil { 378 return errors.WithStack(err) 379 } 380 } 381 } 382 return nil 383 } 384 385 // irNamedMetadataDef translates the given AST named metadata definition to an 386 // equivalent IR named metadata definition. 387 func (gen *generator) irNamedMetadataDef(new *metadata.NamedDef, old *ast.NamedMetadataDef) error { 388 // Nodes. 389 for _, oldNode := range old.MDNodes() { 390 node, err := gen.irMetadataNode(oldNode) 391 if err != nil { 392 return errors.WithStack(err) 393 } 394 new.Nodes = append(new.Nodes, node) 395 } 396 return nil 397 } 398 399 // --- [ Metadata definitions ] ------------------------------------------------ 400 401 // translateMetadataDefs translates the AST metadata definitions of the given 402 // module to IR. 403 func (gen *generator) translateMetadataDefs() error { 404 // 4b4. Translate AST metadata definitions to IR. 405 for id, old := range gen.old.metadataDefs { 406 new, ok := gen.new.metadataDefs[id] 407 if !ok { 408 panic(fmt.Errorf("unable to locate metadata ID %q", enc.MetadataID(id))) 409 } 410 if err := gen.irMetadataDef(new, old); err != nil { 411 return errors.WithStack(err) 412 } 413 } 414 return nil 415 } 416 417 // irMetadataDef translates the given AST metadata definition to an equivalent 418 // IR metadata definition. 419 func (gen *generator) irMetadataDef(new metadata.Definition, old *ast.MetadataDef) error { 420 // (optional) Distinct. 421 if _, ok := old.Distinct(); ok { 422 new.SetDistinct(true) 423 } 424 switch oldNode := old.MDNode().(type) { 425 case *ast.MDTuple: 426 _, err := gen.irMDTuple(new, oldNode) 427 if err != nil { 428 return errors.WithStack(err) 429 } 430 case ast.SpecializedMDNode: 431 _, err := gen.irSpecializedMDNode(new, oldNode) 432 if err != nil { 433 return errors.WithStack(err) 434 } 435 default: 436 panic(fmt.Errorf("support for metadata node %T not yet implemented", old)) 437 } 438 return nil 439 } 440 441 // --- [ Use-list orders ] ----------------------------------------------------- 442 443 // translateUseListOrders translates the AST use-list orders of the given 444 // module to IR. 445 func (gen *generator) translateUseListOrders() error { 446 // 5. Translate use-list orders. 447 if len(gen.old.useListOrders) > 0 { 448 gen.m.UseListOrders = make([]*ir.UseListOrder, len(gen.old.useListOrders)) 449 for i, oldUseListOrder := range gen.old.useListOrders { 450 useListOrder, err := gen.irUseListOrder(oldUseListOrder) 451 if err != nil { 452 return errors.WithStack(err) 453 } 454 gen.m.UseListOrders[i] = useListOrder 455 } 456 } 457 return nil 458 } 459 460 // irUseListOrder returns the IR use-list order corresponding to the given AST 461 // use-list order. 462 func (gen *generator) irUseListOrder(old *ast.UseListOrder) (*ir.UseListOrder, error) { 463 // Value. 464 oldVal := old.Val() 465 typ, err := gen.irType(oldVal.Typ()) 466 if err != nil { 467 return nil, errors.WithStack(err) 468 } 469 oldConst, ok := oldVal.Val().(ast.Constant) 470 if !ok { 471 panic(fmt.Errorf("support for use-list order value %T not yet implemented", oldVal.Val())) 472 } 473 c, err := gen.irConstant(typ, oldConst) 474 if err != nil { 475 return nil, errors.WithStack(err) 476 } 477 // Indices. 478 indices := uintSlice(old.Indices()) 479 useListOrder := &ir.UseListOrder{ 480 Value: c, 481 Indices: indices, 482 } 483 return useListOrder, nil 484 } 485 486 // --- [ Basic block specific use-list orders ] -------------------------------- 487 488 // translateUseListOrderBBs translates the AST basic block specific use-list 489 // orders of the given module to IR. 490 func (gen *generator) translateUseListOrderBBs() error { 491 // 6. Translate basic block specific use-list orders. 492 if len(gen.old.useListOrderBBs) > 0 { 493 gen.m.UseListOrderBBs = make([]*ir.UseListOrderBB, len(gen.old.useListOrderBBs)) 494 for i, oldUseListOrderBB := range gen.old.useListOrderBBs { 495 useListOrderBB, err := gen.irUseListOrderBB(oldUseListOrderBB) 496 if err != nil { 497 return errors.WithStack(err) 498 } 499 gen.m.UseListOrderBBs[i] = useListOrderBB 500 } 501 } 502 return nil 503 } 504 505 // irUseListOrderBB translates the given AST basic block specific use-list order 506 // to an equivalent IR basic block specific use-list order. 507 func (gen *generator) irUseListOrderBB(old *ast.UseListOrderBB) (*ir.UseListOrderBB, error) { 508 // Function. 509 funcIdent := globalIdent(old.Func()) 510 v, ok := gen.new.globals[funcIdent] 511 if !ok { 512 return nil, errors.Errorf("unable to locate global identifier %q", funcIdent.Ident()) 513 } 514 f, ok := v.(*ir.Func) 515 if !ok { 516 return nil, errors.Errorf("invalid function type of %q; expected *ir.Func, got %T", funcIdent.Ident(), v) 517 } 518 // Basic block. 519 blockIdent := localIdent(old.Block()) 520 block, err := findBlock(f, blockIdent) 521 if err != nil { 522 return nil, errors.WithStack(err) 523 } 524 // Indices. 525 indices := uintSlice(old.Indices()) 526 useListOrderBB := &ir.UseListOrderBB{ 527 Func: f, 528 Block: block, 529 Indices: indices, 530 } 531 return useListOrderBB, nil 532 }