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

     1  package asm
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/llir/ll/ast"
     7  	"github.com/llir/llvm/internal/enc"
     8  	"github.com/llir/llvm/ir"
     9  	"github.com/llir/llvm/ir/constant"
    10  	"github.com/llir/llvm/ir/types"
    11  	"github.com/pkg/errors"
    12  )
    13  
    14  // === [ Translate AST to IR ] =================================================
    15  
    16  // irConstant translates the AST constant into an equivalent IR constant.
    17  func (gen *generator) irConstant(t types.Type, old ast.Constant) (constant.Constant, error) {
    18  	switch old := old.(type) {
    19  	case *ast.BoolConst:
    20  		return gen.irBoolConst(t, old)
    21  	case *ast.IntConst:
    22  		return gen.irIntConst(t, old)
    23  	case *ast.FloatConst:
    24  		return gen.irFloatConst(t, old)
    25  	case *ast.NullConst:
    26  		return gen.irNullConst(t, old)
    27  	case *ast.NoneConst:
    28  		return gen.irNoneConst(t, old)
    29  	case *ast.StructConst:
    30  		return gen.irStructConst(t, old)
    31  	case *ast.ArrayConst:
    32  		return gen.irArrayConst(t, old)
    33  	case *ast.CharArrayConst:
    34  		return gen.irCharArrayConst(t, old)
    35  	case *ast.VectorConst:
    36  		return gen.irVectorConst(t, old)
    37  	case *ast.ZeroInitializerConst:
    38  		return constant.NewZeroInitializer(t), nil
    39  	case *ast.UndefConst:
    40  		return constant.NewUndef(t), nil
    41  	case *ast.PoisonConst:
    42  		return constant.NewPoison(t), nil
    43  	case *ast.BlockAddressConst:
    44  		return gen.irBlockAddressConst(t, old)
    45  	case *ast.DSOLocalEquivalentConst:
    46  		return gen.irDSOLocalEquivalentConst(t, old)
    47  	case *ast.NoCFIConst:
    48  		return gen.irNoCFIConst(t, old)
    49  	case *ast.GlobalIdent:
    50  		ident := globalIdent(*old)
    51  		c, ok := gen.new.globals[ident]
    52  		if !ok {
    53  			return nil, errors.Errorf("unable to locate global identifier %q", ident.Ident())
    54  		}
    55  		return c, nil
    56  	case ast.ConstantExpr:
    57  		return gen.irConstantExpr(t, old)
    58  	default:
    59  		panic(fmt.Errorf("support for AST constant %T not yet implemented", old))
    60  	}
    61  }
    62  
    63  // irTypeConst translates the AST type-constant pair into an equivalent IR
    64  // constant.
    65  func (gen *generator) irTypeConst(old ast.TypeConst) (constant.Constant, error) {
    66  	// Type.
    67  	typ, err := gen.irType(old.Typ())
    68  	if err != nil {
    69  		return nil, errors.WithStack(err)
    70  	}
    71  	// Constant.
    72  	return gen.irConstant(typ, old.Val())
    73  }
    74  
    75  // --- [ Boolean constants ] ---------------------------------------------------
    76  
    77  // irBoolConst translates the AST boolean constant into an equivalent IR integer
    78  // constant.
    79  func (gen *generator) irBoolConst(t types.Type, old *ast.BoolConst) (*constant.Int, error) {
    80  	typ, ok := t.(*types.IntType)
    81  	if !ok {
    82  		return nil, errors.Errorf("invalid type of boolean constant; expected *types.IntType, got %T", t)
    83  	}
    84  	if !typ.Equal(types.I1) {
    85  		return nil, errors.Errorf("boolean type mismatch; expected %q, got %q", types.I1, typ)
    86  	}
    87  	return constant.NewBool(boolLit(old.BoolLit())), nil
    88  }
    89  
    90  // --- [ Integer constants ] ---------------------------------------------------
    91  
    92  // irIntConst translates the AST integer constant into an equivalent IR integer
    93  // constant.
    94  func (gen *generator) irIntConst(t types.Type, old *ast.IntConst) (*constant.Int, error) {
    95  	typ, ok := t.(*types.IntType)
    96  	if !ok {
    97  		line, col := old.LineColumn()
    98  		return nil, errors.Errorf("%d:%d: invalid type of integer constant; expected *types.IntType, got %T", line, col, t)
    99  	}
   100  	s := old.IntLit().Text()
   101  	return constant.NewIntFromString(typ, s)
   102  }
   103  
   104  // --- [ Floating-point constants ] --------------------------------------------
   105  
   106  // irFloatConst translates the AST floating-point constant into an equivalent IR
   107  // floating-point constant.
   108  func (gen *generator) irFloatConst(t types.Type, old *ast.FloatConst) (*constant.Float, error) {
   109  	typ, ok := t.(*types.FloatType)
   110  	if !ok {
   111  		return nil, errors.Errorf("invalid type of floating-point constant; expected *types.FloatType, got %T", t)
   112  	}
   113  	s := old.FloatLit().Text()
   114  	return constant.NewFloatFromString(typ, s)
   115  }
   116  
   117  // --- [ Null pointer constants ] ----------------------------------------------
   118  
   119  // irNullConst translates the AST null pointer constant into an equivalent IR
   120  // null pointer constant.
   121  func (gen *generator) irNullConst(t types.Type, old *ast.NullConst) (*constant.Null, error) {
   122  	typ, ok := t.(*types.PointerType)
   123  	if !ok {
   124  		return nil, errors.Errorf("invalid type of null pointer constant; expected *types.PointerType, got %T", t)
   125  	}
   126  	return constant.NewNull(typ), nil
   127  }
   128  
   129  // --- [ Token constants ] -----------------------------------------------------
   130  
   131  // irNoneConst translates the AST none token constant into an equivalent IR none
   132  // token constant.
   133  func (gen *generator) irNoneConst(t types.Type, old *ast.NoneConst) (constant.Constant, error) {
   134  	if !t.Equal(types.Token) {
   135  		return nil, errors.Errorf("invalid type of none token constant; expected %q, got %q", types.Token, t)
   136  	}
   137  	return constant.None, nil
   138  }
   139  
   140  // --- [ Struct constants ] ----------------------------------------------------
   141  
   142  // irStructConst translates the AST struct constant into an equivalent IR struct
   143  // constant.
   144  func (gen *generator) irStructConst(t types.Type, old *ast.StructConst) (*constant.Struct, error) {
   145  	typ, ok := t.(*types.StructType)
   146  	if !ok {
   147  		return nil, errors.Errorf("invalid type of struct constant; expected *types.StructType, got %T", t)
   148  	}
   149  	var fields []constant.Constant
   150  	if oldFields := old.Fields(); len(oldFields) > 0 {
   151  		fields = make([]constant.Constant, len(oldFields))
   152  		for i, oldField := range oldFields {
   153  			field, err := gen.irTypeConst(oldField)
   154  			if err != nil {
   155  				return nil, errors.WithStack(err)
   156  			}
   157  			fields[i] = field
   158  		}
   159  	}
   160  	c := constant.NewStruct(typ, fields...)
   161  	return c, nil
   162  }
   163  
   164  // --- [ Array constants ] -----------------------------------------------------
   165  
   166  // irArrayConst translates the AST array constant into an equivalent IR array
   167  // constant.
   168  func (gen *generator) irArrayConst(t types.Type, old *ast.ArrayConst) (*constant.Array, error) {
   169  	typ, ok := t.(*types.ArrayType)
   170  	if !ok {
   171  		return nil, errors.Errorf("invalid type of array constant; expected *types.ArrayType, got %T", t)
   172  	}
   173  	oldElems := old.Elems()
   174  	if len(oldElems) == 0 {
   175  		typ := types.NewArray(0, typ.ElemType)
   176  		if !t.Equal(typ) {
   177  			return nil, errors.Errorf("array type mismatch; expected %q, got %q", typ, t)
   178  		}
   179  		return &constant.Array{Typ: typ}, nil
   180  	}
   181  	elems := make([]constant.Constant, len(oldElems))
   182  	for i, oldElem := range oldElems {
   183  		elem, err := gen.irTypeConst(oldElem)
   184  		if err != nil {
   185  			return nil, errors.WithStack(err)
   186  		}
   187  		elems[i] = elem
   188  	}
   189  	c := constant.NewArray(typ, elems...)
   190  	return c, nil
   191  }
   192  
   193  // irCharArrayConst translates the AST character array constant into an
   194  // equivalent IR character array constant.
   195  func (gen *generator) irCharArrayConst(t types.Type, old *ast.CharArrayConst) (*constant.CharArray, error) {
   196  	data := enc.Unquote(old.Val().Text())
   197  	c := constant.NewCharArray(data)
   198  	if !t.Equal(c.Typ) {
   199  		return nil, errors.Errorf("character array type mismatch; expected %q, got %q (unquoted_data=`%s`, orig_data=`%s`)", c.Typ, t, data, old.Val().Text())
   200  	}
   201  	return c, nil
   202  }
   203  
   204  // --- [ Vector constants ] ----------------------------------------------------
   205  
   206  // irVectorConst translates the AST vector constant into an equivalent IR vector
   207  // constant.
   208  func (gen *generator) irVectorConst(t types.Type, old *ast.VectorConst) (*constant.Vector, error) {
   209  	typ, ok := t.(*types.VectorType)
   210  	if !ok {
   211  		return nil, errors.Errorf("invalid type of vector constant; expected *types.VectorType, got %T", t)
   212  	}
   213  	oldElems := old.Elems()
   214  	if len(oldElems) == 0 {
   215  		return nil, errors.New("zero element vector is illegal")
   216  	}
   217  	elems := make([]constant.Constant, len(oldElems))
   218  	for i, oldElem := range oldElems {
   219  		elem, err := gen.irTypeConst(oldElem)
   220  		if err != nil {
   221  			return nil, errors.WithStack(err)
   222  		}
   223  		elems[i] = elem
   224  	}
   225  	c := constant.NewVector(typ, elems...)
   226  	return c, nil
   227  }
   228  
   229  // --- [ Addresses of basic blocks ] -------------------------------------------
   230  
   231  // irBlockAddressConst translates the AST blockaddress constant into an
   232  // equivalent IR blockaddress constant.
   233  func (gen *generator) irBlockAddressConst(t types.Type, old *ast.BlockAddressConst) (*constant.BlockAddress, error) {
   234  	// Function.
   235  	funcName := globalIdent(old.Func())
   236  	v, ok := gen.new.globals[funcName]
   237  	if !ok {
   238  		return nil, errors.Errorf("unable to locate global identifier %q", funcName)
   239  	}
   240  	f, ok := v.(*ir.Func)
   241  	if !ok {
   242  		return nil, errors.Errorf("invalid function type; expected *ir.Func, got %T", v)
   243  	}
   244  	// Basic block.
   245  	blockIdent := localIdent(old.Block())
   246  	// Add dummy basic block to track the name recorded by the AST. Resolve the
   247  	// proper basic block after translation of function bodies and assignment of
   248  	// local IDs.
   249  	block := &ir.Block{
   250  		LocalIdent: blockIdent,
   251  	}
   252  	c := constant.NewBlockAddress(f, block)
   253  	gen.todo = append(gen.todo, c)
   254  	if typ := c.Type(); !t.Equal(typ) {
   255  		return nil, errors.Errorf("blockaddress constant type mismatch; expected %q, got %q", typ, t)
   256  	}
   257  	return c, nil
   258  }
   259  
   260  // --- [ DSO Local Equivalent ] ------------------------------------------------
   261  
   262  // irDSOLocalEquivalentConst translates the AST dso_local_equivalent constant
   263  // into an equivalent IR dso_local_equivalent constant.
   264  func (gen *generator) irDSOLocalEquivalentConst(t types.Type, old *ast.DSOLocalEquivalentConst) (*constant.DSOLocalEquivalent, error) {
   265  	// Function.
   266  	funcName := globalIdent(old.Func())
   267  	v, ok := gen.new.globals[funcName]
   268  	if !ok {
   269  		return nil, errors.Errorf("unable to locate global identifier %q", funcName)
   270  	}
   271  	var f constant.Constant
   272  	switch v := v.(type) {
   273  	case *ir.Func, *ir.IFunc, *ir.Alias:
   274  		f = v
   275  	default:
   276  		return nil, errors.Errorf("invalid function type; expected *ir.Func or *ir.IFunc, got %T", v)
   277  	}
   278  	c := constant.NewDSOLocalEquivalent(f)
   279  	if typ := c.Type(); !t.Equal(typ) {
   280  		return nil, errors.Errorf("dso_local_equivalent constant type mismatch; expected %q, got %q", typ, t)
   281  	}
   282  	return c, nil
   283  }
   284  
   285  // --- [ No CFI ] --------------------------------------------------------------
   286  
   287  // irNoCFIConst translates the AST no_cfi constant into an equivalent IR no_cfi
   288  // constant.
   289  func (gen *generator) irNoCFIConst(t types.Type, old *ast.NoCFIConst) (*constant.NoCFI, error) {
   290  	// Function.
   291  	funcName := globalIdent(old.Func())
   292  	v, ok := gen.new.globals[funcName]
   293  	if !ok {
   294  		return nil, errors.Errorf("unable to locate global identifier %q", funcName)
   295  	}
   296  	var f constant.Constant
   297  	switch v := v.(type) {
   298  	case *ir.Func, *ir.IFunc, *ir.Alias:
   299  		f = v
   300  	default:
   301  		return nil, errors.Errorf("invalid function type; expected *ir.Func or *ir.IFunc, got %T", v)
   302  	}
   303  	c := constant.NewNoCFI(f)
   304  	if typ := c.Type(); !t.Equal(typ) {
   305  		return nil, errors.Errorf("no_cfi constant type mismatch; expected %q, got %q", typ, t)
   306  	}
   307  	return c, nil
   308  }