github.com/llir/llvm@v0.3.6/asm/translate.go (about) 1 // Order of translation. 2 // 3 // Note: step 3 and the substeps of 4a can be done concurrently. 4 // Note: the substeps of 4a can be done concurrently. 5 // Note: the substeps of 4b can be done concurrently. 6 // Note: steps 5-7 can be done concurrently. 7 // Note: the substeps of 8 can be done concurrently. 8 // 9 // 1. Index AST top-level entities. 10 // 11 // 2. Resolve IR type definitions. 12 // 13 // a) Index type identifiers and create scaffolding IR type definitions 14 // (without bodies). 15 // 16 // b) Translate AST type definitions to IR. 17 // 18 // 3. Translate AST comdat definitions to IR. 19 // 20 // Note: step 3 and the substeps of 4a can be done concurrently. 21 // 22 // 4. Resolve remaining IR top-level entities. 23 // 24 // a) Index top-level identifiers and create scaffolding IR top-level 25 // declarations and definitions (without bodies but with types). 26 // 27 // Note: the substeps of 4a can be done concurrently. 28 // 29 // 1. Index global identifiers and create scaffolding IR global 30 // declarations and definitions, indirect symbol definitions, and 31 // function declarations and definitions (without bodies but with 32 // types). 33 // 34 // 2. Index attribute group IDs and create scaffolding IR attribute group 35 // definitions (without bodies). 36 // 37 // 3. Index metadata names and create scaffolding IR named metadata 38 // definitions (without bodies). 39 // 40 // 4. Index metadata IDs and create scaffolding IR metadata definitions 41 // (without bodies). 42 // 43 // b) Translate AST top-level declarations and definitions to IR. 44 // 45 // Note: the substeps of 4b can be done concurrently. 46 // 47 // 1. Translate AST global declarations and definitions, indirect symbol 48 // definitions, and function declarations and definitions to IR. 49 // 50 // 2. Translate AST attribute group definitions to IR. 51 // 52 // 3. Translate AST named metadata definitions to IR. 53 // 54 // 4. Translate AST metadata definitions to IR. 55 // 56 // Note: steps 5-7 can be done concurrenty. 57 // 58 // 5. Translate use-list orders. 59 // 60 // 6. Translate basic block specific use-list orders. 61 // 62 // 7. Fix basic block references in blockaddress constants. 63 // 64 // 8. Add IR top-level declarations and definitions to the IR module in order of 65 // occurrence in the input. 66 // 67 // Note: the substeps of 8 can be done concurrently. 68 // 69 // a) Add IR type definitions to the IR module in natural sorting order. 70 // 71 // b) Add IR comdat definitions to the IR module in natural sorting order. 72 // 73 // c) Add IR global variable declarations and definitions, indirect symbol 74 // definitions, and function declarations and definitions to the IR module 75 // in order of occurrence in the input. 76 // 77 // d) Add IR attribute group definitions to the IR module in numeric order. 78 // 79 // e) Add IR named metadata definitions to the IR module. 80 // 81 // f) Add IR metadata definitions to the IR module in numeric order. 82 83 package asm 84 85 import ( 86 "fmt" 87 "sort" 88 "time" 89 90 "github.com/llir/ll/ast" 91 "github.com/llir/llvm/internal/enc" 92 "github.com/llir/llvm/internal/natsort" 93 "github.com/llir/llvm/ir" 94 "github.com/llir/llvm/ir/constant" 95 "github.com/llir/llvm/ir/metadata" 96 "github.com/llir/llvm/ir/types" 97 "github.com/pkg/errors" 98 ) 99 100 // translate translates the given AST module into an equivalent IR module. 101 func translate(old *ast.Module) (*ir.Module, error) { 102 gen := newGenerator() 103 // 1. Index AST top-level entities. 104 indexStart := time.Now() 105 if err := gen.translateTargetDefs(old); err != nil { 106 return nil, errors.WithStack(err) 107 } 108 if err := gen.indexTopLevelEntities(old); err != nil { 109 return nil, errors.WithStack(err) 110 } 111 dbg.Println("index AST top-level entities took:", time.Since(indexStart)) 112 // 2. Resolve IR type definitions. 113 typeStart := time.Now() 114 if err := gen.resolveTypeDefs(); err != nil { 115 return nil, errors.WithStack(err) 116 } 117 dbg.Println("type resolution took:", time.Since(typeStart)) 118 // 3. Translate AST comdat definitions to IR. 119 // 120 // Note: step 3 and the substeps of 4a can be done concurrently. 121 gen.translateComdatDefs() 122 // 4. Resolve remaining IR top-level entities. 123 // 124 // 4a. Index top-level identifiers and create scaffolding IR top-level 125 // declarations and definitions (without bodies but with types). 126 createStart := time.Now() 127 if err := gen.createTopLevelEntities(); err != nil { 128 return nil, errors.WithStack(err) 129 } 130 dbg.Println("create IR top-level entities took:", time.Since(createStart)) 131 // 4b. Translate AST top-level declarations and definitions to IR. 132 // 133 // Note: the substeps of 4b can be done concurrently. 134 translateStart := time.Now() 135 if err := gen.translateTopLevelEntities(); err != nil { 136 return nil, errors.WithStack(err) 137 } 138 dbg.Println("translate AST to IR took:", time.Since(translateStart)) 139 // Note: step 5-7 can be done concurrenty. 140 // 141 // 5. Translate use-list orders. 142 if err := gen.translateUseListOrders(); err != nil { 143 return nil, errors.WithStack(err) 144 } 145 // 6. Translate basic block specific use-list orders. 146 if err := gen.translateUseListOrderBBs(); err != nil { 147 return nil, errors.WithStack(err) 148 } 149 // 7. Fix basic block references in blockaddress constants. 150 for _, c := range gen.todo { 151 if err := fixBlockAddressConst(c); err != nil { 152 return nil, errors.WithStack(err) 153 } 154 } 155 // 8. Add IR top-level declarations and definitions to the IR module in order 156 // of occurrence in the input. 157 // 158 // Note: the substeps of 8 can be done concurrently. 159 addStart := time.Now() 160 gen.addDefsToModule() 161 dbg.Println("add IR definitions to IR module took:", time.Since(addStart)) 162 return gen.m, nil 163 } 164 165 // addDefsToModule adds IR top-level declarations and definitions to the IR 166 // module in order of occurrence in the input. 167 func (gen *generator) addDefsToModule() { 168 // 8. Add IR top-level declarations and definitions to the IR module in order 169 // of occurrence in the input. 170 // 171 // Note: the substeps of 8 can be done concurrently. 172 // 173 // 8a. Add IR type definitions to the IR module in natural sorting order. 174 gen.addTypeDefsToModule() 175 // 8b. Add IR comdat definitions to the IR module in natural sorting order. 176 gen.addComdatDefsToModule() 177 // 8c. Add IR global variable declarations and definitions, indirect symbol 178 // definitions, and function declarations and definitions to the IR 179 // module in order of occurrence in the input. 180 gen.addGlobalEntitiesToModule() 181 // 8d. Add IR attribute group definitions to the IR module in numeric order. 182 gen.addAttrGroupDefsToModule() 183 // 8e. Add IR named metadata definitions to the IR module. 184 gen.addNamedMetadataDefsToModule() 185 // 8f. Add IR metadata definitions to the IR module in numeric order. 186 gen.addMetadataDefsToModule() 187 } 188 189 // addTypeDefsToModule adds IR type definitions to the IR module in natural 190 // sorting order. 191 func (gen *generator) addTypeDefsToModule() { 192 // 8a. Add IR type definitions to the IR module in natural sorting order. 193 typeNames := make([]string, 0, len(gen.old.typeDefs)) 194 for name := range gen.old.typeDefs { 195 typeNames = append(typeNames, name) 196 } 197 natsort.Strings(typeNames) 198 if len(typeNames) > 0 { 199 gen.m.TypeDefs = make([]types.Type, len(typeNames)) 200 for i, name := range typeNames { 201 def, ok := gen.new.typeDefs[name] 202 if !ok { 203 panic(fmt.Errorf("unable to locate type identifier %q", enc.TypeName(name))) 204 } 205 gen.m.TypeDefs[i] = def 206 } 207 } 208 } 209 210 // addComdatDefsToModule adds IR comdat definitions to the IR module in natural 211 // sorting order. 212 func (gen *generator) addComdatDefsToModule() { 213 // 8b. Add IR comdat definitions to the IR module in natural sorting order. 214 comdatNames := make([]string, 0, len(gen.old.comdatDefs)) 215 for name := range gen.old.comdatDefs { 216 comdatNames = append(comdatNames, name) 217 } 218 natsort.Strings(comdatNames) 219 if len(comdatNames) > 0 { 220 gen.m.ComdatDefs = make([]*ir.ComdatDef, len(comdatNames)) 221 for i, name := range comdatNames { 222 def, ok := gen.new.comdatDefs[name] 223 if !ok { 224 panic(fmt.Errorf("unable to locate comdat name %q", enc.ComdatName(name))) 225 } 226 gen.m.ComdatDefs[i] = def 227 } 228 } 229 } 230 231 // addGlobalEntitiesToModule adds IR global variable declarations and 232 // definitions, indirect symbol definitions, and function declarations and 233 // definitions to the IR module in order of occurrence in the input. 234 func (gen *generator) addGlobalEntitiesToModule() { 235 // 8c. Add IR global variable declarations and definitions, indirect symbol 236 // definitions, and function declarations and definitions to the IR 237 // module in order of occurrence in the input. 238 for _, ident := range gen.old.globalOrder { 239 v, ok := gen.new.globals[ident] 240 if !ok { 241 panic(fmt.Errorf("unable to locate global identifier %q", ident.Ident())) 242 } 243 switch def := v.(type) { 244 case *ir.Global: 245 gen.m.Globals = append(gen.m.Globals, def) 246 case *ir.Alias: 247 gen.m.Aliases = append(gen.m.Aliases, def) 248 case *ir.IFunc: 249 gen.m.IFuncs = append(gen.m.IFuncs, def) 250 case *ir.Func: 251 gen.m.Funcs = append(gen.m.Funcs, def) 252 default: 253 panic(fmt.Errorf("support for global %T not yet implemented", v)) 254 } 255 } 256 } 257 258 // addAttrGroupDefsToModule adds IR attribute group definitions to the IR module 259 // in numeric order. 260 func (gen *generator) addAttrGroupDefsToModule() { 261 // 8d. Add IR attribute group definitions to the IR module in numeric order. 262 attrGroupIDs := make([]int64, 0, len(gen.old.attrGroupDefs)) 263 for id := range gen.old.attrGroupDefs { 264 attrGroupIDs = append(attrGroupIDs, id) 265 } 266 less := func(i, j int) bool { 267 return attrGroupIDs[i] < attrGroupIDs[j] 268 } 269 sort.Slice(attrGroupIDs, less) 270 if len(attrGroupIDs) > 0 { 271 gen.m.AttrGroupDefs = make([]*ir.AttrGroupDef, len(attrGroupIDs)) 272 for i, id := range attrGroupIDs { 273 def, ok := gen.new.attrGroupDefs[id] 274 if !ok { 275 panic(fmt.Errorf("unable to locate attribute group ID %q", enc.AttrGroupID(id))) 276 } 277 gen.m.AttrGroupDefs[i] = def 278 } 279 } 280 } 281 282 // addNamedMetadataDefsToModule adds IR named metadata definitions to the IR 283 // module. 284 func (gen *generator) addNamedMetadataDefsToModule() { 285 // 8e. Add IR named metadata definitions to the IR module. 286 for name, def := range gen.new.namedMetadataDefs { 287 gen.m.NamedMetadataDefs[name] = def 288 } 289 } 290 291 // addMetadataDefsToModule adds IR metadata definitions to the IR module in 292 // numeric order. 293 func (gen *generator) addMetadataDefsToModule() { 294 metadataIDs := make([]int64, 0, len(gen.old.metadataDefs)) 295 for id := range gen.old.metadataDefs { 296 metadataIDs = append(metadataIDs, id) 297 } 298 less := func(i, j int) bool { 299 return metadataIDs[i] < metadataIDs[j] 300 } 301 sort.Slice(metadataIDs, less) 302 if len(metadataIDs) > 0 { 303 gen.m.MetadataDefs = make([]metadata.Definition, len(metadataIDs)) 304 for i, id := range metadataIDs { 305 def, ok := gen.new.metadataDefs[id] 306 if !ok { 307 panic(fmt.Errorf("unable to locate metadata ID %q", enc.MetadataID(id))) 308 } 309 gen.m.MetadataDefs[i] = def 310 } 311 } 312 } 313 314 // ### [ Helper functions ] #################################################### 315 316 // fixBlockAddressConst fixes the basic block of the given blockaddress 317 // constant. During translation of constants, blockaddress constants are 318 // assigned dummy basic blocks since function bodies have yet to be translated. 319 // 320 // pre-condition: translated function body and assigned local IDs of c.Func. 321 func fixBlockAddressConst(c *constant.BlockAddress) error { 322 f, ok := c.Func.(*ir.Func) 323 if !ok { 324 panic(fmt.Errorf("invalid function type in blockaddress constant; expected *ir.Func, got %T", c.Func)) 325 } 326 bb, ok := c.Block.(*ir.Block) 327 if !ok { 328 panic(fmt.Errorf("invalid basic block type in blockaddress constant; expected *ir.Block, got %T", c.Block)) 329 } 330 block, err := findBlock(f, bb.LocalIdent) 331 if err != nil { 332 return errors.WithStack(err) 333 } 334 c.Block = block 335 return nil 336 }