From 09ec846c9f3204837ae0695077f6e1359c545fe9 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Tue, 20 Sep 2022 23:26:49 +0200 Subject: [PATCH] all: replace llvm.Const* calls with builder.Create* calls A number of llvm.Const* functions (in particular extractvalue and insertvalue) were removed in LLVM 15, so we have to use a builder instead. This builder will create the same constant values, it simply uses a different API. --- compiler/asserts.go | 2 +- compiler/compiler.go | 23 ++++++++++++++++------- compiler/interface.go | 20 ++++++++++---------- compiler/interrupt.go | 8 +++++--- compiler/llvm.go | 2 +- interp/interpreter.go | 13 +++++++------ interp/memory.go | 8 ++++---- transform/gc.go | 2 +- transform/interface-lowering.go | 14 +++++++------- transform/interrupt.go | 7 ++++--- transform/llvm.go | 16 +++++++++------- transform/reflect.go | 32 +++++++++++++++++++------------- transform/rtcalls.go | 4 ++-- 13 files changed, 86 insertions(+), 65 deletions(-) diff --git a/compiler/asserts.go b/compiler/asserts.go index 8d9efdde..2a5265e9 100644 --- a/compiler/asserts.go +++ b/compiler/asserts.go @@ -145,7 +145,7 @@ func (b *builder) createChanBoundsCheck(elementSize uint64, bufSize llvm.Value, } // Make the maxBufSize actually the maximum allowed value (in number of // elements in the channel buffer). - maxBufSize = llvm.ConstUDiv(maxBufSize, llvm.ConstInt(b.uintptrType, elementSize, false)) + maxBufSize = b.CreateUDiv(maxBufSize, llvm.ConstInt(b.uintptrType, elementSize, false), "") // Make sure maxBufSize has the same type as bufSize. if maxBufSize.Type() != bufSize.Type() { diff --git a/compiler/compiler.go b/compiler/compiler.go index c93b2e56..3d29628c 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -63,6 +63,7 @@ type compilerContext struct { DumpSSA bool mod llvm.Module ctx llvm.Context + builder llvm.Builder // only used for constant operations dibuilder *llvm.DIBuilder cu llvm.Metadata difiles map[string]llvm.Metadata @@ -98,6 +99,7 @@ func newCompilerContext(moduleName string, machine llvm.TargetMachine, config *C } c.ctx = llvm.NewContext() + c.builder = c.ctx.NewBuilder() c.mod = c.ctx.NewModule(moduleName) c.mod.SetTarget(config.Triple) c.mod.SetDataLayout(c.targetData.String()) @@ -126,6 +128,12 @@ func newCompilerContext(moduleName string, machine llvm.TargetMachine, config *C return c } +// Dispose everything related to the context, _except_ for the IR module (and +// the associated context). +func (c *compilerContext) dispose() { + c.builder.Dispose() +} + // builder contains all information relevant to build a single function. type builder struct { *compilerContext @@ -256,6 +264,7 @@ func Sizes(machine llvm.TargetMachine) types.Sizes { // CompilePackage compiles a single package to a LLVM module. func CompilePackage(moduleName string, pkg *loader.Package, ssaPkg *ssa.Package, machine llvm.TargetMachine, config *Config, dumpSSA bool) (llvm.Module, []error) { c := newCompilerContext(moduleName, machine, config, dumpSSA) + defer c.dispose() c.packageDir = pkg.OriginalDir() c.embedGlobals = pkg.EmbedGlobals c.pkg = pkg.Pkg @@ -972,10 +981,10 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global, global llvm.Valu for _, file := range allFiles { fileStruct := llvm.ConstNull(embedFileStructType) name := c.createConst(ssa.NewConst(constant.MakeString(file.Name), types.Typ[types.String])) - fileStruct = llvm.ConstInsertValue(fileStruct, name, []uint32{0}) // "name" field + fileStruct = c.builder.CreateInsertValue(fileStruct, name, 0, "") // "name" field if file.Hash != "" { data := c.getEmbedFileString(file) - fileStruct = llvm.ConstInsertValue(fileStruct, data, []uint32{1}) // "data" field + fileStruct = c.builder.CreateInsertValue(fileStruct, data, 1, "") // "data" field } fileStructs = append(fileStructs, fileStruct) } @@ -1006,7 +1015,7 @@ func (c *compilerContext) createEmbedGlobal(member *ssa.Global, global llvm.Valu // Define the embed.FS struct. It has only one field: the files (as a // *[]embed.file). globalInitializer := llvm.ConstNull(c.getLLVMType(member.Type().(*types.Pointer).Elem())) - globalInitializer = llvm.ConstInsertValue(globalInitializer, sliceGlobal, []uint32{0}) + globalInitializer = c.builder.CreateInsertValue(globalInitializer, sliceGlobal, 0, "") global.SetInitializer(globalInitializer) global.SetVisibility(llvm.HiddenVisibility) global.SetAlignment(c.targetData.ABITypeAlignment(globalInitializer.Type())) @@ -2757,15 +2766,15 @@ func (c *compilerContext) createConst(expr *ssa.Const) llvm.Value { r := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float32])) i := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float32])) cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.FloatType(), c.ctx.FloatType()}, false)) - cplx = llvm.ConstInsertValue(cplx, r, []uint32{0}) - cplx = llvm.ConstInsertValue(cplx, i, []uint32{1}) + cplx = c.builder.CreateInsertValue(cplx, r, 0, "") + cplx = c.builder.CreateInsertValue(cplx, i, 1, "") return cplx } else if typ.Kind() == types.Complex128 { r := c.createConst(ssa.NewConst(constant.Real(expr.Value), types.Typ[types.Float64])) i := c.createConst(ssa.NewConst(constant.Imag(expr.Value), types.Typ[types.Float64])) cplx := llvm.Undef(c.ctx.StructType([]llvm.Type{c.ctx.DoubleType(), c.ctx.DoubleType()}, false)) - cplx = llvm.ConstInsertValue(cplx, r, []uint32{0}) - cplx = llvm.ConstInsertValue(cplx, i, []uint32{1}) + cplx = c.builder.CreateInsertValue(cplx, r, 0, "") + cplx = c.builder.CreateInsertValue(cplx, i, 1, "") return cplx } else { panic("unknown constant of basic type: " + expr.String()) diff --git a/compiler/interface.go b/compiler/interface.go index acb474f5..106c327a 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -88,20 +88,20 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { } globalValue := llvm.ConstNull(global.Type().ElementType()) if !references.IsNil() { - globalValue = llvm.ConstInsertValue(globalValue, references, []uint32{0}) + globalValue = c.builder.CreateInsertValue(globalValue, references, 0, "") } if length != 0 { lengthValue := llvm.ConstInt(c.uintptrType, uint64(length), false) - globalValue = llvm.ConstInsertValue(globalValue, lengthValue, []uint32{1}) + globalValue = c.builder.CreateInsertValue(globalValue, lengthValue, 1, "") } if !methodSet.IsNil() { - globalValue = llvm.ConstInsertValue(globalValue, methodSet, []uint32{2}) + globalValue = c.builder.CreateInsertValue(globalValue, methodSet, 2, "") } if !ptrTo.IsNil() { - globalValue = llvm.ConstInsertValue(globalValue, ptrTo, []uint32{3}) + globalValue = c.builder.CreateInsertValue(globalValue, ptrTo, 3, "") } if !typeAssert.IsNil() { - globalValue = llvm.ConstInsertValue(globalValue, typeAssert, []uint32{4}) + globalValue = c.builder.CreateInsertValue(globalValue, typeAssert, 4, "") } global.SetInitializer(globalValue) global.SetLinkage(llvm.LinkOnceODRLinkage) @@ -121,7 +121,7 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value { structGlobalValue := llvm.ConstNull(structGlobalType) for i := 0; i < typ.NumFields(); i++ { fieldGlobalValue := llvm.ConstNull(runtimeStructField) - fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, c.getTypeCode(typ.Field(i).Type()), []uint32{0}) + fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, c.getTypeCode(typ.Field(i).Type()), 0, "") fieldNameType, fieldName := c.makeGlobalArray([]byte(typ.Field(i).Name()), "reflect/types.structFieldName", c.ctx.Int8Type()) fieldName.SetLinkage(llvm.PrivateLinkage) fieldName.SetUnnamedAddr(true) @@ -129,7 +129,7 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value { llvm.ConstInt(c.ctx.Int32Type(), 0, false), llvm.ConstInt(c.ctx.Int32Type(), 0, false), }) - fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, fieldName, []uint32{1}) + fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, fieldName, 1, "") if typ.Tag(i) != "" { fieldTagType, fieldTag := c.makeGlobalArray([]byte(typ.Tag(i)), "reflect/types.structFieldTag", c.ctx.Int8Type()) fieldTag.SetLinkage(llvm.PrivateLinkage) @@ -138,13 +138,13 @@ func (c *compilerContext) makeStructTypeFields(typ *types.Struct) llvm.Value { llvm.ConstInt(c.ctx.Int32Type(), 0, false), llvm.ConstInt(c.ctx.Int32Type(), 0, false), }) - fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, fieldTag, []uint32{2}) + fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, fieldTag, 2, "") } if typ.Field(i).Embedded() { fieldEmbedded := llvm.ConstInt(c.ctx.Int1Type(), 1, false) - fieldGlobalValue = llvm.ConstInsertValue(fieldGlobalValue, fieldEmbedded, []uint32{3}) + fieldGlobalValue = c.builder.CreateInsertValue(fieldGlobalValue, fieldEmbedded, 3, "") } - structGlobalValue = llvm.ConstInsertValue(structGlobalValue, fieldGlobalValue, []uint32{uint32(i)}) + structGlobalValue = c.builder.CreateInsertValue(structGlobalValue, fieldGlobalValue, i, "") } structGlobal.SetInitializer(structGlobalValue) structGlobal.SetUnnamedAddr(true) diff --git a/compiler/interrupt.go b/compiler/interrupt.go index 45c7d074..c1f7d69f 100644 --- a/compiler/interrupt.go +++ b/compiler/interrupt.go @@ -49,9 +49,11 @@ func (b *builder) createInterruptGlobal(instr *ssa.CallCommon) (llvm.Value, erro global.SetGlobalConstant(true) global.SetUnnamedAddr(true) initializer := llvm.ConstNull(globalLLVMType) - initializer = llvm.ConstInsertValue(initializer, funcContext, []uint32{0}) - initializer = llvm.ConstInsertValue(initializer, funcPtr, []uint32{1}) - initializer = llvm.ConstInsertValue(initializer, llvm.ConstInt(b.intType, uint64(id.Int64()), true), []uint32{2, 0}) + initializer = b.CreateInsertValue(initializer, funcContext, 0, "") + initializer = b.CreateInsertValue(initializer, funcPtr, 1, "") + initializer = b.CreateInsertValue(initializer, llvm.ConstNamedStruct(globalLLVMType.StructElementTypes()[2], []llvm.Value{ + llvm.ConstInt(b.intType, uint64(id.Int64()), true), + }), 2, "") global.SetInitializer(initializer) // Add debug info to the interrupt global. diff --git a/compiler/llvm.go b/compiler/llvm.go index 686d4d2b..8b80869b 100644 --- a/compiler/llvm.go +++ b/compiler/llvm.go @@ -70,7 +70,7 @@ func (c *compilerContext) makeGlobalArray(buf []byte, name string, elementType l value := llvm.Undef(globalType) for i := 0; i < len(buf); i++ { ch := uint64(buf[i]) - value = llvm.ConstInsertValue(value, llvm.ConstInt(elementType, ch, false), []uint32{uint32(i)}) + value = c.builder.CreateInsertValue(value, llvm.ConstInt(elementType, ch, false), i, "") } global.SetInitializer(value) return globalType, global diff --git a/interp/interpreter.go b/interp/interpreter.go index 2c7fd8c3..d029aa33 100644 --- a/interp/interpreter.go +++ b/interp/interpreter.go @@ -408,7 +408,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent // Elem() is only valid for certain type classes. switch class { case "chan", "pointer", "slice", "array": - elementType := llvm.ConstExtractValue(typecodeID.Initializer(), []uint32{0}) + elementType := r.builder.CreateExtractValue(typecodeID.Initializer(), 0, "") uintptrType := r.mod.Context().IntType(int(mem.r.pointerSize) * 8) locals[inst.localIndex] = r.getValue(llvm.ConstPtrToInt(elementType, uintptrType)) default: @@ -461,8 +461,8 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent // easier checking in the next step. concreteTypeMethods := map[string]struct{}{} for i := 0; i < methodSet.Type().ArrayLength(); i++ { - methodInfo := llvm.ConstExtractValue(methodSet, []uint32{uint32(i)}) - name := llvm.ConstExtractValue(methodInfo, []uint32{0}).Name() + methodInfo := r.builder.CreateExtractValue(methodSet, i, "") + name := r.builder.CreateExtractValue(methodInfo, 0, "").Name() concreteTypeMethods[name] = struct{}{} } @@ -496,7 +496,7 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent typecodeID := typecodeIDBitCast.Operand(0).Initializer() // Load the method set, which is part of the typecodeID object. - methodSet := llvm.ConstExtractValue(typecodeID, []uint32{2}).Operand(0).Initializer() + methodSet := r.builder.CreateExtractValue(typecodeID, 2, "").Operand(0).Initializer() // We don't need to load the interface method set. @@ -511,9 +511,10 @@ func (r *runner) run(fn *function, params []value, parentMem *memoryView, indent numMethods := methodSet.Type().ArrayLength() var method llvm.Value for i := 0; i < numMethods; i++ { - methodSignature := llvm.ConstExtractValue(methodSet, []uint32{uint32(i), 0}) + methodSignatureAgg := r.builder.CreateExtractValue(methodSet, i, "") + methodSignature := r.builder.CreateExtractValue(methodSignatureAgg, 0, "") if methodSignature == signature { - method = llvm.ConstExtractValue(methodSet, []uint32{uint32(i), 1}).Operand(0) + method = r.builder.CreateExtractValue(methodSignatureAgg, 1, "").Operand(0) } } if method.IsNil() { diff --git a/interp/memory.go b/interp/memory.go index 2fa6f5cb..583f9355 100644 --- a/interp/memory.go +++ b/interp/memory.go @@ -215,7 +215,7 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) error { case llvm.StructTypeKind: numElements := llvmType.StructElementTypesCount() for i := 0; i < numElements; i++ { - element := llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)}) + element := mv.r.builder.CreateExtractValue(llvmValue, i, "") err := mv.markExternal(element, mark) if err != nil { return err @@ -224,7 +224,7 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) error { case llvm.ArrayTypeKind: numElements := llvmType.ArrayLength() for i := 0; i < numElements; i++ { - element := llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)}) + element := mv.r.builder.CreateExtractValue(llvmValue, i, "") err := mv.markExternal(element, mark) if err != nil { return err @@ -1074,7 +1074,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) { field := rawValue{ buf: v.buf[offset:], } - field.set(llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)}), r) + field.set(r.builder.CreateExtractValue(llvmValue, i, ""), r) } case llvm.ArrayTypeKind: numElements := llvmType.ArrayLength() @@ -1085,7 +1085,7 @@ func (v *rawValue) set(llvmValue llvm.Value, r *runner) { field := rawValue{ buf: v.buf[offset:], } - field.set(llvm.ConstExtractValue(llvmValue, []uint32{uint32(i)}), r) + field.set(r.builder.CreateExtractValue(llvmValue, i, ""), r) } case llvm.DoubleTypeKind: f, _ := llvmValue.DoubleValue() diff --git a/transform/gc.go b/transform/gc.go index 3870a6b6..514fb1bf 100644 --- a/transform/gc.go +++ b/transform/gc.go @@ -218,7 +218,7 @@ func MakeGCStackSlots(mod llvm.Module) bool { initialStackObject := llvm.ConstNull(stackObjectType) numSlots := (targetData.TypeAllocSize(stackObjectType) - uint64(targetData.PointerSize())*2) / uint64(targetData.ABITypeAlignment(uintptrType)) numSlotsValue := llvm.ConstInt(uintptrType, numSlots, false) - initialStackObject = llvm.ConstInsertValue(initialStackObject, numSlotsValue, []uint32{1}) + initialStackObject = builder.CreateInsertValue(initialStackObject, numSlotsValue, 1, "") builder.CreateStore(initialStackObject, stackObject) // Update stack start. diff --git a/transform/interface-lowering.go b/transform/interface-lowering.go index f5b29e30..f28443dc 100644 --- a/transform/interface-lowering.go +++ b/transform/interface-lowering.go @@ -154,7 +154,7 @@ func (p *lowerInterfacesPass) run() error { if initializer.IsNil() { continue } - methodSet := llvm.ConstExtractValue(initializer, []uint32{2}) + methodSet := p.builder.CreateExtractValue(initializer, 2, "") p.addTypeMethods(t, methodSet) } } @@ -288,9 +288,9 @@ func (p *lowerInterfacesPass) run() error { zeroUintptr := llvm.ConstNull(p.uintptrType) for _, t := range p.types { initializer := t.typecode.Initializer() - methodSet := llvm.ConstExtractValue(initializer, []uint32{2}) - initializer = llvm.ConstInsertValue(initializer, llvm.ConstNull(methodSet.Type()), []uint32{2}) - initializer = llvm.ConstInsertValue(initializer, zeroUintptr, []uint32{4}) + methodSet := p.builder.CreateExtractValue(initializer, 2, "") + initializer = p.builder.CreateInsertValue(initializer, llvm.ConstNull(methodSet.Type()), 2, "") + initializer = p.builder.CreateInsertValue(initializer, zeroUintptr, 4, "") t.typecode.SetInitializer(initializer) } @@ -311,10 +311,10 @@ func (p *lowerInterfacesPass) addTypeMethods(t *typeInfo, methodSet llvm.Value) t.methodSet = methodSet set := methodSet.Initializer() // get value from global for i := 0; i < set.Type().ArrayLength(); i++ { - methodData := llvm.ConstExtractValue(set, []uint32{uint32(i)}) - signatureGlobal := llvm.ConstExtractValue(methodData, []uint32{0}) + methodData := p.builder.CreateExtractValue(set, i, "") + signatureGlobal := p.builder.CreateExtractValue(methodData, 0, "") signatureName := signatureGlobal.Name() - function := llvm.ConstExtractValue(methodData, []uint32{1}).Operand(0) + function := p.builder.CreateExtractValue(methodData, 1, "").Operand(0) signature := p.getSignature(signatureName) method := &methodInfo{ function: function, diff --git a/transform/interrupt.go b/transform/interrupt.go index 2c301be0..b15ff8a9 100644 --- a/transform/interrupt.go +++ b/transform/interrupt.go @@ -44,7 +44,8 @@ func LowerInterrupts(mod llvm.Module) []error { // Get the interrupt number from the initializer initializer := global.Initializer() - num := llvm.ConstExtractValue(initializer, []uint32{2, 0}).SExtValue() + interrupt := builder.CreateExtractValue(initializer, 2, "") + num := builder.CreateExtractValue(interrupt, 0, "").SExtValue() pkg := packageFromInterruptHandle(global) handles, exists := handleMap[num] @@ -89,8 +90,8 @@ func LowerInterrupts(mod llvm.Module) []error { builder.SetInsertPointBefore(call) for _, handler := range handlers { initializer := handler.Initializer() - context := llvm.ConstExtractValue(initializer, []uint32{0}) - funcPtr := llvm.ConstExtractValue(initializer, []uint32{1}).Operand(0) + context := builder.CreateExtractValue(initializer, 0, "") + funcPtr := builder.CreateExtractValue(initializer, 1, "").Operand(0) builder.CreateCall(funcPtr.GlobalValueType(), funcPtr, []llvm.Value{ num, context, diff --git a/transform/llvm.go b/transform/llvm.go index 6716dd63..17968f8a 100644 --- a/transform/llvm.go +++ b/transform/llvm.go @@ -36,25 +36,27 @@ func hasUses(value llvm.Value) bool { // linkage/constant/etc properties yourself. func makeGlobalArray(mod llvm.Module, bufItf interface{}, name string, elementType llvm.Type) (llvm.Type, llvm.Value) { buf := reflect.ValueOf(bufItf) - globalType := llvm.ArrayType(elementType, buf.Len()) - global := llvm.AddGlobal(mod, globalType, name) - value := llvm.Undef(globalType) + var values []llvm.Value for i := 0; i < buf.Len(); i++ { ch := buf.Index(i).Uint() - value = llvm.ConstInsertValue(value, llvm.ConstInt(elementType, ch, false), []uint32{uint32(i)}) + values = append(values, llvm.ConstInt(elementType, ch, false)) } + value := llvm.ConstArray(elementType, values) + global := llvm.AddGlobal(mod, value.Type(), name) global.SetInitializer(value) - return globalType, global + return value.Type(), global } // getGlobalBytes returns the slice contained in the array of the provided // global. It can recover the bytes originally created using makeGlobalArray, if // makeGlobalArray was given a byte slice. -func getGlobalBytes(global llvm.Value) []byte { +// +// The builder parameter is only used for constant operations. +func getGlobalBytes(global llvm.Value, builder llvm.Builder) []byte { value := global.Initializer() buf := make([]byte, value.Type().ArrayLength()) for i := range buf { - buf[i] = byte(llvm.ConstExtractValue(value, []uint32{uint32(i)}).ZExtValue()) + buf[i] = byte(builder.CreateExtractValue(value, i, "").ZExtValue()) } return buf } diff --git a/transform/reflect.go b/transform/reflect.go index fd70ccb7..68beba9b 100644 --- a/transform/reflect.go +++ b/transform/reflect.go @@ -76,6 +76,10 @@ var nonBasicTypes = map[string]int64{ // typeCodeAssignmentState keeps some global state around for type code // assignments, used to assign one unique type code to each Go type. type typeCodeAssignmentState struct { + // Builder used purely for constant operations (because LLVM 15 removed many + // llvm.Const* functions). + builder llvm.Builder + // An integer that's incremented each time it's used to give unique IDs to // type codes that are not yet fully supported otherwise by the reflect // package (or are simply unused in the compiled program). @@ -165,6 +169,7 @@ func LowerReflect(mod llvm.Module) { defer targetData.Dispose() uintptrType := mod.Context().IntType(targetData.PointerSize() * 8) state := typeCodeAssignmentState{ + builder: mod.Context().NewBuilder(), fallbackIndex: 1, uintptrLen: targetData.PointerSize() * 8, namedBasicTypes: make(map[string]int), @@ -177,6 +182,7 @@ func LowerReflect(mod llvm.Module) { needsStructNamesSidetable: len(getUses(mod.NamedGlobal("reflect.structNamesSidetable"))) != 0, needsArrayTypesSidetable: len(getUses(mod.NamedGlobal("reflect.arrayTypesSidetable"))) != 0, } + defer state.builder.Dispose() for _, t := range types { num := state.getTypeCodeNum(t.typecode) if num.BitLen() > state.uintptrLen || !num.IsUint64() { @@ -238,7 +244,7 @@ func LowerReflect(mod llvm.Module) { // It also cleans up the IR for testing. for _, typ := range types { initializer := typ.typecode.Initializer() - references := llvm.ConstExtractValue(initializer, []uint32{0}) + references := state.builder.CreateExtractValue(initializer, 0, "") typ.typecode.SetInitializer(llvm.ConstNull(initializer.Type())) if strings.HasPrefix(typ.name, "reflect/types.type:struct:") { // Structs have a 'references' field that is not a typecode but @@ -260,7 +266,7 @@ func (state *typeCodeAssignmentState) getTypeCodeNum(typecode llvm.Value) *big.I name := "" if class == "named" { name = value - typecode = llvm.ConstExtractValue(typecode.Initializer(), []uint32{0}) + typecode = state.builder.CreateExtractValue(typecode.Initializer(), 0, "") class, value = getClassAndValueFromTypeCode(typecode) } if class == "basic" { @@ -344,7 +350,7 @@ func (state *typeCodeAssignmentState) getNonBasicTypeCode(class string, typecode switch class { case "chan", "pointer", "slice": // Prefix-style type kinds. The upper bits contain the element type. - sub := llvm.ConstExtractValue(typecode.Initializer(), []uint32{0}) + sub := state.builder.CreateExtractValue(typecode.Initializer(), 0, "") return state.getTypeCodeNum(sub) case "array": // An array is basically a pair of (typecode, length) stored in a @@ -416,7 +422,7 @@ func (state *typeCodeAssignmentState) getArrayTypeNum(typecode llvm.Value) int { return num } - elemTypeCode := llvm.ConstExtractValue(typecode.Initializer(), []uint32{0}) + elemTypeCode := state.builder.CreateExtractValue(typecode.Initializer(), 0, "") elemTypeNum := state.getTypeCodeNum(elemTypeCode) if elemTypeNum.BitLen() > state.uintptrLen || !elemTypeNum.IsUint64() { // TODO: make this a regular error @@ -424,7 +430,7 @@ func (state *typeCodeAssignmentState) getArrayTypeNum(typecode llvm.Value) int { } // The array side table is a sequence of {element type, array length}. - arrayLength := llvm.ConstExtractValue(typecode.Initializer(), []uint32{1}).ZExtValue() + arrayLength := state.builder.CreateExtractValue(typecode.Initializer(), 1, "").ZExtValue() buf := makeVarint(elemTypeNum.Uint64()) buf = append(buf, makeVarint(arrayLength)...) @@ -454,7 +460,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode llvm.Value) int // Get the fields this struct type contains. // The struct number will be the start index of - structTypeGlobal := llvm.ConstExtractValue(typecode.Initializer(), []uint32{0}).Operand(0).Initializer() + structTypeGlobal := state.builder.CreateExtractValue(typecode.Initializer(), 0, "").Operand(0).Initializer() numFields := structTypeGlobal.Type().ArrayLength() // The first data that is stored in the struct sidetable is the number of @@ -471,28 +477,28 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode llvm.Value) int // the sidetable bigger. for i := 0; i < numFields; i++ { // Collect some information about this field. - field := llvm.ConstExtractValue(structTypeGlobal, []uint32{uint32(i)}) + field := state.builder.CreateExtractValue(structTypeGlobal, i, "") - nameGlobal := llvm.ConstExtractValue(field, []uint32{1}) + nameGlobal := state.builder.CreateExtractValue(field, 1, "") if nameGlobal == llvm.ConstPointerNull(nameGlobal.Type()) { panic("compiler: no name for this struct field") } - fieldNameBytes := getGlobalBytes(nameGlobal.Operand(0)) + fieldNameBytes := getGlobalBytes(nameGlobal.Operand(0), state.builder) fieldNameNumber := state.getStructNameNumber(fieldNameBytes) // See whether this struct field has an associated tag, and if so, // store that tag in the tags sidetable. - tagGlobal := llvm.ConstExtractValue(field, []uint32{2}) + tagGlobal := state.builder.CreateExtractValue(field, 2, "") hasTag := false tagNumber := 0 if tagGlobal != llvm.ConstPointerNull(tagGlobal.Type()) { hasTag = true - tagBytes := getGlobalBytes(tagGlobal.Operand(0)) + tagBytes := getGlobalBytes(tagGlobal.Operand(0), state.builder) tagNumber = state.getStructNameNumber(tagBytes) } // The 'embedded' or 'anonymous' flag for this field. - embedded := llvm.ConstExtractValue(field, []uint32{3}).ZExtValue() != 0 + embedded := state.builder.CreateExtractValue(field, 3, "").ZExtValue() != 0 // The first byte in the struct types sidetable is a flags byte with // two bits in it. @@ -510,7 +516,7 @@ func (state *typeCodeAssignmentState) getStructTypeNum(typecode llvm.Value) int // Get the type number and add it to the buffer. // All fields have a type, so include it directly here. - typeNum := state.getTypeCodeNum(llvm.ConstExtractValue(field, []uint32{0})) + typeNum := state.getTypeCodeNum(state.builder.CreateExtractValue(field, 0, "")) if typeNum.BitLen() > state.uintptrLen || !typeNum.IsUint64() { // TODO: make this a regular error panic("struct field has a type code that is too big") diff --git a/transform/rtcalls.go b/transform/rtcalls.go index 2f17f815..d70bc626 100644 --- a/transform/rtcalls.go +++ b/transform/rtcalls.go @@ -149,7 +149,7 @@ func OptimizeReflectImplements(mod llvm.Module) { interfaceType := interfaceTypeBitCast.Operand(0) if strings.HasPrefix(interfaceType.Name(), "reflect/types.type:named:") { // Get the underlying type. - interfaceType = llvm.ConstExtractValue(interfaceType.Initializer(), []uint32{0}) + interfaceType = builder.CreateExtractValue(interfaceType.Initializer(), 0, "") } if !strings.HasPrefix(interfaceType.Name(), "reflect/types.type:interface:") { // This is an error. The Type passed to Implements should be of @@ -161,7 +161,7 @@ func OptimizeReflectImplements(mod llvm.Module) { // Interface is unknown at compile time. This can't be optimized. continue } - typeAssertFunction := llvm.ConstExtractValue(interfaceType.Initializer(), []uint32{4}).Operand(0) + typeAssertFunction := builder.CreateExtractValue(interfaceType.Initializer(), 4, "").Operand(0) // Replace Implements call with the type assert call. builder.SetInsertPointBefore(call)