aboutsummaryrefslogtreecommitdiffhomepage
path: root/compiler
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2022-09-22 13:33:00 +0200
committerRon Evans <[email protected]>2022-10-19 22:23:19 +0200
commit62df1d7490ccf495dc08837ec72ee1d6042bc374 (patch)
tree379a9e4e5f46dc8293beeb3ba1f386f08bdf53c9 /compiler
parent229746b71ef8c6ab095f0e97aa722959c6f07268 (diff)
downloadtinygo-62df1d7490ccf495dc08837ec72ee1d6042bc374.tar.gz
tinygo-62df1d7490ccf495dc08837ec72ee1d6042bc374.zip
all: remove pointer ElementType calls
This is needed for opaque pointers, which are enabled by default in LLVM 15.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/asserts.go4
-rw-r--r--compiler/calls.go58
-rw-r--r--compiler/compiler.go15
-rw-r--r--compiler/func.go2
-rw-r--r--compiler/interface.go4
-rw-r--r--compiler/ircheck/check.go5
-rw-r--r--compiler/symbol.go15
7 files changed, 41 insertions, 62 deletions
diff --git a/compiler/asserts.go b/compiler/asserts.go
index 2a5265e93..ba4824943 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 b38d770f9..b122f0c8d 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 3d29628cd..fc47c29c1 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 c6a8802d7..4203fdf76 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 106c327a8..2007b7d7c 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 30c6ee172..e2b7ed510 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 83fe050bc..01b3fc377 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&paramIsDeferenceableOrNull == 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)
}
}