all: remove pointer ElementType calls

This is needed for opaque pointers, which are enabled by default in
LLVM 15.
Этот коммит содержится в:
Ayke van Laethem 2022-09-22 13:33:00 +02:00 коммит произвёл Ron Evans
родитель 229746b71e
коммит 62df1d7490
17 изменённых файлов: 82 добавлений и 93 удалений

Просмотреть файл

@ -411,7 +411,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe
return errors.New("global not found: " + globalName) return errors.New("global not found: " + globalName)
} }
name := global.Name() name := global.Name()
newGlobal := llvm.AddGlobal(mod, global.Type().ElementType(), name+".tmp") newGlobal := llvm.AddGlobal(mod, global.GlobalValueType(), name+".tmp")
global.ReplaceAllUsesWith(newGlobal) global.ReplaceAllUsesWith(newGlobal)
global.EraseFromParentAsGlobal() global.EraseFromParentAsGlobal()
newGlobal.SetName(name) newGlobal.SetName(name)
@ -1127,7 +1127,7 @@ func setGlobalValues(mod llvm.Module, globals map[string]map[string]string) erro
// A strin is a {ptr, len} pair. We need these types to build the // A strin is a {ptr, len} pair. We need these types to build the
// initializer. // initializer.
initializerType := global.Type().ElementType() initializerType := global.GlobalValueType()
if initializerType.TypeKind() != llvm.StructTypeKind || initializerType.StructName() == "" { if initializerType.TypeKind() != llvm.StructTypeKind || initializerType.StructName() == "" {
return fmt.Errorf("%s: not a string", globalName) return fmt.Errorf("%s: not a string", globalName)
} }

Просмотреть файл

