github.com/llir/llvm@v0.3.6/asm/inst_binary.go (about)

     1  package asm
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/llir/ll/ast"
     7  	"github.com/llir/llvm/ir"
     8  	"github.com/pkg/errors"
     9  )
    10  
    11  // === [ Create IR ] ===========================================================
    12  
    13  // newAddInst returns a new IR add instruction (without body but with type)
    14  // based on the given AST add instruction.
    15  func (fgen *funcGen) newAddInst(ident ir.LocalIdent, old *ast.AddInst) (*ir.InstAdd, error) {
    16  	typ, err := fgen.gen.irType(old.X().Typ())
    17  	if err != nil {
    18  		return nil, errors.WithStack(err)
    19  	}
    20  	return &ir.InstAdd{LocalIdent: ident, Typ: typ}, nil
    21  }
    22  
    23  // newFAddInst returns a new IR fadd instruction (without body but with type)
    24  // based on the given AST fadd instruction.
    25  func (fgen *funcGen) newFAddInst(ident ir.LocalIdent, old *ast.FAddInst) (*ir.InstFAdd, error) {
    26  	typ, err := fgen.gen.irType(old.X().Typ())
    27  	if err != nil {
    28  		return nil, errors.WithStack(err)
    29  	}
    30  	return &ir.InstFAdd{LocalIdent: ident, Typ: typ}, nil
    31  }
    32  
    33  // newSubInst returns a new IR sub instruction (without body but with type)
    34  // based on the given AST sub instruction.
    35  func (fgen *funcGen) newSubInst(ident ir.LocalIdent, old *ast.SubInst) (*ir.InstSub, error) {
    36  	typ, err := fgen.gen.irType(old.X().Typ())
    37  	if err != nil {
    38  		return nil, errors.WithStack(err)
    39  	}
    40  	return &ir.InstSub{LocalIdent: ident, Typ: typ}, nil
    41  }
    42  
    43  // newFSubInst returns a new IR fsub instruction (without body but with type)
    44  // based on the given AST fsub instruction.
    45  func (fgen *funcGen) newFSubInst(ident ir.LocalIdent, old *ast.FSubInst) (*ir.InstFSub, error) {
    46  	typ, err := fgen.gen.irType(old.X().Typ())
    47  	if err != nil {
    48  		return nil, errors.WithStack(err)
    49  	}
    50  	return &ir.InstFSub{LocalIdent: ident, Typ: typ}, nil
    51  }
    52  
    53  // newMulInst returns a new IR mul instruction (without body but with type)
    54  // based on the given AST mul instruction.
    55  func (fgen *funcGen) newMulInst(ident ir.LocalIdent, old *ast.MulInst) (*ir.InstMul, error) {
    56  	typ, err := fgen.gen.irType(old.X().Typ())
    57  	if err != nil {
    58  		return nil, errors.WithStack(err)
    59  	}
    60  	return &ir.InstMul{LocalIdent: ident, Typ: typ}, nil
    61  }
    62  
    63  // newFMulInst returns a new IR fmul instruction (without body but with type)
    64  // based on the given AST fmul instruction.
    65  func (fgen *funcGen) newFMulInst(ident ir.LocalIdent, old *ast.FMulInst) (*ir.InstFMul, error) {
    66  	typ, err := fgen.gen.irType(old.X().Typ())
    67  	if err != nil {
    68  		return nil, errors.WithStack(err)
    69  	}
    70  	return &ir.InstFMul{LocalIdent: ident, Typ: typ}, nil
    71  }
    72  
    73  // newUDivInst returns a new IR udiv instruction (without body but with type)
    74  // based on the given AST udiv instruction.
    75  func (fgen *funcGen) newUDivInst(ident ir.LocalIdent, old *ast.UDivInst) (*ir.InstUDiv, error) {
    76  	typ, err := fgen.gen.irType(old.X().Typ())
    77  	if err != nil {
    78  		return nil, errors.WithStack(err)
    79  	}
    80  	return &ir.InstUDiv{LocalIdent: ident, Typ: typ}, nil
    81  }
    82  
    83  // newSDivInst returns a new IR sdiv instruction (without body but with type)
    84  // based on the given AST sdiv instruction.
    85  func (fgen *funcGen) newSDivInst(ident ir.LocalIdent, old *ast.SDivInst) (*ir.InstSDiv, error) {
    86  	typ, err := fgen.gen.irType(old.X().Typ())
    87  	if err != nil {
    88  		return nil, errors.WithStack(err)
    89  	}
    90  	return &ir.InstSDiv{LocalIdent: ident, Typ: typ}, nil
    91  }
    92  
    93  // newFDivInst returns a new IR fdiv instruction (without body but with type)
    94  // based on the given AST fdiv instruction.
    95  func (fgen *funcGen) newFDivInst(ident ir.LocalIdent, old *ast.FDivInst) (*ir.InstFDiv, error) {
    96  	typ, err := fgen.gen.irType(old.X().Typ())
    97  	if err != nil {
    98  		return nil, errors.WithStack(err)
    99  	}
   100  	return &ir.InstFDiv{LocalIdent: ident, Typ: typ}, nil
   101  }
   102  
   103  // newURemInst returns a new IR urem instruction (without body but with type)
   104  // based on the given AST urem instruction.
   105  func (fgen *funcGen) newURemInst(ident ir.LocalIdent, old *ast.URemInst) (*ir.InstURem, error) {
   106  	typ, err := fgen.gen.irType(old.X().Typ())
   107  	if err != nil {
   108  		return nil, errors.WithStack(err)
   109  	}
   110  	return &ir.InstURem{LocalIdent: ident, Typ: typ}, nil
   111  }
   112  
   113  // newSRemInst returns a new IR srem instruction (without body but with type)
   114  // based on the given AST srem instruction.
   115  func (fgen *funcGen) newSRemInst(ident ir.LocalIdent, old *ast.SRemInst) (*ir.InstSRem, error) {
   116  	typ, err := fgen.gen.irType(old.X().Typ())
   117  	if err != nil {
   118  		return nil, errors.WithStack(err)
   119  	}
   120  	return &ir.InstSRem{LocalIdent: ident, Typ: typ}, nil
   121  }
   122  
   123  // newFRemInst returns a new IR frem instruction (without body but with type)
   124  // based on the given AST frem instruction.
   125  func (fgen *funcGen) newFRemInst(ident ir.LocalIdent, old *ast.FRemInst) (*ir.InstFRem, error) {
   126  	typ, err := fgen.gen.irType(old.X().Typ())
   127  	if err != nil {
   128  		return nil, errors.WithStack(err)
   129  	}
   130  	return &ir.InstFRem{LocalIdent: ident, Typ: typ}, nil
   131  }
   132  
   133  // === [ Translate AST to IR ] =================================================
   134  
   135  // --- [ add ] -----------------------------------------------------------------
   136  
   137  // irAddInst translates the given AST add instruction into an equivalent IR
   138  // instruction.
   139  func (fgen *funcGen) irAddInst(new ir.Instruction, old *ast.AddInst) error {
   140  	inst, ok := new.(*ir.InstAdd)
   141  	if !ok {
   142  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstAdd, got %T", new))
   143  	}
   144  	// X operand.
   145  	x, err := fgen.irTypeValue(old.X())
   146  	if err != nil {
   147  		return errors.WithStack(err)
   148  	}
   149  	inst.X = x
   150  	// Y operand.
   151  	y, err := fgen.irValue(x.Type(), old.Y())
   152  	if err != nil {
   153  		return errors.WithStack(err)
   154  	}
   155  	inst.Y = y
   156  	// (optional) Overflow flags.
   157  	inst.OverflowFlags = irOverflowFlags(old.OverflowFlags())
   158  	// (optional) Metadata.
   159  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   160  	if err != nil {
   161  		return errors.WithStack(err)
   162  	}
   163  	inst.Metadata = md
   164  	return nil
   165  }
   166  
   167  // --- [ fadd ] ----------------------------------------------------------------
   168  
   169  // irFAddInst translates the given AST fadd instruction into an equivalent IR
   170  // instruction.
   171  func (fgen *funcGen) irFAddInst(new ir.Instruction, old *ast.FAddInst) error {
   172  	inst, ok := new.(*ir.InstFAdd)
   173  	if !ok {
   174  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstFAdd, got %T", new))
   175  	}
   176  	// X operand.
   177  	x, err := fgen.irTypeValue(old.X())
   178  	if err != nil {
   179  		return errors.WithStack(err)
   180  	}
   181  	inst.X = x
   182  	// Y operand.
   183  	y, err := fgen.irValue(x.Type(), old.Y())
   184  	if err != nil {
   185  		return errors.WithStack(err)
   186  	}
   187  	inst.Y = y
   188  	// (optional) Fast math flags.
   189  	inst.FastMathFlags = irFastMathFlags(old.FastMathFlags())
   190  	// (optional) Metadata.
   191  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   192  	if err != nil {
   193  		return errors.WithStack(err)
   194  	}
   195  	inst.Metadata = md
   196  	return nil
   197  }
   198  
   199  // --- [ sub ] -----------------------------------------------------------------
   200  
   201  // irSubInst translates the given AST sub instruction into an equivalent IR
   202  // instruction.
   203  func (fgen *funcGen) irSubInst(new ir.Instruction, old *ast.SubInst) error {
   204  	inst, ok := new.(*ir.InstSub)
   205  	if !ok {
   206  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstSub, got %T", new))
   207  	}
   208  	// X operand.
   209  	x, err := fgen.irTypeValue(old.X())
   210  	if err != nil {
   211  		return errors.WithStack(err)
   212  	}
   213  	inst.X = x
   214  	// Y operand.
   215  	y, err := fgen.irValue(x.Type(), old.Y())
   216  	if err != nil {
   217  		return errors.WithStack(err)
   218  	}
   219  	inst.Y = y
   220  	// (optional) Overflow flags.
   221  	inst.OverflowFlags = irOverflowFlags(old.OverflowFlags())
   222  	// (optional) Metadata.
   223  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   224  	if err != nil {
   225  		return errors.WithStack(err)
   226  	}
   227  	inst.Metadata = md
   228  	return nil
   229  }
   230  
   231  // --- [ fsub ] ----------------------------------------------------------------
   232  
   233  // irFSubInst translates the given AST fsub instruction into an equivalent IR
   234  // instruction.
   235  func (fgen *funcGen) irFSubInst(new ir.Instruction, old *ast.FSubInst) error {
   236  	inst, ok := new.(*ir.InstFSub)
   237  	if !ok {
   238  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstFSub, got %T", new))
   239  	}
   240  	// X operand.
   241  	x, err := fgen.irTypeValue(old.X())
   242  	if err != nil {
   243  		return errors.WithStack(err)
   244  	}
   245  	inst.X = x
   246  	// Y operand.
   247  	y, err := fgen.irValue(x.Type(), old.Y())
   248  	if err != nil {
   249  		return errors.WithStack(err)
   250  	}
   251  	inst.Y = y
   252  	// (optional) Fast math flags.
   253  	inst.FastMathFlags = irFastMathFlags(old.FastMathFlags())
   254  	// (optional) Metadata.
   255  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   256  	if err != nil {
   257  		return errors.WithStack(err)
   258  	}
   259  	inst.Metadata = md
   260  	return nil
   261  }
   262  
   263  // --- [ mul ] -----------------------------------------------------------------
   264  
   265  // irMulInst translates the given AST mul instruction into an equivalent IR
   266  // instruction.
   267  func (fgen *funcGen) irMulInst(new ir.Instruction, old *ast.MulInst) error {
   268  	inst, ok := new.(*ir.InstMul)
   269  	if !ok {
   270  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstMul, got %T", new))
   271  	}
   272  	// X operand.
   273  	x, err := fgen.irTypeValue(old.X())
   274  	if err != nil {
   275  		return errors.WithStack(err)
   276  	}
   277  	inst.X = x
   278  	// Y operand.
   279  	y, err := fgen.irValue(x.Type(), old.Y())
   280  	if err != nil {
   281  		return errors.WithStack(err)
   282  	}
   283  	inst.Y = y
   284  	// (optional) Overflow flags.
   285  	inst.OverflowFlags = irOverflowFlags(old.OverflowFlags())
   286  	// (optional) Metadata.
   287  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   288  	if err != nil {
   289  		return errors.WithStack(err)
   290  	}
   291  	inst.Metadata = md
   292  	return nil
   293  }
   294  
   295  // --- [ fmul ] ----------------------------------------------------------------
   296  
   297  // irFMulInst translates the given AST fmul instruction into an equivalent IR
   298  // instruction.
   299  func (fgen *funcGen) irFMulInst(new ir.Instruction, old *ast.FMulInst) error {
   300  	inst, ok := new.(*ir.InstFMul)
   301  	if !ok {
   302  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstFMul, got %T", new))
   303  	}
   304  	// X operand.
   305  	x, err := fgen.irTypeValue(old.X())
   306  	if err != nil {
   307  		return errors.WithStack(err)
   308  	}
   309  	inst.X = x
   310  	// Y operand.
   311  	y, err := fgen.irValue(x.Type(), old.Y())
   312  	if err != nil {
   313  		return errors.WithStack(err)
   314  	}
   315  	inst.Y = y
   316  	// (optional) Fast math flags.
   317  	inst.FastMathFlags = irFastMathFlags(old.FastMathFlags())
   318  	// (optional) Metadata.
   319  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   320  	if err != nil {
   321  		return errors.WithStack(err)
   322  	}
   323  	inst.Metadata = md
   324  	return nil
   325  }
   326  
   327  // --- [ udiv ] ----------------------------------------------------------------
   328  
   329  // irUDivInst translates the given AST udiv instruction into an equivalent IR
   330  // instruction.
   331  func (fgen *funcGen) irUDivInst(new ir.Instruction, old *ast.UDivInst) error {
   332  	inst, ok := new.(*ir.InstUDiv)
   333  	if !ok {
   334  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstUDiv, got %T", new))
   335  	}
   336  	// X operand.
   337  	x, err := fgen.irTypeValue(old.X())
   338  	if err != nil {
   339  		return errors.WithStack(err)
   340  	}
   341  	inst.X = x
   342  	// Y operand.
   343  	y, err := fgen.irValue(x.Type(), old.Y())
   344  	if err != nil {
   345  		return errors.WithStack(err)
   346  	}
   347  	inst.Y = y
   348  	// (optional) Exact.
   349  	_, inst.Exact = old.Exact()
   350  	// (optional) Metadata.
   351  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   352  	if err != nil {
   353  		return errors.WithStack(err)
   354  	}
   355  	inst.Metadata = md
   356  	return nil
   357  }
   358  
   359  // --- [ sdiv ] ----------------------------------------------------------------
   360  
   361  // irSDivInst translates the given AST sdiv instruction into an equivalent IR
   362  // instruction.
   363  func (fgen *funcGen) irSDivInst(new ir.Instruction, old *ast.SDivInst) error {
   364  	inst, ok := new.(*ir.InstSDiv)
   365  	if !ok {
   366  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstSDiv, got %T", new))
   367  	}
   368  	// X operand.
   369  	x, err := fgen.irTypeValue(old.X())
   370  	if err != nil {
   371  		return errors.WithStack(err)
   372  	}
   373  	inst.X = x
   374  	// Y operand.
   375  	y, err := fgen.irValue(x.Type(), old.Y())
   376  	if err != nil {
   377  		return errors.WithStack(err)
   378  	}
   379  	inst.Y = y
   380  	// (optional) Exact.
   381  	_, inst.Exact = old.Exact()
   382  	// (optional) Metadata.
   383  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   384  	if err != nil {
   385  		return errors.WithStack(err)
   386  	}
   387  	inst.Metadata = md
   388  	return nil
   389  }
   390  
   391  // --- [ fdiv ] ----------------------------------------------------------------
   392  
   393  // irFDivInst translates the given AST fdiv instruction into an equivalent IR
   394  // instruction.
   395  func (fgen *funcGen) irFDivInst(new ir.Instruction, old *ast.FDivInst) error {
   396  	inst, ok := new.(*ir.InstFDiv)
   397  	if !ok {
   398  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstFDiv, got %T", new))
   399  	}
   400  	// X operand.
   401  	x, err := fgen.irTypeValue(old.X())
   402  	if err != nil {
   403  		return errors.WithStack(err)
   404  	}
   405  	inst.X = x
   406  	// Y operand.
   407  	y, err := fgen.irValue(x.Type(), old.Y())
   408  	if err != nil {
   409  		return errors.WithStack(err)
   410  	}
   411  	inst.Y = y
   412  	// (optional) Fast math flags.
   413  	inst.FastMathFlags = irFastMathFlags(old.FastMathFlags())
   414  	// (optional) Metadata.
   415  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   416  	if err != nil {
   417  		return errors.WithStack(err)
   418  	}
   419  	inst.Metadata = md
   420  	return nil
   421  }
   422  
   423  // --- [ urem ] ----------------------------------------------------------------
   424  
   425  // irURemInst translates the given AST urem instruction into an equivalent IR
   426  // instruction.
   427  func (fgen *funcGen) irURemInst(new ir.Instruction, old *ast.URemInst) error {
   428  	inst, ok := new.(*ir.InstURem)
   429  	if !ok {
   430  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstURem, got %T", new))
   431  	}
   432  	// X operand.
   433  	x, err := fgen.irTypeValue(old.X())
   434  	if err != nil {
   435  		return errors.WithStack(err)
   436  	}
   437  	inst.X = x
   438  	// Y operand.
   439  	y, err := fgen.irValue(x.Type(), old.Y())
   440  	if err != nil {
   441  		return errors.WithStack(err)
   442  	}
   443  	inst.Y = y
   444  	// (optional) Metadata.
   445  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   446  	if err != nil {
   447  		return errors.WithStack(err)
   448  	}
   449  	inst.Metadata = md
   450  	return nil
   451  }
   452  
   453  // --- [ srem ] ----------------------------------------------------------------
   454  
   455  // irSRemInst translates the given AST srem instruction into an equivalent IR
   456  // instruction.
   457  func (fgen *funcGen) irSRemInst(new ir.Instruction, old *ast.SRemInst) error {
   458  	inst, ok := new.(*ir.InstSRem)
   459  	if !ok {
   460  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstSRem, got %T", new))
   461  	}
   462  	// X operand.
   463  	x, err := fgen.irTypeValue(old.X())
   464  	if err != nil {
   465  		return errors.WithStack(err)
   466  	}
   467  	inst.X = x
   468  	// Y operand.
   469  	y, err := fgen.irValue(x.Type(), old.Y())
   470  	if err != nil {
   471  		return errors.WithStack(err)
   472  	}
   473  	inst.Y = y
   474  	// (optional) Metadata.
   475  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   476  	if err != nil {
   477  		return errors.WithStack(err)
   478  	}
   479  	inst.Metadata = md
   480  	return nil
   481  }
   482  
   483  // --- [ frem ] ----------------------------------------------------------------
   484  
   485  // irFRemInst translates the given AST frem instruction into an equivalent IR
   486  // instruction.
   487  func (fgen *funcGen) irFRemInst(new ir.Instruction, old *ast.FRemInst) error {
   488  	inst, ok := new.(*ir.InstFRem)
   489  	if !ok {
   490  		panic(fmt.Errorf("invalid IR instruction for AST instruction; expected *ir.InstFRem, got %T", new))
   491  	}
   492  	// X operand.
   493  	x, err := fgen.irTypeValue(old.X())
   494  	if err != nil {
   495  		return errors.WithStack(err)
   496  	}
   497  	inst.X = x
   498  	// Y operand.
   499  	y, err := fgen.irValue(x.Type(), old.Y())
   500  	if err != nil {
   501  		return errors.WithStack(err)
   502  	}
   503  	inst.Y = y
   504  	// (optional) Fast math flags.
   505  	inst.FastMathFlags = irFastMathFlags(old.FastMathFlags())
   506  	// (optional) Metadata.
   507  	md, err := fgen.gen.irMetadataAttachments(old.Metadata())
   508  	if err != nil {
   509  		return errors.WithStack(err)
   510  	}
   511  	inst.Metadata = md
   512  	return nil
   513  }