github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/interp/memory.go (about)

     1  package interp
     2  
     3  // This file implements memory as used by interp in a reversible way.
     4  // Each new function call creates a new layer which is merged in the parent on
     5  // successful return and is thrown away when the function couldn't complete (in
     6  // which case the function call is done at runtime).
     7  // Memory is not typed, except that there is a difference between pointer and
     8  // non-pointer data. A pointer always points to an object. This implies:
     9  //   * Nil pointers are zero, and are not considered a pointer.
    10  //   * Pointers for memory-mapped I/O point to numeric pointer values, and are
    11  //     thus not considered pointers but regular values. Dereferencing them cannot be
    12  //     done in interp and results in a revert.
    13  //
    14  // Right now the memory is assumed to be little endian. This will need an update
    15  // for big endian architectures, if TinyGo ever adds support for one.
    16  
    17  import (
    18  	"encoding/binary"
    19  	"errors"
    20  	"fmt"
    21  	"math"
    22  	"math/big"
    23  	"strconv"
    24  	"strings"
    25  
    26  	"tinygo.org/x/go-llvm"
    27  )
    28  
    29  // An object is a memory buffer that may be an already existing global or a
    30  // global created with runtime.alloc or the alloca instruction. If llvmGlobal is
    31  // set, that's the global for this object, otherwise it needs to be created (if
    32  // it is still reachable when the package initializer returns). The
    33  // llvmLayoutType is not necessarily a complete type: it may need to be
    34  // repeated (for example, for a slice value).
    35  //
    36  // Objects are copied in a memory view when they are stored to, to provide the
    37  // ability to roll back interpreting a function.
    38  type object struct {
    39  	llvmGlobal     llvm.Value
    40  	llvmType       llvm.Type // must match llvmGlobal.GlobalValueType() if both are set, may be unset if llvmGlobal is set
    41  	llvmLayoutType llvm.Type // LLVM type based on runtime.alloc layout parameter, if available
    42  	globalName     string    // name, if not yet created (not guaranteed to be the final name)
    43  	buffer         value     // buffer with value as given by interp, nil if external
    44  	size           uint32    // must match buffer.len(), if available
    45  	constant       bool      // true if this is a constant global
    46  	marked         uint8     // 0 means unmarked, 1 means external read, 2 means external write
    47  }
    48  
    49  // clone() returns a cloned version of this object, for when an object needs to
    50  // be written to for example.
    51  func (obj object) clone() object {
    52  	if obj.buffer != nil {
    53  		obj.buffer = obj.buffer.clone()
    54  	}
    55  	return obj
    56  }
    57  
    58  // A memoryView is bound to a function activation. Loads are done from this view
    59  // or a parent view (up to the *runner if it isn't included in a view). Stores
    60  // copy the object to the current view.
    61  //
    62  // For details, see the README in the package.
    63  type memoryView struct {
    64  	r       *runner
    65  	parent  *memoryView
    66  	objects map[uint32]object
    67  
    68  	// These instructions were added to runtime.initAll while interpreting a
    69  	// function. They are stored here in a list so they can be removed if the
    70  	// execution of the function needs to be rolled back.
    71  	instructions []llvm.Value
    72  }
    73  
    74  // extend integrates the changes done by the sub-memoryView into this memory
    75  // view. This happens when a function is successfully interpreted and returns to
    76  // the parent, in which case all changed objects should be included in this
    77  // memory view.
    78  func (mv *memoryView) extend(sub memoryView) {
    79  	if mv.objects == nil && len(sub.objects) != 0 {
    80  		mv.objects = make(map[uint32]object)
    81  	}
    82  	for key, value := range sub.objects {
    83  		mv.objects[key] = value
    84  	}
    85  	mv.instructions = append(mv.instructions, sub.instructions...)
    86  }
    87  
    88  // revert undoes changes done in this memory view: it removes all instructions
    89  // created in this memoryView. Do not reuse this memoryView.
    90  func (mv *memoryView) revert() {
    91  	// Erase instructions in reverse order.
    92  	for i := len(mv.instructions) - 1; i >= 0; i-- {
    93  		llvmInst := mv.instructions[i]
    94  		if llvmInst.IsAInstruction().IsNil() {
    95  			// The IR builder will try to create constant versions of
    96  			// instructions whenever possible. If it does this, it's not an
    97  			// instruction and thus shouldn't be removed.
    98  			continue
    99  		}
   100  		llvmInst.EraseFromParentAsInstruction()
   101  	}
   102  }
   103  
   104  // markExternalLoad marks the given LLVM value as having an external read. That
   105  // means that the interpreter can still read from it, but cannot write to it as
   106  // that would mean the external read (done at runtime) reads from a state that
   107  // would not exist had the whole initialization been done at runtime.
   108  func (mv *memoryView) markExternalLoad(llvmValue llvm.Value) error {
   109  	return mv.markExternal(llvmValue, 1)
   110  }
   111  
   112  // markExternalStore marks the given LLVM value as having an external write.
   113  // This means that the interpreter can no longer read from it or write to it, as
   114  // that would happen in a different order than if all initialization were
   115  // happening at runtime.
   116  func (mv *memoryView) markExternalStore(llvmValue llvm.Value) error {
   117  	return mv.markExternal(llvmValue, 2)
   118  }
   119  
   120  // markExternal is a helper for markExternalLoad and markExternalStore, and
   121  // should not be called directly.
   122  func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) error {
   123  	if llvmValue.IsUndef() || llvmValue.IsNull() {
   124  		// Null and undef definitely don't contain (valid) pointers.
   125  		return nil
   126  	}
   127  	if !llvmValue.IsAInstruction().IsNil() || !llvmValue.IsAArgument().IsNil() {
   128  		// These are considered external by default, there is nothing to mark.
   129  		return nil
   130  	}
   131  
   132  	if !llvmValue.IsAGlobalValue().IsNil() {
   133  		objectIndex := mv.r.getValue(llvmValue).(pointerValue).index()
   134  		obj := mv.get(objectIndex)
   135  		if obj.marked < mark {
   136  			obj = obj.clone()
   137  			obj.marked = mark
   138  			if mv.objects == nil {
   139  				mv.objects = make(map[uint32]object)
   140  			}
   141  			mv.objects[objectIndex] = obj
   142  			if !llvmValue.IsAGlobalVariable().IsNil() {
   143  				initializer := llvmValue.Initializer()
   144  				if !initializer.IsNil() {
   145  					// Using mark '2' (which means read/write access) because
   146  					// even from an object that is only read from, the resulting
   147  					// loaded pointer can be written to.
   148  					err := mv.markExternal(initializer, 2)
   149  					if err != nil {
   150  						return err
   151  					}
   152  				}
   153  			} else {
   154  				// This is a function. Go through all instructions and mark all
   155  				// objects in there.
   156  				for bb := llvmValue.FirstBasicBlock(); !bb.IsNil(); bb = llvm.NextBasicBlock(bb) {
   157  					for inst := bb.FirstInstruction(); !inst.IsNil(); inst = llvm.NextInstruction(inst) {
   158  						opcode := inst.InstructionOpcode()
   159  						if opcode == llvm.Call {
   160  							calledValue := inst.CalledValue()
   161  							if !calledValue.IsAFunction().IsNil() {
   162  								functionName := calledValue.Name()
   163  								if functionName == "llvm.dbg.value" || strings.HasPrefix(functionName, "llvm.lifetime.") {
   164  									continue
   165  								}
   166  							}
   167  						}
   168  						if opcode == llvm.Br || opcode == llvm.Switch {
   169  							// These don't affect memory. Skipped here because
   170  							// they also have a label as operand.
   171  							continue
   172  						}
   173  						numOperands := inst.OperandsCount()
   174  						for i := 0; i < numOperands; i++ {
   175  							// Using mark '2' (which means read/write access)
   176  							// because this might be a store instruction.
   177  							err := mv.markExternal(inst.Operand(i), 2)
   178  							if err != nil {
   179  								return err
   180  							}
   181  						}
   182  					}
   183  				}
   184  			}
   185  		}
   186  	} else if !llvmValue.IsAConstantExpr().IsNil() {
   187  		switch llvmValue.Opcode() {
   188  		case llvm.IntToPtr, llvm.PtrToInt, llvm.BitCast, llvm.GetElementPtr:
   189  			err := mv.markExternal(llvmValue.Operand(0), mark)
   190  			if err != nil {
   191  				return err
   192  			}
   193  		case llvm.Add, llvm.Sub, llvm.Mul, llvm.UDiv, llvm.SDiv, llvm.URem, llvm.SRem, llvm.Shl, llvm.LShr, llvm.AShr, llvm.And, llvm.Or, llvm.Xor:
   194  			// Integer binary operators. Mark both operands.
   195  			err := mv.markExternal(llvmValue.Operand(0), mark)
   196  			if err != nil {
   197  				return err
   198  			}
   199  			err = mv.markExternal(llvmValue.Operand(1), mark)
   200  			if err != nil {
   201  				return err
   202  			}
   203  		default:
   204  			return fmt.Errorf("interp: unknown constant expression '%s'", instructionNameMap[llvmValue.Opcode()])
   205  		}
   206  	} else if !llvmValue.IsAInlineAsm().IsNil() {
   207  		// Inline assembly can modify globals but only exported globals. Let's
   208  		// hope the author knows what they're doing.
   209  	} else {
   210  		llvmType := llvmValue.Type()
   211  		switch llvmType.TypeKind() {
   212  		case llvm.IntegerTypeKind, llvm.FloatTypeKind, llvm.DoubleTypeKind:
   213  			// Nothing to do here. Integers and floats aren't pointers so don't
   214  			// need any marking.
   215  		case llvm.StructTypeKind:
   216  			numElements := llvmType.StructElementTypesCount()
   217  			for i := 0; i < numElements; i++ {
   218  				element := mv.r.builder.CreateExtractValue(llvmValue, i, "")
   219  				err := mv.markExternal(element, mark)
   220  				if err != nil {
   221  					return err
   222  				}
   223  			}
   224  		case llvm.ArrayTypeKind:
   225  			numElements := llvmType.ArrayLength()
   226  			for i := 0; i < numElements; i++ {
   227  				element := mv.r.builder.CreateExtractValue(llvmValue, i, "")
   228  				err := mv.markExternal(element, mark)
   229  				if err != nil {
   230  					return err
   231  				}
   232  			}
   233  		default:
   234  			return errors.New("interp: unknown type kind in markExternalValue")
   235  		}
   236  	}
   237  	return nil
   238  }
   239  
   240  // hasExternalLoadOrStore returns true if this object has an external load or
   241  // store. If this has happened, it is not possible for the interpreter to load
   242  // from the object or store to it without affecting the behavior of the program.
   243  func (mv *memoryView) hasExternalLoadOrStore(v pointerValue) bool {
   244  	obj := mv.get(v.index())
   245  	return obj.marked >= 1
   246  }
   247  
   248  // hasExternalStore returns true if this object has an external store. If this
   249  // is true, stores to this object are no longer allowed by the interpreter.
   250  // It returns false if it only has an external load, in which case it is still
   251  // possible for the interpreter to read from the object.
   252  func (mv *memoryView) hasExternalStore(v pointerValue) bool {
   253  	obj := mv.get(v.index())
   254  	return obj.marked >= 2 && !obj.constant
   255  }
   256  
   257  // get returns an object that can only be read from, as it may return an object
   258  // of a parent view.
   259  func (mv *memoryView) get(index uint32) object {
   260  	if obj, ok := mv.objects[index]; ok {
   261  		return obj
   262  	}
   263  	if mv.parent != nil {
   264  		return mv.parent.get(index)
   265  	}
   266  	return mv.r.objects[index]
   267  }
   268  
   269  // getWritable returns an object that can be written to.
   270  func (mv *memoryView) getWritable(index uint32) object {
   271  	if obj, ok := mv.objects[index]; ok {
   272  		// Object is already in the current memory view, so can be modified.
   273  		return obj
   274  	}
   275  	// Object is not currently in this view. Get it, and clone it for use.
   276  	obj := mv.get(index).clone()
   277  	mv.r.objects[index] = obj
   278  	return obj
   279  }
   280  
   281  // Replace the object (indicated with index) with the given object. This put is
   282  // only done at the current memory view, so that if this memory view is reverted
   283  // the object is not changed.
   284  func (mv *memoryView) put(index uint32, obj object) {
   285  	if mv.objects == nil {
   286  		mv.objects = make(map[uint32]object)
   287  	}
   288  	if checks && mv.get(index).buffer == nil {
   289  		panic("writing to external object")
   290  	}
   291  	if checks && mv.get(index).buffer.len(mv.r) != obj.buffer.len(mv.r) {
   292  		panic("put() with a differently-sized object")
   293  	}
   294  	if checks && obj.constant {
   295  		panic("interp: store to a constant")
   296  	}
   297  	mv.objects[index] = obj
   298  }
   299  
   300  // Load the value behind the given pointer. Returns nil if the pointer points to
   301  // an external global.
   302  func (mv *memoryView) load(p pointerValue, size uint32) value {
   303  	if checks && mv.hasExternalStore(p) {
   304  		panic("interp: load from object with external store")
   305  	}
   306  	obj := mv.get(p.index())
   307  	if obj.buffer == nil {
   308  		// External global, return nil.
   309  		return nil
   310  	}
   311  	if p.offset() == 0 && size == obj.size {
   312  		return obj.buffer.clone()
   313  	}
   314  	if checks && p.offset()+size > obj.size {
   315  		panic("interp: load out of bounds")
   316  	}
   317  	v := obj.buffer.asRawValue(mv.r)
   318  	loadedValue := rawValue{
   319  		buf: v.buf[p.offset() : p.offset()+size],
   320  	}
   321  	return loadedValue
   322  }
   323  
   324  // Store to the value behind the given pointer. This overwrites the value in the
   325  // memory view, so that the changed value is discarded when the memory view is
   326  // reverted. Returns true on success, false if the object to store to is
   327  // external.
   328  func (mv *memoryView) store(v value, p pointerValue) bool {
   329  	if checks && mv.hasExternalLoadOrStore(p) {
   330  		panic("interp: store to object with external load/store")
   331  	}
   332  	obj := mv.get(p.index())
   333  	if obj.buffer == nil {
   334  		// External global, return false (for a failure).
   335  		return false
   336  	}
   337  	if checks && p.offset()+v.len(mv.r) > obj.size {
   338  		panic("interp: store out of bounds")
   339  	}
   340  	if p.offset() == 0 && v.len(mv.r) == obj.buffer.len(mv.r) {
   341  		obj.buffer = v
   342  	} else {
   343  		obj = obj.clone()
   344  		buffer := obj.buffer.asRawValue(mv.r)
   345  		obj.buffer = buffer
   346  		v := v.asRawValue(mv.r)
   347  		for i := uint32(0); i < v.len(mv.r); i++ {
   348  			buffer.buf[p.offset()+i] = v.buf[i]
   349  		}
   350  	}
   351  	mv.put(p.index(), obj)
   352  	return true // success
   353  }
   354  
   355  // value is some sort of value, comparable to a LLVM constant. It can be
   356  // implemented in various ways for efficiency, but the fallback value (that all
   357  // implementations can be converted to except for localValue) is rawValue.
   358  type value interface {
   359  	// len returns the length in bytes.
   360  	len(r *runner) uint32
   361  	clone() value
   362  	asPointer(*runner) (pointerValue, error)
   363  	asRawValue(*runner) rawValue
   364  	Uint() uint64
   365  	Int() int64
   366  	toLLVMValue(llvm.Type, *memoryView) (llvm.Value, error)
   367  	String() string
   368  }
   369  
   370  // literalValue contains simple integer values that don't need to be stored in a
   371  // buffer.
   372  type literalValue struct {
   373  	value interface{}
   374  }
   375  
   376  // Make a literalValue given the number of bits.
   377  func makeLiteralInt(value uint64, bits int) literalValue {
   378  	switch bits {
   379  	case 64:
   380  		return literalValue{value}
   381  	case 32:
   382  		return literalValue{uint32(value)}
   383  	case 16:
   384  		return literalValue{uint16(value)}
   385  	case 8:
   386  		return literalValue{uint8(value)}
   387  	default:
   388  		panic("unknown integer size")
   389  	}
   390  }
   391  
   392  func (v literalValue) len(r *runner) uint32 {
   393  	switch v.value.(type) {
   394  	case uint64:
   395  		return 8
   396  	case uint32:
   397  		return 4
   398  	case uint16:
   399  		return 2
   400  	case uint8:
   401  		return 1
   402  	default:
   403  		panic("unknown value type")
   404  	}
   405  }
   406  
   407  func (v literalValue) String() string {
   408  	return strconv.FormatInt(v.Int(), 10)
   409  }
   410  
   411  func (v literalValue) clone() value {
   412  	return v
   413  }
   414  
   415  func (v literalValue) asPointer(r *runner) (pointerValue, error) {
   416  	return pointerValue{}, errIntegerAsPointer
   417  }
   418  
   419  func (v literalValue) asRawValue(r *runner) rawValue {
   420  	var buf []byte
   421  	switch value := v.value.(type) {
   422  	case uint64:
   423  		buf = make([]byte, 8)
   424  		binary.LittleEndian.PutUint64(buf, value)
   425  	case uint32:
   426  		buf = make([]byte, 4)
   427  		binary.LittleEndian.PutUint32(buf, uint32(value))
   428  	case uint16:
   429  		buf = make([]byte, 2)
   430  		binary.LittleEndian.PutUint16(buf, uint16(value))
   431  	case uint8:
   432  		buf = []byte{uint8(value)}
   433  	default:
   434  		panic("unknown value type")
   435  	}
   436  	raw := newRawValue(uint32(len(buf)))
   437  	for i, b := range buf {
   438  		raw.buf[i] = uint64(b)
   439  	}
   440  	return raw
   441  }
   442  
   443  func (v literalValue) Uint() uint64 {
   444  	switch value := v.value.(type) {
   445  	case uint64:
   446  		return value
   447  	case uint32:
   448  		return uint64(value)
   449  	case uint16:
   450  		return uint64(value)
   451  	case uint8:
   452  		return uint64(value)
   453  	default:
   454  		panic("inpterp: unknown literal type")
   455  	}
   456  }
   457  
   458  func (v literalValue) Int() int64 {
   459  	switch value := v.value.(type) {
   460  	case uint64:
   461  		return int64(value)
   462  	case uint32:
   463  		return int64(int32(value))
   464  	case uint16:
   465  		return int64(int16(value))
   466  	case uint8:
   467  		return int64(int8(value))
   468  	default:
   469  		panic("inpterp: unknown literal type")
   470  	}
   471  }
   472  
   473  func (v literalValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Value, error) {
   474  	switch llvmType.TypeKind() {
   475  	case llvm.IntegerTypeKind:
   476  		switch value := v.value.(type) {
   477  		case uint64:
   478  			return llvm.ConstInt(llvmType, value, false), nil
   479  		case uint32:
   480  			return llvm.ConstInt(llvmType, uint64(value), false), nil
   481  		case uint16:
   482  			return llvm.ConstInt(llvmType, uint64(value), false), nil
   483  		case uint8:
   484  			return llvm.ConstInt(llvmType, uint64(value), false), nil
   485  		default:
   486  			return llvm.Value{}, errors.New("interp: unknown literal type")
   487  		}
   488  	case llvm.DoubleTypeKind:
   489  		return llvm.ConstFloat(llvmType, math.Float64frombits(v.value.(uint64))), nil
   490  	case llvm.FloatTypeKind:
   491  		return llvm.ConstFloat(llvmType, float64(math.Float32frombits(v.value.(uint32)))), nil
   492  	default:
   493  		return v.asRawValue(mem.r).toLLVMValue(llvmType, mem)
   494  	}
   495  }
   496  
   497  // pointerValue contains a single pointer, with an offset into the underlying
   498  // object.
   499  type pointerValue struct {
   500  	pointer uint64 // low 32 bits are offset, high 32 bits are index
   501  }
   502  
   503  func newPointerValue(r *runner, index, offset int) pointerValue {
   504  	return pointerValue{
   505  		pointer: uint64(index)<<32 | uint64(offset),
   506  	}
   507  }
   508  
   509  func (v pointerValue) index() uint32 {
   510  	return uint32(v.pointer >> 32)
   511  }
   512  
   513  func (v pointerValue) offset() uint32 {
   514  	return uint32(v.pointer)
   515  }
   516  
   517  // addOffset essentially does a GEP operation (pointer arithmetic): it adds the
   518  // offset to the pointer. It also checks that the offset doesn't overflow the
   519  // maximum offset size (which is 4GB).
   520  func (v pointerValue) addOffset(offset int64) (pointerValue, error) {
   521  	result := pointerValue{v.pointer + uint64(offset)}
   522  	if checks && v.index() != result.index() {
   523  		return result, fmt.Errorf("interp: offset %d out of range for object %v", offset, v)
   524  	}
   525  	return result, nil
   526  }
   527  
   528  func (v pointerValue) len(r *runner) uint32 {
   529  	return r.pointerSize
   530  }
   531  
   532  func (v pointerValue) String() string {
   533  	name := strconv.Itoa(int(v.index()))
   534  	if v.offset() == 0 {
   535  		return "<" + name + ">"
   536  	}
   537  	return "<" + name + "+" + strconv.Itoa(int(v.offset())) + ">"
   538  }
   539  
   540  func (v pointerValue) clone() value {
   541  	return v
   542  }
   543  
   544  func (v pointerValue) asPointer(r *runner) (pointerValue, error) {
   545  	return v, nil
   546  }
   547  
   548  func (v pointerValue) asRawValue(r *runner) rawValue {
   549  	rv := newRawValue(r.pointerSize)
   550  	for i := range rv.buf {
   551  		rv.buf[i] = v.pointer
   552  	}
   553  	return rv
   554  }
   555  
   556  func (v pointerValue) Uint() uint64 {
   557  	panic("cannot convert pointer to integer")
   558  }
   559  
   560  func (v pointerValue) Int() int64 {
   561  	panic("cannot convert pointer to integer")
   562  }
   563  
   564  func (v pointerValue) equal(rhs pointerValue) bool {
   565  	return v.pointer == rhs.pointer
   566  }
   567  
   568  func (v pointerValue) llvmValue(mem *memoryView) llvm.Value {
   569  	return mem.get(v.index()).llvmGlobal
   570  }
   571  
   572  // toLLVMValue returns the LLVM value for this pointer, which may be a GEP or
   573  // bitcast. The llvm.Type parameter is optional, if omitted the pointer type may
   574  // be different than expected.
   575  func (v pointerValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Value, error) {
   576  	// If a particular LLVM type is requested, cast to it.
   577  	if !llvmType.IsNil() && llvmType.TypeKind() != llvm.PointerTypeKind {
   578  		// The LLVM value has (or should have) the same bytes once compiled, but
   579  		// does not have the right LLVM type. This can happen for example when
   580  		// storing to a struct with a single pointer field: this pointer may
   581  		// then become the value even though the pointer should be wrapped in a
   582  		// struct.
   583  		// This can be worked around by simply converting to a raw value,
   584  		// rawValue knows how to create such structs.
   585  		return v.asRawValue(mem.r).toLLVMValue(llvmType, mem)
   586  	}
   587  
   588  	// Obtain the llvmValue, creating it if it doesn't exist yet.
   589  	llvmValue := v.llvmValue(mem)
   590  	if llvmValue.IsNil() {
   591  		// The global does not yet exist. Probably this is the result of a
   592  		// runtime.alloc.
   593  		// First allocate a new global for this object.
   594  		obj := mem.get(v.index())
   595  		if obj.llvmType.IsNil() && obj.llvmLayoutType.IsNil() {
   596  			// Create an initializer without knowing the global type.
   597  			// This is probably the result of a runtime.alloc call.
   598  			initializer, err := obj.buffer.asRawValue(mem.r).rawLLVMValue(mem)
   599  			if err != nil {
   600  				return llvm.Value{}, err
   601  			}
   602  			globalType := initializer.Type()
   603  			llvmValue = llvm.AddGlobal(mem.r.mod, globalType, obj.globalName)
   604  			llvmValue.SetInitializer(initializer)
   605  			llvmValue.SetAlignment(mem.r.maxAlign)
   606  			obj.llvmGlobal = llvmValue
   607  			mem.put(v.index(), obj)
   608  		} else {
   609  			// The global type is known, or at least its structure.
   610  			var globalType llvm.Type
   611  			if !obj.llvmType.IsNil() {
   612  				// The exact type is known.
   613  				globalType = obj.llvmType
   614  			} else { // !obj.llvmLayoutType.IsNil()
   615  				// The exact type isn't known, but the object layout is known.
   616  				globalType = obj.llvmLayoutType
   617  				// The layout may not span the full size of the global because
   618  				// of repetition. One example would be make([]string, 5) which
   619  				// would be 10 words in size but the layout would only be two
   620  				// words (for the string type).
   621  				typeSize := mem.r.targetData.TypeAllocSize(globalType)
   622  				if typeSize != uint64(obj.size) {
   623  					globalType = llvm.ArrayType(globalType, int(uint64(obj.size)/typeSize))
   624  				}
   625  			}
   626  			if checks && mem.r.targetData.TypeAllocSize(globalType) != uint64(obj.size) {
   627  				panic("size of the globalType isn't the same as the object size")
   628  			}
   629  			llvmValue = llvm.AddGlobal(mem.r.mod, globalType, obj.globalName)
   630  			obj.llvmGlobal = llvmValue
   631  			mem.put(v.index(), obj)
   632  
   633  			// Set the initializer for the global. Do this after creation to avoid
   634  			// infinite recursion between creating the global and creating the
   635  			// contents of the global (if the global contains itself).
   636  			initializer, err := obj.buffer.toLLVMValue(globalType, mem)
   637  			if err != nil {
   638  				return llvm.Value{}, err
   639  			}
   640  			if checks && initializer.Type() != globalType {
   641  				return llvm.Value{}, errors.New("interp: allocated value does not match allocated type")
   642  			}
   643  			llvmValue.SetInitializer(initializer)
   644  			if obj.llvmType.IsNil() {
   645  				// The exact type isn't known (only the layout), so use the
   646  				// alignment that would normally be expected from runtime.alloc.
   647  				llvmValue.SetAlignment(mem.r.maxAlign)
   648  			}
   649  		}
   650  
   651  		// It should be included in r.globals because otherwise markExternal
   652  		// would consider it a new global (and would fail to mark this global as
   653  		// having an externa load/store).
   654  		mem.r.globals[llvmValue] = int(v.index())
   655  		llvmValue.SetLinkage(llvm.InternalLinkage)
   656  	}
   657  
   658  	if v.offset() != 0 {
   659  		// If there is an offset, make sure to use a GEP to index into the
   660  		// pointer.
   661  		llvmValue = llvm.ConstInBoundsGEP(mem.r.mod.Context().Int8Type(), llvmValue, []llvm.Value{
   662  			llvm.ConstInt(mem.r.mod.Context().Int32Type(), uint64(v.offset()), false),
   663  		})
   664  	}
   665  
   666  	return llvmValue, nil
   667  }
   668  
   669  // rawValue is a raw memory buffer that can store either pointers or regular
   670  // data. This is the fallback data for everything that isn't clearly a
   671  // literalValue or pointerValue.
   672  type rawValue struct {
   673  	// An integer in buf contains either pointers or bytes.
   674  	// If it is a byte, it is smaller than 256.
   675  	// If it is a pointer, the index is contained in the upper 32 bits and the
   676  	// offset is contained in the lower 32 bits.
   677  	buf []uint64
   678  }
   679  
   680  func newRawValue(size uint32) rawValue {
   681  	return rawValue{make([]uint64, size)}
   682  }
   683  
   684  func (v rawValue) len(r *runner) uint32 {
   685  	return uint32(len(v.buf))
   686  }
   687  
   688  func (v rawValue) String() string {
   689  	if len(v.buf) == 2 || len(v.buf) == 4 || len(v.buf) == 8 {
   690  		// Format as a pointer if the entire buf is this pointer.
   691  		if v.buf[0] > 255 {
   692  			isPointer := true
   693  			for _, p := range v.buf {
   694  				if p != v.buf[0] {
   695  					isPointer = false
   696  					break
   697  				}
   698  			}
   699  			if isPointer {
   700  				return pointerValue{v.buf[0]}.String()
   701  			}
   702  		}
   703  		// Format as number if none of the buf is a pointer.
   704  		if !v.hasPointer() {
   705  			return strconv.FormatInt(v.Int(), 10)
   706  		}
   707  	}
   708  	return "<[…" + strconv.Itoa(len(v.buf)) + "]>"
   709  }
   710  
   711  func (v rawValue) clone() value {
   712  	newValue := v
   713  	newValue.buf = make([]uint64, len(v.buf))
   714  	copy(newValue.buf, v.buf)
   715  	return newValue
   716  }
   717  
   718  func (v rawValue) asPointer(r *runner) (pointerValue, error) {
   719  	if v.buf[0] <= 255 {
   720  		// Probably a null pointer or memory-mapped I/O.
   721  		return pointerValue{}, errIntegerAsPointer
   722  	}
   723  	return pointerValue{v.buf[0]}, nil
   724  }
   725  
   726  func (v rawValue) asRawValue(r *runner) rawValue {
   727  	return v
   728  }
   729  
   730  func (v rawValue) bytes() []byte {
   731  	buf := make([]byte, len(v.buf))
   732  	for i, p := range v.buf {
   733  		if p > 255 {
   734  			panic("cannot convert pointer value to byte")
   735  		}
   736  		buf[i] = byte(p)
   737  	}
   738  	return buf
   739  }
   740  
   741  func (v rawValue) Uint() uint64 {
   742  	buf := v.bytes()
   743  
   744  	switch len(v.buf) {
   745  	case 1:
   746  		return uint64(buf[0])
   747  	case 2:
   748  		return uint64(binary.LittleEndian.Uint16(buf))
   749  	case 4:
   750  		return uint64(binary.LittleEndian.Uint32(buf))
   751  	case 8:
   752  		return binary.LittleEndian.Uint64(buf)
   753  	default:
   754  		panic("unknown integer size")
   755  	}
   756  }
   757  
   758  func (v rawValue) Int() int64 {
   759  	switch len(v.buf) {
   760  	case 1:
   761  		return int64(int8(v.Uint()))
   762  	case 2:
   763  		return int64(int16(v.Uint()))
   764  	case 4:
   765  		return int64(int32(v.Uint()))
   766  	case 8:
   767  		return int64(int64(v.Uint()))
   768  	default:
   769  		panic("unknown integer size")
   770  	}
   771  }
   772  
   773  // equal returns true if (and only if) the value matches rhs.
   774  func (v rawValue) equal(rhs rawValue) bool {
   775  	if len(v.buf) != len(rhs.buf) {
   776  		panic("comparing values of different size")
   777  	}
   778  	for i, p := range v.buf {
   779  		if rhs.buf[i] != p {
   780  			return false
   781  		}
   782  	}
   783  	return true
   784  }
   785  
   786  // rawLLVMValue returns a llvm.Value for this rawValue, making up a type as it
   787  // goes. The resulting value does not have a specified type, but it will be the
   788  // same size and have the same bytes if it was created with a provided LLVM type
   789  // (through toLLVMValue).
   790  func (v rawValue) rawLLVMValue(mem *memoryView) (llvm.Value, error) {
   791  	var structFields []llvm.Value
   792  	ctx := mem.r.mod.Context()
   793  	int8Type := ctx.Int8Type()
   794  
   795  	var bytesBuf []llvm.Value
   796  	// addBytes can be called after adding to bytesBuf to flush remaining bytes
   797  	// to a new array in structFields.
   798  	addBytes := func() {
   799  		if len(bytesBuf) == 0 {
   800  			return
   801  		}
   802  		if len(bytesBuf) == 1 {
   803  			structFields = append(structFields, bytesBuf[0])
   804  		} else {
   805  			structFields = append(structFields, llvm.ConstArray(int8Type, bytesBuf))
   806  		}
   807  		bytesBuf = nil
   808  	}
   809  
   810  	// Create structFields, converting the rawValue to a LLVM value.
   811  	for i := uint32(0); i < uint32(len(v.buf)); {
   812  		if v.buf[i] > 255 {
   813  			addBytes()
   814  			field, err := pointerValue{v.buf[i]}.toLLVMValue(llvm.Type{}, mem)
   815  			if err != nil {
   816  				return llvm.Value{}, err
   817  			}
   818  			if !field.IsAGlobalVariable().IsNil() {
   819  				elementType := field.GlobalValueType()
   820  				if elementType.TypeKind() == llvm.StructTypeKind {
   821  					// There are some special pointer types that should be used
   822  					// as a ptrtoint, so that they can be used in certain
   823  					// optimizations.
   824  					name := elementType.StructName()
   825  					if name == "runtime.funcValueWithSignature" {
   826  						uintptrType := ctx.IntType(int(mem.r.pointerSize) * 8)
   827  						field = llvm.ConstPtrToInt(field, uintptrType)
   828  					}
   829  				}
   830  			}
   831  			structFields = append(structFields, field)
   832  			i += mem.r.pointerSize
   833  			continue
   834  		}
   835  		val := llvm.ConstInt(int8Type, uint64(v.buf[i]), false)
   836  		bytesBuf = append(bytesBuf, val)
   837  		i++
   838  	}
   839  	addBytes()
   840  
   841  	// Return the created data.
   842  	if len(structFields) == 1 {
   843  		return structFields[0], nil
   844  	}
   845  	return ctx.ConstStruct(structFields, false), nil
   846  }
   847  
   848  func (v rawValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Value, error) {
   849  	isZero := true
   850  	for _, p := range v.buf {
   851  		if p != 0 {
   852  			isZero = false
   853  			break
   854  		}
   855  	}
   856  	if isZero {
   857  		return llvm.ConstNull(llvmType), nil
   858  	}
   859  	switch llvmType.TypeKind() {
   860  	case llvm.IntegerTypeKind:
   861  		if v.buf[0] > 255 {
   862  			ptr, err := v.asPointer(mem.r)
   863  			if err != nil {
   864  				panic(err)
   865  			}
   866  			if checks && mem.r.targetData.TypeAllocSize(llvmType) != mem.r.targetData.TypeAllocSize(mem.r.dataPtrType) {
   867  				// Probably trying to serialize a pointer to a byte array,
   868  				// perhaps as a result of rawLLVMValue() in a previous interp
   869  				// run.
   870  				return llvm.Value{}, errInvalidPtrToIntSize
   871  			}
   872  			v, err := ptr.toLLVMValue(llvm.Type{}, mem)
   873  			if err != nil {
   874  				return llvm.Value{}, err
   875  			}
   876  			return llvm.ConstPtrToInt(v, llvmType), nil
   877  		}
   878  		var n uint64
   879  		switch llvmType.IntTypeWidth() {
   880  		case 64:
   881  			n = rawValue{v.buf[:8]}.Uint()
   882  		case 32:
   883  			n = rawValue{v.buf[:4]}.Uint()
   884  		case 16:
   885  			n = rawValue{v.buf[:2]}.Uint()
   886  		case 8:
   887  			n = uint64(v.buf[0])
   888  		case 1:
   889  			n = uint64(v.buf[0])
   890  			if n != 0 && n != 1 {
   891  				panic("bool must be 0 or 1")
   892  			}
   893  		default:
   894  			panic("unknown integer size")
   895  		}
   896  		return llvm.ConstInt(llvmType, n, false), nil
   897  	case llvm.StructTypeKind:
   898  		fieldTypes := llvmType.StructElementTypes()
   899  		fields := make([]llvm.Value, len(fieldTypes))
   900  		for i, fieldType := range fieldTypes {
   901  			offset := mem.r.targetData.ElementOffset(llvmType, i)
   902  			field := rawValue{
   903  				buf: v.buf[offset:],
   904  			}
   905  			var err error
   906  			fields[i], err = field.toLLVMValue(fieldType, mem)
   907  			if err != nil {
   908  				return llvm.Value{}, err
   909  			}
   910  		}
   911  		if llvmType.StructName() != "" {
   912  			return llvm.ConstNamedStruct(llvmType, fields), nil
   913  		}
   914  		return llvmType.Context().ConstStruct(fields, false), nil
   915  	case llvm.ArrayTypeKind:
   916  		numElements := llvmType.ArrayLength()
   917  		childType := llvmType.ElementType()
   918  		childTypeSize := mem.r.targetData.TypeAllocSize(childType)
   919  		fields := make([]llvm.Value, numElements)
   920  		for i := range fields {
   921  			offset := i * int(childTypeSize)
   922  			field := rawValue{
   923  				buf: v.buf[offset:],
   924  			}
   925  			var err error
   926  			fields[i], err = field.toLLVMValue(childType, mem)
   927  			if err != nil {
   928  				return llvm.Value{}, err
   929  			}
   930  			if checks && fields[i].Type() != childType {
   931  				panic("child type doesn't match")
   932  			}
   933  		}
   934  		return llvm.ConstArray(childType, fields), nil
   935  	case llvm.PointerTypeKind:
   936  		if v.buf[0] > 255 {
   937  			// This is a regular pointer.
   938  			llvmValue, err := pointerValue{v.buf[0]}.toLLVMValue(llvm.Type{}, mem)
   939  			if err != nil {
   940  				return llvm.Value{}, err
   941  			}
   942  			if llvmValue.Type() != llvmType {
   943  				if llvmValue.Type().PointerAddressSpace() != llvmType.PointerAddressSpace() {
   944  					// Special case for AVR function pointers.
   945  					// Because go-llvm doesn't have addrspacecast at the moment,
   946  					// do it indirectly with a ptrtoint/inttoptr pair.
   947  					llvmValue = llvm.ConstIntToPtr(llvm.ConstPtrToInt(llvmValue, mem.r.uintptrType), llvmType)
   948  				}
   949  			}
   950  			return llvmValue, nil
   951  		}
   952  		// This is either a null pointer or a raw pointer for memory-mapped I/O
   953  		// (such as 0xe000ed00).
   954  		ptr := rawValue{v.buf[:mem.r.pointerSize]}.Uint()
   955  		if ptr == 0 {
   956  			// Null pointer.
   957  			return llvm.ConstNull(llvmType), nil
   958  		}
   959  		var ptrValue llvm.Value // the underlying int
   960  		switch mem.r.pointerSize {
   961  		case 8:
   962  			ptrValue = llvm.ConstInt(llvmType.Context().Int64Type(), ptr, false)
   963  		case 4:
   964  			ptrValue = llvm.ConstInt(llvmType.Context().Int32Type(), ptr, false)
   965  		case 2:
   966  			ptrValue = llvm.ConstInt(llvmType.Context().Int16Type(), ptr, false)
   967  		default:
   968  			return llvm.Value{}, errors.New("interp: unknown pointer size")
   969  		}
   970  		return llvm.ConstIntToPtr(ptrValue, llvmType), nil
   971  	case llvm.DoubleTypeKind:
   972  		b := rawValue{v.buf[:8]}.Uint()
   973  		f := math.Float64frombits(b)
   974  		return llvm.ConstFloat(llvmType, f), nil
   975  	case llvm.FloatTypeKind:
   976  		b := uint32(rawValue{v.buf[:4]}.Uint())
   977  		f := math.Float32frombits(b)
   978  		return llvm.ConstFloat(llvmType, float64(f)), nil
   979  	default:
   980  		return llvm.Value{}, errors.New("interp: todo: raw value to LLVM value: " + llvmType.String())
   981  	}
   982  }
   983  
   984  func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
   985  	if llvmValue.IsNull() {
   986  		// A zero value is common so check that first.
   987  		return
   988  	}
   989  	if !llvmValue.IsAGlobalValue().IsNil() {
   990  		ptrSize := r.pointerSize
   991  		ptr, err := r.getValue(llvmValue).asPointer(r)
   992  		if err != nil {
   993  			panic(err)
   994  		}
   995  		for i := uint32(0); i < ptrSize; i++ {
   996  			v.buf[i] = ptr.pointer
   997  		}
   998  	} else if !llvmValue.IsAConstantExpr().IsNil() {
   999  		switch llvmValue.Opcode() {
  1000  		case llvm.IntToPtr, llvm.PtrToInt, llvm.BitCast:
  1001  			// All these instructions effectively just reinterprets the bits
  1002  			// (like a bitcast) while no bits change and keeping the same
  1003  			// length, so just read its contents.
  1004  			v.set(llvmValue.Operand(0), r)
  1005  		case llvm.GetElementPtr:
  1006  			ptr := llvmValue.Operand(0)
  1007  			index := llvmValue.Operand(1)
  1008  			numOperands := llvmValue.OperandsCount()
  1009  			elementType := llvmValue.GEPSourceElementType()
  1010  			totalOffset := r.targetData.TypeAllocSize(elementType) * index.ZExtValue()
  1011  			for i := 2; i < numOperands; i++ {
  1012  				indexValue := llvmValue.Operand(i)
  1013  				if checks && indexValue.IsAConstantInt().IsNil() {
  1014  					panic("expected const gep index to be a constant integer")
  1015  				}
  1016  				index := indexValue.ZExtValue()
  1017  				switch elementType.TypeKind() {
  1018  				case llvm.StructTypeKind:
  1019  					// Indexing into a struct field.
  1020  					offsetInBytes := r.targetData.ElementOffset(elementType, int(index))
  1021  					totalOffset += offsetInBytes
  1022  					elementType = elementType.StructElementTypes()[index]
  1023  				default:
  1024  					// Indexing into an array.
  1025  					elementType = elementType.ElementType()
  1026  					elementSize := r.targetData.TypeAllocSize(elementType)
  1027  					totalOffset += index * elementSize
  1028  				}
  1029  			}
  1030  			ptrSize := r.pointerSize
  1031  			ptrValue, err := r.getValue(ptr).asPointer(r)
  1032  			if err != nil {
  1033  				panic(err)
  1034  			}
  1035  			ptrValue.pointer += totalOffset
  1036  			for i := uint32(0); i < ptrSize; i++ {
  1037  				v.buf[i] = ptrValue.pointer
  1038  			}
  1039  		case llvm.ICmp:
  1040  			size := r.targetData.TypeAllocSize(llvmValue.Operand(0).Type())
  1041  			lhs := newRawValue(uint32(size))
  1042  			rhs := newRawValue(uint32(size))
  1043  			lhs.set(llvmValue.Operand(0), r)
  1044  			rhs.set(llvmValue.Operand(1), r)
  1045  			if r.interpretICmp(lhs, rhs, llvmValue.IntPredicate()) {
  1046  				v.buf[0] = 1 // result is true
  1047  			} else {
  1048  				v.buf[0] = 0 // result is false
  1049  			}
  1050  		default:
  1051  			llvmValue.Dump()
  1052  			println()
  1053  			panic("unknown constant expr")
  1054  		}
  1055  	} else if llvmValue.IsUndef() {
  1056  		// Let undef be zero, by lack of an explicit 'undef' marker.
  1057  	} else {
  1058  		if checks && llvmValue.IsAConstant().IsNil() {
  1059  			panic("expected a constant")
  1060  		}
  1061  		llvmType := llvmValue.Type()
  1062  		switch llvmType.TypeKind() {
  1063  		case llvm.IntegerTypeKind:
  1064  			n := llvmValue.ZExtValue()
  1065  			switch llvmValue.Type().IntTypeWidth() {
  1066  			case 64:
  1067  				var buf [8]byte
  1068  				binary.LittleEndian.PutUint64(buf[:], n)
  1069  				for i, b := range buf {
  1070  					v.buf[i] = uint64(b)
  1071  				}
  1072  			case 32:
  1073  				var buf [4]byte
  1074  				binary.LittleEndian.PutUint32(buf[:], uint32(n))
  1075  				for i, b := range buf {
  1076  					v.buf[i] = uint64(b)
  1077  				}
  1078  			case 16:
  1079  				var buf [2]byte
  1080  				binary.LittleEndian.PutUint16(buf[:], uint16(n))
  1081  				for i, b := range buf {
  1082  					v.buf[i] = uint64(b)
  1083  				}
  1084  			case 8, 1:
  1085  				v.buf[0] = n
  1086  			default:
  1087  				panic("unknown integer size")
  1088  			}
  1089  		case llvm.StructTypeKind:
  1090  			numElements := llvmType.StructElementTypesCount()
  1091  			for i := 0; i < numElements; i++ {
  1092  				offset := r.targetData.ElementOffset(llvmType, i)
  1093  				field := rawValue{
  1094  					buf: v.buf[offset:],
  1095  				}
  1096  				field.set(r.builder.CreateExtractValue(llvmValue, i, ""), r)
  1097  			}
  1098  		case llvm.ArrayTypeKind:
  1099  			numElements := llvmType.ArrayLength()
  1100  			childType := llvmType.ElementType()
  1101  			childTypeSize := r.targetData.TypeAllocSize(childType)
  1102  			for i := 0; i < numElements; i++ {
  1103  				offset := i * int(childTypeSize)
  1104  				field := rawValue{
  1105  					buf: v.buf[offset:],
  1106  				}
  1107  				field.set(r.builder.CreateExtractValue(llvmValue, i, ""), r)
  1108  			}
  1109  		case llvm.DoubleTypeKind:
  1110  			f, _ := llvmValue.DoubleValue()
  1111  			var buf [8]byte
  1112  			binary.LittleEndian.PutUint64(buf[:], math.Float64bits(f))
  1113  			for i, b := range buf {
  1114  				v.buf[i] = uint64(b)
  1115  			}
  1116  		case llvm.FloatTypeKind:
  1117  			f, _ := llvmValue.DoubleValue()
  1118  			var buf [4]byte
  1119  			binary.LittleEndian.PutUint32(buf[:], math.Float32bits(float32(f)))
  1120  			for i, b := range buf {
  1121  				v.buf[i] = uint64(b)
  1122  			}
  1123  		default:
  1124  			llvmValue.Dump()
  1125  			println()
  1126  			panic("unknown constant")
  1127  		}
  1128  	}
  1129  }
  1130  
  1131  // hasPointer returns true if this raw value contains a pointer somewhere in the
  1132  // buffer.
  1133  func (v rawValue) hasPointer() bool {
  1134  	for _, p := range v.buf {
  1135  		if p > 255 {
  1136  			return true
  1137  		}
  1138  	}
  1139  	return false
  1140  }
  1141  
  1142  // localValue is a special implementation of the value interface. It is a
  1143  // placeholder for other values in instruction operands, and is replaced with
  1144  // one of the others before executing.
  1145  type localValue struct {
  1146  	value llvm.Value
  1147  }
  1148  
  1149  func (v localValue) len(r *runner) uint32 {
  1150  	panic("interp: localValue.len")
  1151  }
  1152  
  1153  func (v localValue) String() string {
  1154  	return "<!>"
  1155  }
  1156  
  1157  func (v localValue) clone() value {
  1158  	panic("interp: localValue.clone()")
  1159  }
  1160  
  1161  func (v localValue) asPointer(r *runner) (pointerValue, error) {
  1162  	return pointerValue{}, errors.New("interp: localValue.asPointer called")
  1163  }
  1164  
  1165  func (v localValue) asRawValue(r *runner) rawValue {
  1166  	panic("interp: localValue.asRawValue")
  1167  }
  1168  
  1169  func (v localValue) Uint() uint64 {
  1170  	panic("interp: localValue.Uint")
  1171  }
  1172  
  1173  func (v localValue) Int() int64 {
  1174  	panic("interp: localValue.Int")
  1175  }
  1176  
  1177  func (v localValue) toLLVMValue(llvmType llvm.Type, mem *memoryView) (llvm.Value, error) {
  1178  	return v.value, nil
  1179  }
  1180  
  1181  func (r *runner) getValue(llvmValue llvm.Value) value {
  1182  	if checks && llvmValue.IsNil() {
  1183  		panic("nil llvmValue")
  1184  	}
  1185  	if !llvmValue.IsAGlobalValue().IsNil() {
  1186  		index, ok := r.globals[llvmValue]
  1187  		if !ok {
  1188  			obj := object{
  1189  				llvmGlobal: llvmValue,
  1190  			}
  1191  			index = len(r.objects)
  1192  			r.globals[llvmValue] = index
  1193  			r.objects = append(r.objects, obj)
  1194  			if !llvmValue.IsAGlobalVariable().IsNil() {
  1195  				obj.size = uint32(r.targetData.TypeAllocSize(llvmValue.GlobalValueType()))
  1196  				if initializer := llvmValue.Initializer(); !initializer.IsNil() {
  1197  					obj.buffer = r.getValue(initializer)
  1198  					obj.constant = llvmValue.IsGlobalConstant()
  1199  				}
  1200  			} else if !llvmValue.IsAFunction().IsNil() {
  1201  				// OK
  1202  			} else {
  1203  				panic("interp: unknown global value")
  1204  			}
  1205  			// Update the object after it has been created. This avoids an
  1206  			// infinite recursion when using getValue on a global that contains
  1207  			// a reference to itself.
  1208  			r.objects[index] = obj
  1209  		}
  1210  		return newPointerValue(r, index, 0)
  1211  	} else if !llvmValue.IsAConstant().IsNil() {
  1212  		if !llvmValue.IsAConstantInt().IsNil() {
  1213  			n := llvmValue.ZExtValue()
  1214  			switch llvmValue.Type().IntTypeWidth() {
  1215  			case 64:
  1216  				return literalValue{n}
  1217  			case 32:
  1218  				return literalValue{uint32(n)}
  1219  			case 16:
  1220  				return literalValue{uint16(n)}
  1221  			case 8, 1:
  1222  				return literalValue{uint8(n)}
  1223  			default:
  1224  				panic("unknown integer size")
  1225  			}
  1226  		}
  1227  		size := r.targetData.TypeAllocSize(llvmValue.Type())
  1228  		v := newRawValue(uint32(size))
  1229  		v.set(llvmValue, r)
  1230  		return v
  1231  	} else if !llvmValue.IsAInstruction().IsNil() || !llvmValue.IsAArgument().IsNil() {
  1232  		return localValue{llvmValue}
  1233  	} else if !llvmValue.IsAInlineAsm().IsNil() {
  1234  		return localValue{llvmValue}
  1235  	} else {
  1236  		llvmValue.Dump()
  1237  		println()
  1238  		panic("unknown value")
  1239  	}
  1240  }
  1241  
  1242  // readObjectLayout reads the object layout as it is stored by the compiler. It
  1243  // returns the size in the number of words and the bitmap.
  1244  //
  1245  // For details on this format, see src/runtime/gc_precise.go.
  1246  func (r *runner) readObjectLayout(layoutValue value) (uint64, *big.Int) {
  1247  	pointerSize := layoutValue.len(r)
  1248  	if checks && uint64(pointerSize) != r.targetData.TypeAllocSize(r.dataPtrType) {
  1249  		panic("inconsistent pointer size")
  1250  	}
  1251  
  1252  	// The object layout can be stored in a global variable, directly as an
  1253  	// integer value, or can be nil.
  1254  	ptr, err := layoutValue.asPointer(r)
  1255  	if err == errIntegerAsPointer {
  1256  		// It's an integer, which means it's a small object or unknown.
  1257  		layout := layoutValue.Uint()
  1258  		if layout == 0 {
  1259  			// Nil pointer, which means the layout is unknown.
  1260  			return 0, nil
  1261  		}
  1262  		if layout%2 != 1 {
  1263  			// Sanity check: the least significant bit must be set. This is how
  1264  			// the runtime can separate pointers from integers.
  1265  			panic("unexpected layout")
  1266  		}
  1267  
  1268  		// Determine format of bitfields in the integer.
  1269  		pointerBits := uint64(pointerSize * 8)
  1270  		var sizeFieldBits uint64
  1271  		switch pointerBits {
  1272  		case 16:
  1273  			sizeFieldBits = 4
  1274  		case 32:
  1275  			sizeFieldBits = 5
  1276  		case 64:
  1277  			sizeFieldBits = 6
  1278  		default:
  1279  			panic("unknown pointer size")
  1280  		}
  1281  
  1282  		// Extract fields.
  1283  		objectSizeWords := (layout >> 1) & (1<<sizeFieldBits - 1)
  1284  		bitmap := new(big.Int).SetUint64(layout >> (1 + sizeFieldBits))
  1285  		return objectSizeWords, bitmap
  1286  	}
  1287  
  1288  	// Read the object size in words and the bitmap from the global.
  1289  	buf := r.objects[ptr.index()].buffer.(rawValue)
  1290  	objectSizeWords := rawValue{buf: buf.buf[:r.pointerSize]}.Uint()
  1291  	rawByteValues := buf.buf[r.pointerSize:]
  1292  	rawBytes := make([]byte, len(rawByteValues))
  1293  	for i, v := range rawByteValues {
  1294  		if uint64(byte(v)) != v {
  1295  			panic("found pointer in data array?") // sanity check
  1296  		}
  1297  		rawBytes[i] = byte(v)
  1298  	}
  1299  	reverseBytes(rawBytes) // little-endian to big-endian
  1300  	bitmap := new(big.Int).SetBytes(rawBytes)
  1301  	return objectSizeWords, bitmap
  1302  }
  1303  
  1304  // getLLVMTypeFromLayout returns the 'layout type', which is an approximation of
  1305  // the real type. Pointers are in the correct location but the actual object may
  1306  // have some additional repetition, for example in the buffer of a slice.
  1307  func (r *runner) getLLVMTypeFromLayout(layoutValue value) llvm.Type {
  1308  	objectSizeWords, bitmap := r.readObjectLayout(layoutValue)
  1309  	if bitmap == nil {
  1310  		// No information available.
  1311  		return llvm.Type{}
  1312  	}
  1313  
  1314  	if bitmap.BitLen() == 0 {
  1315  		// There are no pointers in this object, so treat this as a raw byte
  1316  		// buffer. This is important because objects without pointers may have
  1317  		// lower alignment.
  1318  		return r.mod.Context().Int8Type()
  1319  	}
  1320  
  1321  	// Create the LLVM type.
  1322  	pointerSize := layoutValue.len(r)
  1323  	pointerAlignment := r.targetData.PrefTypeAlignment(r.dataPtrType)
  1324  	var fields []llvm.Type
  1325  	for i := 0; i < int(objectSizeWords); {
  1326  		if bitmap.Bit(i) != 0 {
  1327  			// Pointer field.
  1328  			fields = append(fields, r.dataPtrType)
  1329  			i += int(pointerSize / uint32(pointerAlignment))
  1330  		} else {
  1331  			// Byte/word field.
  1332  			fields = append(fields, r.mod.Context().IntType(pointerAlignment*8))
  1333  			i += 1
  1334  		}
  1335  	}
  1336  	var llvmLayoutType llvm.Type
  1337  	if len(fields) == 1 {
  1338  		llvmLayoutType = fields[0]
  1339  	} else {
  1340  		llvmLayoutType = r.mod.Context().StructType(fields, false)
  1341  	}
  1342  
  1343  	objectSizeBytes := objectSizeWords * uint64(pointerAlignment)
  1344  	if checks && r.targetData.TypeAllocSize(llvmLayoutType) != objectSizeBytes {
  1345  		panic("unexpected size") // sanity check
  1346  	}
  1347  	return llvmLayoutType
  1348  }
  1349  
  1350  // Reverse a slice of bytes. From the wiki:
  1351  // https://github.com/golang/go/wiki/SliceTricks#reversing
  1352  func reverseBytes(buf []byte) {
  1353  	for i := len(buf)/2 - 1; i >= 0; i-- {
  1354  		opp := len(buf) - 1 - i
  1355  		buf[i], buf[opp] = buf[opp], buf[i]
  1356  	}
  1357  }