@ -91,7 +91,7 @@ func (b *builder) createSliceToArrayPointerCheck(sliceLen llvm.Value, arrayLen i
// createUnsafeSliceCheck inserts a runtime check used for unsafe.Slice. This // createUnsafeSliceCheck inserts a runtime check used for unsafe.Slice. This
// function must panic if the ptr/len parameters are invalid. // function must panic if the ptr/len parameters are invalid.
func (b *builder) createUnsafeSliceCheck(ptr, len llvm.Value, lenType *types.Basic) { func (b *builder) createUnsafeSliceCheck(ptr, len llvm.Value, elementType llvm.Type, lenType *types.Basic) {
// From the documentation of unsafe.Slice: // From the documentation of unsafe.Slice:
// > At run time, if len is negative, or if ptr is nil and len is not // > At run time, if len is negative, or if ptr is nil and len is not
// > zero, a run-time panic occurs. // > zero, a run-time panic occurs.
@ -105,7 +105,7 @@ func (b *builder) createUnsafeSliceCheck(ptr, len llvm.Value, lenType *types.Bas
// Determine the maximum slice size, and therefore the maximum value of the // Determine the maximum slice size, and therefore the maximum value of the
// len parameter. // len parameter.
maxSize := b.maxSliceSize(ptr.Type().ElementType()) maxSize := b.maxSliceSize(elementType)
maxSizeValue := llvm.ConstInt(len.Type(), maxSize, false) maxSizeValue := llvm.ConstInt(len.Type(), maxSize, false)
// Do the check. By using unsigned greater than for the length check, signed // Do the check. By using unsigned greater than for the length check, signed

Просмотреть файл

@ -20,7 +20,7 @@ const maxFieldsPerParam = 3
type paramInfo struct { type paramInfo struct {
llvmType llvm.Type llvmType llvm.Type
name string // name, possibly with suffixes for e.g. struct fields name string // name, possibly with suffixes for e.g. struct fields
flags paramFlags elemSize uint64 // size of pointer element type, or 0 if this isn't a pointer
} }
// paramFlags identifies parameter attributes for flags. Most importantly, it // paramFlags identifies parameter attributes for flags. Most importantly, it
@ -96,13 +96,7 @@ func (c *compilerContext) expandFormalParamType(t llvm.Type, name string, goType
// failed to expand this parameter: too many fields // failed to expand this parameter: too many fields
} }
// TODO: split small arrays // TODO: split small arrays
return []paramInfo{ return []paramInfo{c.getParamInfo(t, name, goType)}
{
llvmType: t,
name: name,
flags: getTypeFlags(goType),
},
}
} }
// expandFormalParamOffsets returns a list of offsets from the start of an // expandFormalParamOffsets returns a list of offsets from the start of an
@ -152,7 +146,6 @@ func (b *builder) expandFormalParam(v llvm.Value) []llvm.Value {
// Try to flatten a struct type to a list of types. Returns a 1-element slice // Try to flatten a struct type to a list of types. Returns a 1-element slice
// with the passed in type if this is not possible. // with the passed in type if this is not possible.
func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType types.Type) []paramInfo { func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType types.Type) []paramInfo {
typeFlags := getTypeFlags(goType)
switch t.TypeKind() { switch t.TypeKind() {
case llvm.StructTypeKind: case llvm.StructTypeKind:
var paramInfos []paramInfo var paramInfos []paramInfo
@ -183,40 +176,37 @@ func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType
} }
} }
subInfos := c.flattenAggregateType(subfield, name+"."+suffix, extractSubfield(goType, i)) subInfos := c.flattenAggregateType(subfield, name+"."+suffix, extractSubfield(goType, i))
for i := range subInfos {
subInfos[i].flags |= typeFlags
}
paramInfos = append(paramInfos, subInfos...) paramInfos = append(paramInfos, subInfos...)
} }
return paramInfos return paramInfos
default: default:
return []paramInfo{ return []paramInfo{c.getParamInfo(t, name, goType)}
{
llvmType: t,
name: name,
flags: typeFlags,
},
}
} }
} }
// getTypeFlags returns the type flags for a given type. It will not recurse // getParamInfo collects information about a parameter. For example, if this
// into sub-types (such as in structs). // parameter is pointer-like, it will also store the element type for the
func getTypeFlags(t types.Type) paramFlags { // dereferenceable_or_null attribute.
if t == nil { func (c *compilerContext) getParamInfo(t llvm.Type, name string, goType types.Type) paramInfo {
return 0 info := paramInfo{
llvmType: t,
name: name,
} }
switch t.Underlying().(type) { if goType != nil {
case *types.Pointer: switch underlying := goType.Underlying().(type) {
// Pointers in Go must either point to an object or be nil. case *types.Pointer:
return paramIsDeferenceableOrNull // Pointers in Go must either point to an object or be nil.
case *types.Chan, *types.Map: info.elemSize = c.targetData.TypeAllocSize(c.getLLVMType(underlying.Elem()))
// Channels and maps are implemented as pointers pointing to some case *types.Chan:
// object, and follow the same rules as *types.Pointer. // Channels are implemented simply as a *runtime.channel.
return paramIsDeferenceableOrNull info.elemSize = c.targetData.TypeAllocSize(c.getLLVMRuntimeType("channel"))
default: case *types.Map:
return 0 // Maps are similar to channels: they are implemented as a
// *runtime.hashmap.
info.elemSize = c.targetData.TypeAllocSize(c.getLLVMRuntimeType("hashmap"))
}
} }
return info
} }
// extractSubfield extracts a field from a struct, or returns null if this is // extractSubfield extracts a field from a struct, or returns null if this is

Просмотреть файл

