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  }