diff --git a/builder/build.go b/builder/build.go index 7a6b9dbb..17a007f8 100644 --- a/builder/build.go +++ b/builder/build.go @@ -411,7 +411,7 @@ func Build(pkgName, outpath, tmpdir string, config *compileopts.Config) (BuildRe return errors.New("global not found: " + globalName) } name := global.Name() - newGlobal := llvm.AddGlobal(mod, global.Type().ElementType(), name+".tmp") + newGlobal := llvm.AddGlobal(mod, global.GlobalValueType(), name+".tmp") global.ReplaceAllUsesWith(newGlobal) global.EraseFromParentAsGlobal() 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 // initializer. - initializerType := global.Type().ElementType() + initializerType := global.GlobalValueType() if initializerType.TypeKind() != llvm.StructTypeKind || initializerType.StructName() == "" { return fmt.Errorf("%s: not a string", globalName) } diff --git a/compiler/asserts.go b/compiler/asserts.go index 2a5265e9..ba482494 100644 --- a/compiler/asserts.go +++ b/compiler/asserts.go @@ -91,7 +91,7 @@ func (b *builder) createSliceToArrayPointerCheck(sliceLen llvm.Value, arrayLen i // createUnsafeSliceCheck inserts a runtime check used for unsafe.Slice. This // 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: // > At run time, if len is negative, or if ptr is nil and len is not // > 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 // len parameter. - maxSize := b.maxSliceSize(ptr.Type().ElementType()) + maxSize := b.maxSliceSize(elementType) maxSizeValue := llvm.ConstInt(len.Type(), maxSize, false) // Do the check. By using unsigned greater than for the length check, signed diff --git a/compiler/calls.go b/compiler/calls.go index b38d770f..b122f0c8 100644 --- a/compiler/calls.go +++ b/compiler/calls.go @@ -20,7 +20,7 @@ const maxFieldsPerParam = 3 type paramInfo struct { llvmType llvm.Type 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 @@ -96,13 +96,7 @@ func (c *compilerContext) expandFormalParamType(t llvm.Type, name string, goType // failed to expand this parameter: too many fields } // TODO: split small arrays - return []paramInfo{ - { - llvmType: t, - name: name, - flags: getTypeFlags(goType), - }, - } + return []paramInfo{c.getParamInfo(t, name, goType)} } // 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 // with the passed in type if this is not possible. func (c *compilerContext) flattenAggregateType(t llvm.Type, name string, goType types.Type) []paramInfo { - typeFlags := getTypeFlags(goType) switch t.TypeKind() { case llvm.StructTypeKind: 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)) - for i := range subInfos { - subInfos[i].flags |= typeFlags - } paramInfos = append(paramInfos, subInfos...) } return paramInfos default: - return []paramInfo{ - { - llvmType: t, - name: name, - flags: typeFlags, - }, - } + return []paramInfo{c.getParamInfo(t, name, goType)} } } -// getTypeFlags returns the type flags for a given type. It will not recurse -// into sub-types (such as in structs). -func getTypeFlags(t types.Type) paramFlags { - if t == nil { - return 0 +// getParamInfo collects information about a parameter. For example, if this +// parameter is pointer-like, it will also store the element type for the +// dereferenceable_or_null attribute. +func (c *compilerContext) getParamInfo(t llvm.Type, name string, goType types.Type) paramInfo { + info := paramInfo{ + llvmType: t, + name: name, } - switch t.Underlying().(type) { - case *types.Pointer: - // Pointers in Go must either point to an object or be nil. - return paramIsDeferenceableOrNull - case *types.Chan, *types.Map: - // Channels and maps are implemented as pointers pointing to some - // object, and follow the same rules as *types.Pointer. - return paramIsDeferenceableOrNull - default: - return 0 + if goType != nil { + switch underlying := goType.Underlying().(type) { + case *types.Pointer: + // Pointers in Go must either point to an object or be nil. + info.elemSize = c.targetData.TypeAllocSize(c.getLLVMType(underlying.Elem())) + case *types.Chan: + // Channels are implemented simply as a *runtime.channel. + info.elemSize = c.targetData.TypeAllocSize(c.getLLVMRuntimeType("channel")) + case *types.Map: + // 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 diff --git a/compiler/compiler.go b/compiler/compiler.go index 3d29628c..fc47c29c 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -862,7 +862,7 @@ func (c *compilerContext) createPackage(irbuilder llvm.Builder, pkg *ssa.Package if files, ok := c.embedGlobals[member.Name()]; ok { c.createEmbedGlobal(member, global, files) } else if !info.extern { - global.SetInitializer(llvm.ConstNull(global.Type().ElementType())) + global.SetInitializer(llvm.ConstNull(global.GlobalValueType())) global.SetVisibility(llvm.HiddenVisibility) if info.section != "" { global.SetSection(info.section) @@ -1405,7 +1405,7 @@ func (b *builder) createInstruction(instr ssa.Instruction) { b.CreateRet(b.getValue(instr.Results[0])) } else { // 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 { val := b.getValue(result) 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") elemsPtr := b.CreateBitCast(elemsBuf, b.i8ptrType, "append.srcPtr") 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) result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcPtr, elemsPtr, srcLen, srcCap, elemsLen, elemSize}, "append.new") 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") dstBuf := b.CreateExtractValue(dst, 0, "copy.dstArray") 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") srcBuf = b.CreateBitCast(srcBuf, b.i8ptrType, "copy.srcPtr") 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, }, 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() { // Too small, zero-extend len. 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 // entirely. For details, see: // 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)) } case *ssa.MakeClosure: @@ -3095,7 +3096,7 @@ func (b *builder) createUnOp(unop *ssa.UnOp) (llvm.Value, error) { } case token.MUL: // *x, dereference pointer 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 return llvm.ConstNull(valueType), nil } else if strings.HasSuffix(unop.X.String(), "$funcaddr") { diff --git a/compiler/func.go b/compiler/func.go index c6a8802d..4203fdf7 100644 --- a/compiler/func.go +++ b/compiler/func.go @@ -73,7 +73,7 @@ func (c *compilerContext) getFuncType(typ *types.Signature) llvm.Type { 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 { // Get the return type. var returnType llvm.Type diff --git a/compiler/interface.go b/compiler/interface.go index 106c327a..2007b7d7 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -86,7 +86,7 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { if _, ok := typ.Underlying().(*types.Pointer); !ok { ptrTo = c.getTypeCode(types.NewPointer(typ)) } - globalValue := llvm.ConstNull(global.Type().ElementType()) + globalValue := llvm.ConstNull(global.GlobalValueType()) if !references.IsNil() { 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] 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.CreateRetVoid() } else { diff --git a/compiler/ircheck/check.go b/compiler/ircheck/check.go index 30c6ee17..e2b7ed51 100644 --- a/compiler/ircheck/check.go +++ b/compiler/ircheck/check.go @@ -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()) } case llvm.PointerTypeKind: - // check underlying type - 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()) - } + // Pointers can't be checked in an opaque pointer world. case llvm.VectorTypeKind: // check element type if err := c.checkType(t.ElementType(), checked, specials); err != nil { diff --git a/compiler/symbol.go b/compiler/symbol.go index 83fe050b..01b3fc37 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -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 // closures and bound methods, but should be optimized away when not used. 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 @@ -112,17 +112,8 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) dereferenceableOrNullKind := llvm.AttributeKindID("dereferenceable_or_null") for i, info := range paramInfos { - if info.flags¶mIsDeferenceableOrNull == 0 { - continue - } - 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) + if info.elemSize != 0 { + dereferenceableOrNull := c.ctx.CreateEnumAttribute(dereferenceableOrNullKind, info.elemSize) llvmFn.AddAttributeAtIndex(i+1, dereferenceableOrNull) } } diff --git a/interp/compiler.go b/interp/compiler.go index 20723c64..ffef69e5 100644 --- a/interp/compiler.go +++ b/interp/compiler.go @@ -209,7 +209,7 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function { case llvm.Alloca: // Alloca allocates stack space for local variables. 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{ literalValue{elementSize * uint64(numElements)}, } @@ -218,17 +218,17 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function { inst.name = llvmInst.Name() ptr := llvmInst.Operand(0) n := llvmInst.OperandsCount() - elementType := ptr.Type().ElementType() + elementType := llvmInst.GEPSourceElementType() // gep: [source ptr, dest value size, pairs of indices...] inst.operands = []value{ r.getValue(ptr), - literalValue{r.targetData.TypeAllocSize(llvmInst.Type().ElementType())}, r.getValue(llvmInst.Operand(1)), literalValue{r.targetData.TypeAllocSize(elementType)}, } for i := 2; i < n; i++ { operand := r.getValue(llvmInst.Operand(i)) - if elementType.TypeKind() == llvm.StructTypeKind { + switch elementType.TypeKind() { + case llvm.StructTypeKind: index := operand.(literalValue).value.(uint32) elementOffset := r.targetData.ElementOffset(elementType, int(index)) // Encode operands in a special way. The elementOffset @@ -242,12 +242,15 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function { // runtime. inst.operands = append(inst.operands, literalValue{elementOffset}, literalValue{^uint64(index)}) elementType = elementType.StructElementTypes()[index] - } else { + case llvm.ArrayTypeKind: elementType = elementType.ElementType() elementSize := r.targetData.TypeAllocSize(elementType) elementSizeOperand := literalValue{elementSize} // Add operand * elementSizeOperand bytes to the pointer. inst.operands = append(inst.operands, operand, elementSizeOperand) + default: + // This should be unreachable. + panic("unknown type: " + elementType.String()) } } case llvm.BitCast, llvm.IntToPtr, llvm.PtrToInt: @@ -267,10 +270,12 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function { case llvm.StructTypeKind: offset += r.targetData.ElementOffset(indexingType, int(index)) indexingType = indexingType.StructElementTypes()[index] - default: // ArrayTypeKind + case llvm.ArrayTypeKind: indexingType = indexingType.ElementType() elementSize := r.targetData.TypeAllocSize(indexingType) offset += elementSize * uint64(index) + default: + panic("unknown type kind") // unreachable } } size := r.targetData.TypeAllocSize(inst.llvmInst.Type()) @@ -290,10 +295,12 @@ func (r *runner) compileFunction(llvmFn llvm.Value) *function { case llvm.StructTypeKind: offset += r.targetData.ElementOffset(indexingType, int(index)) indexingType = indexingType.StructElementTypes()[index] - default: // ArrayTypeKind + case llvm.ArrayTypeKind: indexingType = indexingType.ElementType() elementSize := r.targetData.TypeAllocSize(indexingType) offset += elementSize * uint64(index) + default: + panic("unknown type kind") // unreachable } } // insertvalue [agg, elt, byteOffset] diff --git a/interp/interp.go b/interp/interp.go index 856f08b1..7833dfe9 100644 --- a/interp/interp.go +++ b/interp/interp.go @@ -156,7 +156,7 @@ func Run(mod llvm.Module, timeout time.Duration, debug bool) error { if obj.constant { 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 { // This can happen when a previous interp run did not have the // 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 { return err } - if checks && initializer.Type() != obj.llvmGlobal.Type().ElementType() { + if checks && initializer.Type() != obj.llvmGlobal.GlobalValueType() { panic("initializer type mismatch") } 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")] // 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.SetVisibility(fn.Visibility()) entry := mod.Context().AddBasicBlock(newFn, "entry") @@ -263,11 +263,11 @@ func RunFunc(fn llvm.Value, timeout time.Duration, debug bool) error { if obj.constant { 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 { return err } - if checks && initializer.Type() != obj.llvmGlobal.Type().ElementType() { + if checks && initializer.Type() != obj.llvmGlobal.GlobalValueType() { panic("initializer type mismatch") } obj.llvmGlobal.SetInitializer(initializer) diff --git a/interp/interpreter.go b/interp/interpreter.go index 8c783a70..c438b4b6 100644 --- a/interp/interpreter.go +++ b/interp/interpreter.go @@ -655,7 +655,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent // GetElementPtr does pointer arithmetic, changing the offset of the // pointer into the underlying object. var offset uint64 - for i := 2; i < len(operands); i += 2 { + for i := 1; i < len(operands); i += 2 { index := operands[i].Uint() elementSize := operands[i+1].Uint() if int64(elementSize) < 0 { diff --git a/interp/memory.go b/interp/memory.go index 6a537bad..82ab716d 100644 --- a/interp/memory.go +++ b/interp/memory.go @@ -808,14 +808,17 @@ func (v rawValue) rawLLVMValue(mem *memoryView) (llvm.Value, error) { if err != nil { return llvm.Value{}, err } - elementType := field.Type().ElementType() - if elementType.TypeKind() == llvm.StructTypeKind { - // There are some special pointer types that should be used as a - // ptrtoint, so that they can be used in certain optimizations. - name := elementType.StructName() - if name == "runtime.typecodeID" || name == "runtime.funcValueWithSignature" { - uintptrType := ctx.IntType(int(mem.r.pointerSize) * 8) - field = llvm.ConstPtrToInt(field, uintptrType) + if !field.IsAGlobalVariable().IsNil() { + elementType := field.GlobalValueType() + if elementType.TypeKind() == llvm.StructTypeKind { + // There are some special pointer types that should be used + // as a ptrtoint, so that they can be used in certain + // optimizations. + name := elementType.StructName() + if name == "runtime.typecodeID" || name == "runtime.funcValueWithSignature" { + uintptrType := ctx.IntType(int(mem.r.pointerSize) * 8) + field = llvm.ConstPtrToInt(field, uintptrType) + } } } structFields = append(structFields, field) @@ -998,7 +1001,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) { ptr := llvmValue.Operand(0) index := llvmValue.Operand(1) numOperands := llvmValue.OperandsCount() - elementType := ptr.Type().ElementType() + elementType := llvmValue.GEPSourceElementType() totalOffset := r.targetData.TypeAllocSize(elementType) * index.ZExtValue() for i := 2; i < numOperands; i++ { indexValue := llvmValue.Operand(i) @@ -1173,7 +1176,7 @@ func (r *runner) getValue(llvmValue llvm.Value) value { r.globals[llvmValue] = index r.objects = append(r.objects, obj) 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() { obj.buffer = r.getValue(initializer) obj.constant = llvmValue.IsGlobalConstant() diff --git a/transform/allocs.go b/transform/allocs.go index af7c70b2..5be7df2d 100644 --- a/transform/allocs.go +++ b/transform/allocs.go @@ -124,7 +124,7 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, logger func(tok alloca.SetAlignment(alignment) // 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) store := builder.CreateStore(zero, alloca) store.SetAlignment(alignment) diff --git a/transform/gc.go b/transform/gc.go index 514fb1bf..e2d23987 100644 --- a/transform/gc.go +++ b/transform/gc.go @@ -18,7 +18,7 @@ func MakeGCStackSlots(mod llvm.Module) bool { stackChainStart := mod.NamedGlobal("runtime.stackChainStart") if !stackChainStart.IsNil() { stackChainStart.SetLinkage(llvm.InternalLinkage) - stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.Type().ElementType())) + stackChainStart.SetInitializer(llvm.ConstNull(stackChainStart.GlobalValueType())) stackChainStart.SetGlobalConstant(true) } return false @@ -96,7 +96,7 @@ func MakeGCStackSlots(mod llvm.Module) bool { return false } stackChainStart.SetLinkage(llvm.InternalLinkage) - stackChainStartType := stackChainStart.Type().ElementType() + stackChainStartType := stackChainStart.GlobalValueType() stackChainStart.SetInitializer(llvm.ConstNull(stackChainStartType)) // Iterate until runtime.trackPointer has no uses left. diff --git a/transform/interface-lowering.go b/transform/interface-lowering.go index f28443dc..9e2ffa90 100644 --- a/transform/interface-lowering.go +++ b/transform/interface-lowering.go @@ -423,7 +423,7 @@ func (p *lowerInterfacesPass) defineInterfaceImplementsFunc(fn llvm.Value, itf * func (p *lowerInterfacesPass) defineInterfaceMethodFunc(fn llvm.Value, itf *interfaceInfo, signature *signatureInfo) { context := fn.LastParam() actualType := llvm.PrevParam(context) - returnType := fn.Type().ElementType().ReturnType() + returnType := fn.GlobalValueType().ReturnType() context.SetName("context") actualType.SetName("actualType") fn.SetLinkage(llvm.InternalLinkage) diff --git a/transform/llvm.go b/transform/llvm.go index 17968f8a..7042b32d 100644 --- a/transform/llvm.go +++ b/transform/llvm.go @@ -66,7 +66,7 @@ func getGlobalBytes(global llvm.Value, builder llvm.Builder) []byte { // function used for creating reflection sidetables, for example. func replaceGlobalIntWithArray(mod llvm.Module, name string, buf interface{}) llvm.Value { 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{ llvm.ConstInt(mod.Context().Int32Type(), 0, false), llvm.ConstInt(mod.Context().Int32Type(), 0, false), diff --git a/transform/wasm-abi.go b/transform/wasm-abi.go index 064e38f4..83a16d85 100644 --- a/transform/wasm-abi.go +++ b/transform/wasm-abi.go @@ -50,7 +50,7 @@ func ExternalInt64AsPtr(mod llvm.Module, config *compileopts.Config) error { paramTypes := []llvm.Type{} // Check return type for 64-bit integer. - fnType := fn.Type().ElementType() + fnType := fn.GlobalValueType() returnType := fnType.ReturnType() if returnType == int64Type { hasInt64 = true