@ -862,7 +862,7 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package
if files, ok := c.embedGlobals[member.Name()]; ok { if files, ok := c.embedGlobals[member.Name()]; ok {
c.createEmbedGlobal(member, global, files) c.createEmbedGlobal(member, global, files)
} else if !info.extern { } else if !info.extern {
global.SetInitializer(llvm.ConstNull(global.Type().ElementType())) global.SetInitializer(llvm.ConstNull(global.GlobalValueType()))
global.SetVisibility(llvm.HiddenVisibility) global.SetVisibility(llvm.HiddenVisibility)
if info.section != "" { if info.section != "" {
global.SetSection(info.section) global.SetSection(info.section)
@ -1405,7 +1405,7 @@ func (b *builder) createInstruction(instr ssa.Instruction) {
b.CreateRet(b.getValue(instr.Results[0])) b.CreateRet(b.getValue(instr.Results[0]))
} else { } else {
// Multiple return values. Put them all in a struct. // Multiple return values. Put them all in a struct.
retVal := llvm.ConstNull(b.llvmFn.Type().ElementType().ReturnType()) retVal := llvm.ConstNull(b.llvmFn.GlobalValueType().ReturnType())
for i, result := range instr.Results { for i, result := range instr.Results {
val := b.getValue(result) val := b.getValue(result)
retVal = b.CreateInsertValue(retVal, val, i, "") retVal = b.CreateInsertValue(retVal, val, i, "")
@ -1444,7 +1444,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
elemsBuf := b.CreateExtractValue(elems, 0, "append.elemsBuf") elemsBuf := b.CreateExtractValue(elems, 0, "append.elemsBuf")
elemsPtr := b.CreateBitCast(elemsBuf, b.i8ptrType, "append.srcPtr") elemsPtr := b.CreateBitCast(elemsBuf, b.i8ptrType, "append.srcPtr")
elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen") elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen")
elemType := srcBuf.Type().ElementType() elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false) elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcPtr, elemsPtr, srcLen, srcCap, elemsLen, elemSize}, "append.new") result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcPtr, elemsPtr, srcLen, srcCap, elemsLen, elemSize}, "append.new")
newPtr := b.CreateExtractValue(result, 0, "append.newPtr") newPtr := b.CreateExtractValue(result, 0, "append.newPtr")
@ -1497,7 +1497,7 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
srcLen := b.CreateExtractValue(src, 1, "copy.srcLen") srcLen := b.CreateExtractValue(src, 1, "copy.srcLen")
dstBuf := b.CreateExtractValue(dst, 0, "copy.dstArray") dstBuf := b.CreateExtractValue(dst, 0, "copy.dstArray")
srcBuf := b.CreateExtractValue(src, 0, "copy.srcArray") srcBuf := b.CreateExtractValue(src, 0, "copy.srcArray")
elemType := dstBuf.Type().ElementType() elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
dstBuf = b.CreateBitCast(dstBuf, b.i8ptrType, "copy.dstPtr") dstBuf = b.CreateBitCast(dstBuf, b.i8ptrType, "copy.dstPtr")
srcBuf = b.CreateBitCast(srcBuf, b.i8ptrType, "copy.srcPtr") srcBuf = b.CreateBitCast(srcBuf, b.i8ptrType, "copy.srcPtr")
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false) elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
@ -1637,7 +1637,8 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
b.uintptrType, b.uintptrType,
b.uintptrType, b.uintptrType,
}, false)) }, false))
b.createUnsafeSliceCheck(ptr, len, argTypes[1].Underlying().(*types.Basic)) elementType := b.getLLVMType(argTypes[0].Underlying().(*types.Pointer).Elem())
b.createUnsafeSliceCheck(ptr, len, elementType, argTypes[1].Underlying().(*types.Basic))
if len.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() { if len.Type().IntTypeWidth() < b.uintptrType.IntTypeWidth() {
// Too small, zero-extend len. // Too small, zero-extend len.
len = b.CreateZExt(len, b.uintptrType, "") len = b.CreateZExt(len, b.uintptrType, "")
@ -1712,7 +1713,7 @@ func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error)
// Eventually we might be able to eliminate this special case // Eventually we might be able to eliminate this special case
// entirely. For details, see: // entirely. For details, see:
// https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c/60521 // https://discourse.llvm.org/t/rfc-enabling-wstrict-prototypes-by-default-in-c/60521
calleeType = llvm.FunctionType(callee.Type().ElementType().ReturnType(), nil, false) calleeType = llvm.FunctionType(callee.GlobalValueType().ReturnType(), nil, false)
callee = llvm.ConstBitCast(callee, llvm.PointerType(calleeType, b.funcPtrAddrSpace)) callee = llvm.ConstBitCast(callee, llvm.PointerType(calleeType, b.funcPtrAddrSpace))
} }
case *ssa.MakeClosure: case *ssa.MakeClosure:
@ -3095,7 +3096,7 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) {
} }
case token.MUL: // *x, dereference pointer case token.MUL: // *x, dereference pointer
valueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Pointer).Elem()) valueType := b.getLLVMType(unop.X.Type().Underlying().(*types.Pointer).Elem())
if b.targetData.TypeAllocSize(x.Type().ElementType()) == 0 { if b.targetData.TypeAllocSize(valueType) == 0 {
// zero-length data // zero-length data
return llvm.ConstNull(valueType), nil return llvm.ConstNull(valueType), nil
} else if strings.HasSuffix(unop.X.String(), "$funcaddr") { } else if strings.HasSuffix(unop.X.String(), "$funcaddr") {

Просмотреть файл

@ -73,7 +73,7 @@ func (c *compilerContext) getFuncType(typ *types.Signature) llvm.Type {
return c.ctx.StructType([]llvm.Type{c.i8ptrType, c.rawVoidFuncType}, false) return c.ctx.StructType([]llvm.Type{c.i8ptrType, c.rawVoidFuncType}, false)
} }
// getRawFuncType returns a LLVM function pointer type for a given signature. // getRawFuncType returns a LLVM function type for a given signature.
func (c *compilerContext) getRawFuncType(typ *types.Signature) llvm.Type { func (c *compilerContext) getRawFuncType(typ *types.Signature) llvm.Type {
// Get the return type. // Get the return type.
var returnType llvm.Type var returnType llvm.Type

Просмотреть файл

@ -86,7 +86,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
if _, ok := typ.Underlying().(*types.Pointer); !ok { if _, ok := typ.Underlying().(*types.Pointer); !ok {
ptrTo = c.getTypeCode(types.NewPointer(typ)) ptrTo = c.getTypeCode(types.NewPointer(typ))
} }
globalValue := llvm.ConstNull(global.Type().ElementType()) globalValue := llvm.ConstNull(global.GlobalValueType())
if !references.IsNil() { if !references.IsNil() {
globalValue = c.builder.CreateInsertValue(globalValue, references, 0, "") globalValue = c.builder.CreateInsertValue(globalValue, references, 0, "")
} }
@ -533,7 +533,7 @@ func (c *compilerContext) getInterfaceInvokeWrapper(fn *ssa.Function, llvmFnType
receiverValue := b.emitPointerUnpack(wrapper.Param(0), []llvm.Type{receiverType})[0] receiverValue := b.emitPointerUnpack(wrapper.Param(0), []llvm.Type{receiverType})[0]
params := append(b.expandFormalParam(receiverValue), wrapper.Params()[1:]...) params := append(b.expandFormalParam(receiverValue), wrapper.Params()[1:]...)
if llvmFn.Type().ElementType().ReturnType().TypeKind() == llvm.VoidTypeKind { if llvmFnType.ReturnType().TypeKind() == llvm.VoidTypeKind {
b.CreateCall(llvmFnType, llvmFn, params, "") b.CreateCall(llvmFnType, llvmFn, params, "")
b.CreateRetVoid() b.CreateRetVoid()
} else { } else {

Просмотреть файл

@ -70,10 +70,7 @@ func (c *checker) checkType(t llvm.Type, checked map[llvm.Type]struct{}, special
return fmt.Errorf("failed to verify element type of array type %s: %s", t.String(), err.Error()) return fmt.Errorf("failed to verify element type of array type %s: %s", t.String(), err.Error())
} }
case llvm.PointerTypeKind: case llvm.PointerTypeKind:
// check underlying type // Pointers can't be checked in an opaque pointer world.
if err := c.checkType(t.ElementType(), checked, specials); err != nil {
return fmt.Errorf("failed to verify underlying type of pointer type %s: %s", t.String(), err.Error())
}
case llvm.VectorTypeKind: case llvm.VectorTypeKind:
// check element type // check element type
if err := c.checkType(t.ElementType(), checked, specials); err != nil { if err := c.checkType(t.ElementType(), checked, specials); err != nil {

Просмотреть файл

@ -83,7 +83,7 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
// Add an extra parameter as the function context. This context is used in // Add an extra parameter as the function context. This context is used in
// closures and bound methods, but should be optimized away when not used. // closures and bound methods, but should be optimized away when not used.
if !info.exported { if !info.exported {
paramInfos = append(paramInfos, paramInfo{llvmType: c.i8ptrType, name: "context", flags: 0}) paramInfos = append(paramInfos, paramInfo{llvmType: c.i8ptrType, name: "context", elemSize: 0})
} }
var paramTypes []llvm.Type var paramTypes []llvm.Type
@ -112,17 +112,8 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value)
dereferenceableOrNullKind := llvm.AttributeKindID("dereferenceable_or_null") dereferenceableOrNullKind := llvm.AttributeKindID("dereferenceable_or_null")
for i, info := range paramInfos { for i, info := range paramInfos {
if info.flags&paramIsDeferenceableOrNull == 0 { if info.elemSize != 0 {
continue dereferenceableOrNull := c.ctx.CreateEnumAttribute(dereferenceableOrNullKind, info.elemSize)
}
if info.llvmType.TypeKind() == llvm.PointerTypeKind {
el := info.llvmType.ElementType()
size := c.targetData.TypeAllocSize(el)
if size == 0 {
// dereferenceable_or_null(0) appears to be illegal in LLVM.
continue
}
dereferenceableOrNull := c.ctx.CreateEnumAttribute(dereferenceableOrNullKind, size)
llvmFn.AddAttributeAtIndex(i+1, dereferenceableOrNull) llvmFn.AddAttributeAtIndex(i+1, dereferenceableOrNull)
} }
} }

Просмотреть файл

@ -209,7 +209,7 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
case llvm.Alloca: case llvm.Alloca:
// Alloca allocates stack space for local variables. // Alloca allocates stack space for local variables.
numElements := r.getValue(inst.llvmInst.Operand(0)).(literalValue).value.(uint32) numElements := r.getValue(inst.llvmInst.Operand(0)).(literalValue).value.(uint32)
elementSize := r.targetData.TypeAllocSize(inst.llvmInst.Type().ElementType()) elementSize := r.targetData.TypeAllocSize(inst.llvmInst.AllocatedType())
inst.operands = []value{ inst.operands = []value{
literalValue{elementSize * uint64(numElements)}, literalValue{elementSize * uint64(numElements)},
} }
@ -218,17 +218,17 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
inst.name = llvmInst.Name() inst.name = llvmInst.Name()
ptr := llvmInst.Operand(0) ptr := llvmInst.Operand(0)
n := llvmInst.OperandsCount() n := llvmInst.OperandsCount()
elementType := ptr.Type().ElementType() elementType := llvmInst.GEPSourceElementType()
// gep: [source ptr, dest value size, pairs of indices...] // gep: [source ptr, dest value size, pairs of indices...]
inst.operands = []value{ inst.operands = []value{
r.getValue(ptr), r.getValue(ptr),
literalValue{r.targetData.TypeAllocSize(llvmInst.Type().ElementType())},
r.getValue(llvmInst.Operand(1)), r.getValue(llvmInst.Operand(1)),
literalValue{r.targetData.TypeAllocSize(elementType)}, literalValue{r.targetData.TypeAllocSize(elementType)},
} }
for i := 2; i < n; i++ { for i := 2; i < n; i++ {
operand := r.getValue(llvmInst.Operand(i)) operand := r.getValue(llvmInst.Operand(i))
if elementType.TypeKind() == llvm.StructTypeKind { switch elementType.TypeKind() {
case llvm.StructTypeKind:
index := operand.(literalValue).value.(uint32) index := operand.(literalValue).value.(uint32)
elementOffset := r.targetData.ElementOffset(elementType, int(index)) elementOffset := r.targetData.ElementOffset(elementType, int(index))
// Encode operands in a special way. The elementOffset // Encode operands in a special way. The elementOffset
@ -242,12 +242,15 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
// runtime. // runtime.
inst.operands = append(inst.operands, literalValue{elementOffset}, literalValue{^uint64(index)}) inst.operands = append(inst.operands, literalValue{elementOffset}, literalValue{^uint64(index)})
elementType = elementType.StructElementTypes()[index] elementType = elementType.StructElementTypes()[index]
} else { case llvm.ArrayTypeKind:
elementType = elementType.ElementType() elementType = elementType.ElementType()
elementSize := r.targetData.TypeAllocSize(elementType) elementSize := r.targetData.TypeAllocSize(elementType)
elementSizeOperand := literalValue{elementSize} elementSizeOperand := literalValue{elementSize}
// Add operand * elementSizeOperand bytes to the pointer. // Add operand * elementSizeOperand bytes to the pointer.
inst.operands = append(inst.operands, operand, elementSizeOperand) inst.operands = append(inst.operands, operand, elementSizeOperand)
default:
// This should be unreachable.
panic("unknown type: " + elementType.String())
} }
} }
case llvm.BitCast, llvm.IntToPtr, llvm.PtrToInt: case llvm.BitCast, llvm.IntToPtr, llvm.PtrToInt:
@ -267,10 +270,12 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
case llvm.StructTypeKind: case llvm.StructTypeKind:
offset += r.targetData.ElementOffset(indexingType, int(index)) offset += r.targetData.ElementOffset(indexingType, int(index))
indexingType = indexingType.StructElementTypes()[index] indexingType = indexingType.StructElementTypes()[index]
default: // ArrayTypeKind case llvm.ArrayTypeKind:
indexingType = indexingType.ElementType() indexingType = indexingType.ElementType()
elementSize := r.targetData.TypeAllocSize(indexingType) elementSize := r.targetData.TypeAllocSize(indexingType)
offset += elementSize * uint64(index) offset += elementSize * uint64(index)
default:
panic("unknown type kind") // unreachable
} }
} }
size := r.targetData.TypeAllocSize(inst.llvmInst.Type()) size := r.targetData.TypeAllocSize(inst.llvmInst.Type())
@ -290,10 +295,12 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function {
case llvm.StructTypeKind: case llvm.StructTypeKind:
offset += r.targetData.ElementOffset(indexingType, int(index)) offset += r.targetData.ElementOffset(indexingType, int(index))
indexingType = indexingType.StructElementTypes()[index] indexingType = indexingType.StructElementTypes()[index]
default: // ArrayTypeKind case llvm.ArrayTypeKind:
indexingType = indexingType.ElementType() indexingType = indexingType.ElementType()
elementSize := r.targetData.TypeAllocSize(indexingType) elementSize := r.targetData.TypeAllocSize(indexingType)
offset += elementSize * uint64(index) offset += elementSize * uint64(index)
default:
panic("unknown type kind") // unreachable
} }
} }
// insertvalue [agg, elt, byteOffset] // insertvalue [agg, elt, byteOffset]

