Index: cmd/gllgo/gllgo.go =================================================================== --- cmd/gllgo/gllgo.go +++ cmd/gllgo/gllgo.go @@ -154,16 +154,21 @@ } func (san *sanitizerOptions) getAttribute() llvm.Attribute { + var attrKind uint + switch { case san.address: - return llvm.SanitizeAddressAttribute + attrKind = llvm.AttributeKindID("sanitize_address") case san.thread: - return llvm.SanitizeThreadAttribute + attrKind = llvm.AttributeKindID("sanitize_thread") case san.memory: - return llvm.SanitizeMemoryAttribute + attrKind = llvm.AttributeKindID("sanitize_memory") default: - return 0 + attrKind = 0 } + + ctx := llvm.GlobalContext() + return ctx.CreateEnumAttribute(attrKind, 0) } type driverOptions struct { Index: irgen/attribute.go =================================================================== --- irgen/attribute.go +++ irgen/attribute.go @@ -148,25 +148,27 @@ for _, field := range strings.Fields(value) { switch strings.ToLower(field) { case "noreturn": - result |= llvmAttribute(llvm.NoReturnAttribute) case "nounwind": - result |= llvmAttribute(llvm.NoUnwindAttribute) case "noinline": - result |= llvmAttribute(llvm.NoInlineAttribute) case "alwaysinline": - result |= llvmAttribute(llvm.AlwaysInlineAttribute) + kind := llvm.AttributeKindID(strings.ToLower(field)) + result.AttrKinds = append(result.AttrKinds, kind) } } return result } -type llvmAttribute llvm.Attribute +type llvmAttribute struct { + AttrKinds []uint +} func (a llvmAttribute) Apply(v llvm.Value) { + ctx := v.GlobalParent().Context() if !v.IsAFunction().IsNil() { - v.AddFunctionAttr(llvm.Attribute(a)) - } else { - v.AddAttribute(llvm.Attribute(a)) + for _, kind := range a.AttrKinds { + attr := ctx.CreateEnumAttribute(kind, 0) + v.AddFunctionAttr(attr) + } } } Index: irgen/cabi.go =================================================================== --- irgen/cabi.go +++ irgen/cabi.go @@ -249,6 +249,7 @@ switch bt := bt.(type) { case *structBType, *arrayBType: + noneAttr := tm.ctx.CreateEnumAttribute(0, 0) bo := tm.getBackendOffsets(bt) sp := 0 for sp != len(bo) && bo[sp].offset < 8 { @@ -258,21 +259,23 @@ eb2 := bo[sp:] if len(eb2) > 0 { argTypes = append(argTypes, tm.classifyEightbyte(eb1, &numInt, &numSSE), tm.classifyEightbyte(eb2, &numInt, &numSSE)) - argAttrs = append(argAttrs, 0, 0) + argAttrs = append(argAttrs, noneAttr, noneAttr) } else { argTypes = append(argTypes, tm.classifyEightbyte(eb1, &numInt, &numSSE)) - argAttrs = append(argAttrs, 0) + argAttrs = append(argAttrs, noneAttr) } return argTypes, argAttrs, numInt, numSSE case *intBType: if bt.width < 4 { + var argAttrKind uint if bt.signed { - argAttr = llvm.SExtAttribute + argAttrKind = llvm.AttributeKindID("signext") } else { - argAttr = llvm.ZExtAttribute + argAttrKind = llvm.AttributeKindID("zeroext") } + argAttr = tm.ctx.CreateEnumAttribute(argAttrKind, 0) } } @@ -516,10 +519,12 @@ func (fi *functionTypeInfo) declare(m llvm.Module, name string) llvm.Value { fn := llvm.AddFunction(m, name, fi.functionType) - fn.AddFunctionAttr(fi.retAttr) + if fi.retAttr.GetEnumKind() != 0 { + fn.AddAttributeAtIndex(0, fi.retAttr) + } for i, a := range fi.argAttrs { - if a != 0 { - fn.Param(i).AddAttribute(a) + if a.GetEnumKind() != 0 { + fn.AddAttributeAtIndex(i + 1, a) } } return fn @@ -537,9 +542,13 @@ fi.retInf.prepare(ctx, allocaBuilder, callArgs) typedCallee := builder.CreateBitCast(callee, llvm.PointerType(fi.functionType, 0), "") call := builder.CreateCall(typedCallee, callArgs, "") - call.AddInstrAttribute(0, fi.retAttr) + if fi.retAttr.GetEnumKind() != 0 { + call.AddCallSiteAttribute(0, fi.retAttr) + } for i, a := range fi.argAttrs { - call.AddInstrAttribute(i+1, a) + if a.GetEnumKind() != 0 { + call.AddCallSiteAttribute(i + 1, a) + } } return fi.retInf.decode(ctx, allocaBuilder, builder, call) } @@ -556,9 +565,13 @@ fi.retInf.prepare(ctx, allocaBuilder, callArgs) typedCallee := builder.CreateBitCast(callee, llvm.PointerType(fi.functionType, 0), "") call := builder.CreateInvoke(typedCallee, callArgs, cont, lpad, "") - call.AddInstrAttribute(0, fi.retAttr) + if fi.retAttr.GetEnumKind() != 0 { + call.AddCallSiteAttribute(0, fi.retAttr) + } for i, a := range fi.argAttrs { - call.AddInstrAttribute(i+1, a) + if a.GetEnumKind() != 0 { + call.AddCallSiteAttribute(i + 1, a) + } } builder.SetInsertPointAtEnd(cont) return fi.retInf.decode(ctx, allocaBuilder, builder, call) @@ -567,6 +580,7 @@ func (tm *llvmTypeMap) getFunctionTypeInfo(args []types.Type, results []types.Type) (fi functionTypeInfo) { var returnType llvm.Type var argTypes []llvm.Type + var argAttrKind uint if len(results) == 0 { returnType = llvm.VoidType() fi.retInf = &directRetInfo{} @@ -609,7 +623,8 @@ case AIK_Indirect: returnType = llvm.VoidType() argTypes = []llvm.Type{llvm.PointerType(resultsType, 0)} - fi.argAttrs = []llvm.Attribute{llvm.StructRetAttribute} + argAttrKind = llvm.AttributeKindID("sret") + fi.argAttrs = []llvm.Attribute{tm.ctx.CreateEnumAttribute(argAttrKind, 0)} fi.retInf = &indirectRetInfo{numResults: len(results), resultsType: resultsType} } } @@ -617,7 +632,8 @@ // Allocate an argument for the call chain. fi.chainIndex = len(argTypes) argTypes = append(argTypes, llvm.PointerType(tm.ctx.Int8Type(), 0)) - fi.argAttrs = append(fi.argAttrs, llvm.NestAttribute) + argAttrKind = llvm.AttributeKindID("nest") + fi.argAttrs = append(fi.argAttrs, tm.ctx.CreateEnumAttribute(argAttrKind, 0)) // Keep track of the number of INTEGER/SSE class registers remaining. remainingInt := 6 @@ -651,7 +667,8 @@ if !isDirect { fi.argInfos = append(fi.argInfos, &indirectArgInfo{len(argTypes)}) argTypes = append(argTypes, llvm.PointerType(tm.ToLLVM(arg), 0)) - fi.argAttrs = append(fi.argAttrs, llvm.ByValAttribute) + argAttrKind = llvm.AttributeKindID("byval") + fi.argAttrs = append(fi.argAttrs, tm.ctx.CreateEnumAttribute(argAttrKind, 0)) } } Index: irgen/compiler.go =================================================================== --- irgen/compiler.go +++ irgen/compiler.go @@ -156,8 +156,8 @@ func (c *compiler) addCommonFunctionAttrs(fn llvm.Value) { fn.AddTargetDependentFunctionAttr("disable-tail-calls", "true") fn.AddTargetDependentFunctionAttr("split-stack", "") - if attr := c.SanitizerAttribute; attr != 0 { - fn.AddFunctionAttr(attr) + if c.SanitizerAttribute.GetEnumKind() != 0 { + fn.AddFunctionAttr(c.SanitizerAttribute) } } Index: irgen/maps.go =================================================================== --- irgen/maps.go +++ irgen/maps.go @@ -39,8 +39,10 @@ pk := fr.allocaBuilder.CreateAlloca(llk.Type(), "") fr.builder.CreateStore(llk, pk) valptr := fr.runtime.mapIndex.call(fr, m.value, pk, boolLLVMValue(false))[0] - valptr.AddInstrAttribute(2, llvm.NoCaptureAttribute) - valptr.AddInstrAttribute(2, llvm.ReadOnlyAttribute) + attrkind := llvm.AttributeKindID("nocapture") + valptr.AddCallSiteAttribute(2, fr.types.ctx.CreateEnumAttribute(attrkind, 0)) + attrkind = llvm.AttributeKindID("readonly") + valptr.AddCallSiteAttribute(2, fr.types.ctx.CreateEnumAttribute(attrkind, 0)) okbit := fr.builder.CreateIsNotNull(valptr, "") elemtyp := m.Type().Underlying().(*types.Map).Elem() @@ -55,8 +57,10 @@ pk := fr.allocaBuilder.CreateAlloca(llk.Type(), "") fr.builder.CreateStore(llk, pk) valptr := fr.runtime.mapIndex.call(fr, m.value, pk, boolLLVMValue(true))[0] - valptr.AddInstrAttribute(2, llvm.NoCaptureAttribute) - valptr.AddInstrAttribute(2, llvm.ReadOnlyAttribute) + attrkind := llvm.AttributeKindID("nocapture") + valptr.AddCallSiteAttribute(2, fr.types.ctx.CreateEnumAttribute(attrkind, 0)) + attrkind = llvm.AttributeKindID("readonly") + valptr.AddCallSiteAttribute(2, fr.types.ctx.CreateEnumAttribute(attrkind, 0)) elemtyp := m.Type().Underlying().(*types.Map).Elem() llelemtyp := fr.types.ToLLVM(elemtyp) Index: irgen/runtime.go =================================================================== --- irgen/runtime.go +++ irgen/runtime.go @@ -145,6 +145,11 @@ ByteSlice := types.NewSlice(types.Typ[types.Byte]) IntSlice := types.NewSlice(types.Typ[types.Int]) + AttrKind := llvm.AttributeKindID("nounwind") + NoUnwindAttr := module.Context().CreateEnumAttribute(AttrKind, 0) + AttrKind = llvm.AttributeKindID("noreturn") + NoReturnAttr := module.Context().CreateEnumAttribute(AttrKind, 0) + for _, rt := range [...]struct { name string rfi *runtimeFnInfo @@ -168,7 +173,7 @@ rfi: &ri.byteArrayToString, args: []types.Type{UnsafePointer, Int}, res: []types.Type{String}, - attrs: []llvm.Attribute{llvm.NoUnwindAttribute}, + attrs: []llvm.Attribute{NoUnwindAttr}, }, { name: "__go_can_recover", @@ -314,7 +319,7 @@ rfi: &ri.New, args: []types.Type{UnsafePointer, Uintptr}, res: []types.Type{UnsafePointer}, - attrs: []llvm.Attribute{llvm.NoUnwindAttribute}, + attrs: []llvm.Attribute{NoUnwindAttr}, }, { name: "__go_new_channel", @@ -338,7 +343,7 @@ name: "__go_panic", rfi: &ri.panic, args: []types.Type{EmptyInterface}, - attrs: []llvm.Attribute{llvm.NoReturnAttribute}, + attrs: []llvm.Attribute{NoReturnAttr}, }, { name: "__go_print_bool", @@ -417,7 +422,7 @@ name: "__go_runtime_error", rfi: &ri.runtimeError, args: []types.Type{Int32}, - attrs: []llvm.Attribute{llvm.NoReturnAttribute}, + attrs: []llvm.Attribute{NoReturnAttr}, }, { name: "runtime.selectdefault", @@ -474,7 +479,7 @@ rfi: &ri.stringToByteArray, args: []types.Type{String}, res: []types.Type{ByteSlice}, - attrs: []llvm.Attribute{llvm.NoUnwindAttribute}, + attrs: []llvm.Attribute{NoUnwindAttr}, }, { name: "__go_string_to_int_array", Index: irgen/ssa.go =================================================================== --- irgen/ssa.go +++ irgen/ssa.go @@ -534,7 +534,9 @@ func (fr *frame) bridgeRecoverFunc(llfn llvm.Value, fti functionTypeInfo) *frame { // The bridging function must not be inlined, or the return address // may not correspond to the source function. - llfn.AddFunctionAttr(llvm.NoInlineAttribute) + attrKind := llvm.AttributeKindID("noinline") + noInlineAttr := fr.module.Context().CreateEnumAttribute(attrKind, 0) + llfn.AddFunctionAttr(noInlineAttr) // Call __go_can_recover, passing in the function's return address. entry := llvm.AddBasicBlock(llfn, "entry")