Просмотреть файл

@ -156,7 +156,7 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
if obj.constant { if obj.constant {
continue // constant buffers can't have been modified continue // constant buffers can't have been modified
} }
initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.Type().ElementType(), &mem) initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.GlobalValueType(), &mem)
if err == errInvalidPtrToIntSize { if err == errInvalidPtrToIntSize {
// This can happen when a previous interp run did not have the // This can happen when a previous interp run did not have the
// correct LLVM type for a global and made something up. In that // correct LLVM type for a global and made something up. In that
@ -190,7 +190,7 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error {
if err != nil { if err != nil {
return err return err
} }
if checks && initializer.Type() != obj.llvmGlobal.Type().ElementType() { if checks && initializer.Type() != obj.llvmGlobal.GlobalValueType() {
panic("initializer type mismatch") panic("initializer type mismatch")
} }
obj.llvmGlobal.SetInitializer(initializer) obj.llvmGlobal.SetInitializer(initializer)
@ -213,7 +213,7 @@ func RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error {
r.pkgName = initName[:len(initName)-len(".init")] r.pkgName = initName[:len(initName)-len(".init")]
// Create new function with the interp result. // Create new function with the interp result.
newFn := llvm.AddFunction(mod, fn.Name()+".tmp", fn.Type().ElementType()) newFn := llvm.AddFunction(mod, fn.Name()+".tmp", fn.GlobalValueType())
newFn.SetLinkage(fn.Linkage()) newFn.SetLinkage(fn.Linkage())
newFn.SetVisibility(fn.Visibility()) newFn.SetVisibility(fn.Visibility())
entry := mod.Context().AddBasicBlock(newFn, "entry") entry := mod.Context().AddBasicBlock(newFn, "entry")
@ -263,11 +263,11 @@ func RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error {
if obj.constant { if obj.constant {
continue // constant, so can't have been modified continue // constant, so can't have been modified
} }
initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.Type().ElementType(), &mem) initializer, err := obj.buffer.toLLVMValue(obj.llvmGlobal.GlobalValueType(), &mem)
if err != nil { if err != nil {
return err return err
} }
if checks && initializer.Type() != obj.llvmGlobal.Type().ElementType() { if checks && initializer.Type() != obj.llvmGlobal.GlobalValueType() {
panic("initializer type mismatch") panic("initializer type mismatch")
} }
obj.llvmGlobal.SetInitializer(initializer) obj.llvmGlobal.SetInitializer(initializer)

Просмотреть файл

@ -655,7 +655,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent
// GetElementPtr does pointer arithmetic, changing the offset of the // GetElementPtr does pointer arithmetic, changing the offset of the
// pointer into the underlying object. // pointer into the underlying object.
var offset uint64 var offset uint64
for i := 2; i < len(operands); i += 2 { for i := 1; i < len(operands); i += 2 {
index := operands[i].Uint() index := operands[i].Uint()
elementSize := operands[i+1].Uint() elementSize := operands[i+1].Uint()
if int64(elementSize) < 0 { if int64(elementSize) < 0 {

Просмотреть файл

@ -808,14 +808,17 @@ func (v rawValue) rawLLVMValue(mem *memoryView) (llvm.Value, error) {
if err != nil { if err != nil {
return llvm.Value{}, err return llvm.Value{}, err
} }
elementType := field.Type().ElementType() if !field.IsAGlobalVariable().IsNil() {
if elementType.TypeKind() == llvm.StructTypeKind { elementType := field.GlobalValueType()
// There are some special pointer types that should be used as a if elementType.TypeKind() == llvm.StructTypeKind {
// ptrtoint, so that they can be used in certain optimizations. // There are some special pointer types that should be used
name := elementType.StructName() // as a ptrtoint, so that they can be used in certain
if name == "runtime.typecodeID" || name == "runtime.funcValueWithSignature" { // optimizations.
uintptrType := ctx.IntType(int(mem.r.pointerSize) * 8) name := elementType.StructName()
field = llvm.ConstPtrToInt(field, uintptrType) if name == "runtime.typecodeID" || name == "runtime.funcValueWithSignature" {
uintptrType := ctx.IntType(int(mem.r.pointerSize) * 8)
field = llvm.ConstPtrToInt(field, uintptrType)
}
} }
} }
structFields = append(structFields, field) structFields = append(structFields, field)
@ -998,7 +1001,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) {
ptr := llvmValue.Operand(0) ptr := llvmValue.Operand(0)
index := llvmValue.Operand(1) index := llvmValue.Operand(1)
numOperands := llvmValue.OperandsCount() numOperands := llvmValue.OperandsCount()
elementType := ptr.Type().ElementType() elementType := llvmValue.GEPSourceElementType()
totalOffset := r.targetData.TypeAllocSize(elementType) * index.ZExtValue() totalOffset := r.targetData.TypeAllocSize(elementType) * index.ZExtValue()
for i := 2; i < numOperands; i++ { for i := 2; i < numOperands; i++ {
indexValue := llvmValue.Operand(i) indexValue := llvmValue.Operand(i)
@ -1173,7 +1176,7 @@ func (r *runner) getValue(llvmValue llvm.Value) value {
r.globals[llvmValue] = index r.globals[llvmValue] = index
r.objects = append(r.objects, obj) r.objects = append(r.objects, obj)
if !llvmValue.IsAGlobalVariable().IsNil() { if !llvmValue.IsAGlobalVariable().IsNil() {
obj.size = uint32(r.targetData.TypeAllocSize(llvmValue.Type().ElementType())) obj.size = uint32(r.targetData.TypeAllocSize(llvmValue.GlobalValueType()))
if initializer := llvmValue.Initializer(); !initializer.IsNil() { if initializer := llvmValue.Initializer(); !initializer.IsNil() {
obj.buffer = r.getValue(initializer) obj.buffer = r.getValue(initializer)
obj.constant = llvmValue.IsGlobalConstant() obj.constant = llvmValue.IsGlobalConstant()

Просмотреть файл

@ -124,7 +124,7 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, logger func(tok
alloca.SetAlignment(alignment) alloca.SetAlignment(alignment)
// Zero the allocation inside the block where the value was originally allocated. // Zero the allocation inside the block where the value was originally allocated.
zero := llvm.ConstNull(alloca.Type().ElementType()) zero := llvm.ConstNull(alloca.AllocatedType())
builder.SetInsertPointBefore(bitcast) builder.SetInsertPointBefore(bitcast)
store := builder.CreateStore(zero, alloca) store := builder.CreateStore(zero, alloca)
store.SetAlignment(alignment) store.SetAlignment(alignment)

Просмотреть файл

@ -18,7 +18,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
stackChainStart := mod.NamedGlobal("runtime.stackChainStart") stackChainStart := mod.NamedGlobal("runtime.stackChainStart")
if !stackChainStart.IsNil() { if !stackChainStart.IsNil() {
stackChainStart.SetLinkage(llvm.InternalLinkage) stackChainStart.SetLinkage(llvm.InternalLinkage)
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.Type().ElementType())) stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.GlobalValueType()))
stackChainStart.SetGlobalConstant(true) stackChainStart.SetGlobalConstant(true)
} }
return false return false
@ -96,7 +96,7 @@ func MakeGCStackSlots(mod llvm.Module) bool {
return false return false
} }
stackChainStart.SetLinkage(llvm.InternalLinkage) stackChainStart.SetLinkage(llvm.InternalLinkage)
stackChainStartType := stackChainStart.Type().ElementType() stackChainStartType := stackChainStart.GlobalValueType()
stackChainStart.SetInitializer(llvm.ConstNull(stackChainStartType)) stackChainStart.SetInitializer(llvm.ConstNull(stackChainStartType))
// Iterate until runtime.trackPointer has no uses left. // Iterate until runtime.trackPointer has no uses left.

Просмотреть файл

@ -423,7 +423,7 @@ func (p *lowerInterfacesPass) defineInterfaceImplementsFunc(fn llvm.Value, itf *
func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *interfaceInfo, signature *signatureInfo) { func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *interfaceInfo, signature *signatureInfo) {
context := fn.LastParam() context := fn.LastParam()
actualType := llvm.PrevParam(context) actualType := llvm.PrevParam(context)
returnType := fn.Type().ElementType().ReturnType() returnType := fn.GlobalValueType().ReturnType()
context.SetName("context") context.SetName("context")
actualType.SetName("actualType") actualType.SetName("actualType")
fn.SetLinkage(llvm.InternalLinkage) fn.SetLinkage(llvm.InternalLinkage)

Просмотреть файл

@ -66,7 +66,7 @@ func getGlobalBytes(global llvm.Value, builder llvm.Builder) []byte {
// function used for creating reflection sidetables, for example. // function used for creating reflection sidetables, for example.
func replaceGlobalIntWithArray(mod llvm.Module, name string, buf interface{}) llvm.Value { func replaceGlobalIntWithArray(mod llvm.Module, name string, buf interface{}) llvm.Value {
oldGlobal := mod.NamedGlobal(name) oldGlobal := mod.NamedGlobal(name)
globalType, global := makeGlobalArray(mod, buf, name+".tmp", oldGlobal.Type().ElementType()) globalType, global := makeGlobalArray(mod, buf, name+".tmp", oldGlobal.GlobalValueType())
gep := llvm.ConstGEP(globalType, global, []llvm.Value{ gep := llvm.ConstGEP(globalType, global, []llvm.Value{
llvm.ConstInt(mod.Context().Int32Type(), 0, false), llvm.ConstInt(mod.Context().Int32Type(), 0, false),
llvm.ConstInt(mod.Context().Int32Type(), 0, false), llvm.ConstInt(mod.Context().Int32Type(), 0, false),

Просмотреть файл

@ -50,7 +50,7 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config) error {
paramTypes := []llvm.Type{} paramTypes := []llvm.Type{}
// Check return type for 64-bit integer. // Check return type for 64-bit integer.
fnType := fn.Type().ElementType() fnType := fn.GlobalValueType()
returnType := fnType.ReturnType() returnType := fnType.ReturnType()
if returnType == int64Type { if returnType == int64Type {
hasInt64 = true hasInt64 = true