Index: bindings/go/llvm/ir.go =================================================================== --- bindings/go/llvm/ir.go +++ bindings/go/llvm/ir.go @@ -58,7 +58,9 @@ Metadata struct { C C.LLVMMetadataRef } - Attribute uint64 + Attribute struct { + C C.LLVMAttributeRef + } Opcode C.LLVMOpcode TypeKind C.LLVMTypeKind Linkage C.LLVMLinkage @@ -79,6 +81,7 @@ func (c MemoryBuffer) IsNil() bool { return c.C == nil } func (c PassManager) IsNil() bool { return c.C == nil } func (c Use) IsNil() bool { return c.C == nil } +func (c Attribute) IsNil() bool { return c.C == nil } // helpers func llvmTypeRefPtr(t *Type) *C.LLVMTypeRef { return (*C.LLVMTypeRef)(unsafe.Pointer(t)) } @@ -115,56 +118,6 @@ } //------------------------------------------------------------------------- -// llvm.Attribute -//------------------------------------------------------------------------- - -const ( - NoneAttribute Attribute = 0 - ZExtAttribute Attribute = C.LLVMZExtAttribute - SExtAttribute Attribute = C.LLVMSExtAttribute - NoReturnAttribute Attribute = C.LLVMNoReturnAttribute - InRegAttribute Attribute = C.LLVMInRegAttribute - StructRetAttribute Attribute = C.LLVMStructRetAttribute - NoUnwindAttribute Attribute = C.LLVMNoUnwindAttribute - NoAliasAttribute Attribute = C.LLVMNoAliasAttribute - ByValAttribute Attribute = C.LLVMByValAttribute - NestAttribute Attribute = C.LLVMNestAttribute - ReadNoneAttribute Attribute = C.LLVMReadNoneAttribute - ReadOnlyAttribute Attribute = C.LLVMReadOnlyAttribute - NoInlineAttribute Attribute = C.LLVMNoInlineAttribute - AlwaysInlineAttribute Attribute = C.LLVMAlwaysInlineAttribute - OptimizeForSizeAttribute Attribute = C.LLVMOptimizeForSizeAttribute - StackProtectAttribute Attribute = C.LLVMStackProtectAttribute - StackProtectReqAttribute Attribute = C.LLVMStackProtectReqAttribute - Alignment Attribute = C.LLVMAlignment - NoCaptureAttribute Attribute = C.LLVMNoCaptureAttribute - NoRedZoneAttribute Attribute = C.LLVMNoRedZoneAttribute - NoImplicitFloatAttribute Attribute = C.LLVMNoImplicitFloatAttribute - NakedAttribute Attribute = C.LLVMNakedAttribute - InlineHintAttribute Attribute = C.LLVMInlineHintAttribute - StackAlignment Attribute = C.LLVMStackAlignment - ReturnsTwiceAttribute Attribute = C.LLVMReturnsTwice - UWTableAttribute Attribute = C.LLVMUWTable - NonLazyBindAttribute Attribute = 1 << 31 - SanitizeAddressAttribute Attribute = 1 << 32 - MinSizeAttribute Attribute = 1 << 33 - NoDuplicateAttribute Attribute = 1 << 34 - StackProtectStrongAttribute Attribute = 1 << 35 - SanitizeThreadAttribute Attribute = 1 << 36 - SanitizeMemoryAttribute Attribute = 1 << 37 - NoBuiltinAttribute Attribute = 1 << 38 - ReturnedAttribute Attribute = 1 << 39 - ColdAttribute Attribute = 1 << 40 - BuiltinAttribute Attribute = 1 << 41 - OptimizeNoneAttribute Attribute = 1 << 42 - InAllocaAttribute Attribute = 1 << 43 - NonNullAttribute Attribute = 1 << 44 - JumpTableAttribute Attribute = 1 << 45 - ConvergentAttribute Attribute = 1 << 46 - SafeStackAttribute Attribute = 1 << 47 -) - -//------------------------------------------------------------------------- // llvm.Opcode //------------------------------------------------------------------------- @@ -367,6 +320,63 @@ } //------------------------------------------------------------------------- +// llvm.Attribute +//------------------------------------------------------------------------- + +func AttributeKindID(name string) (id uint) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + id = uint(C.LLVMGetEnumAttributeKindForName(cname, C.size_t(len(name)))) + return +} + +func (c Context) CreateEnumAttribute(kind uint, val uint64) (a Attribute) { + a.C = C.LLVMCreateEnumAttribute(c.C, C.unsigned(kind), C.uint64_t(val)) + return +} + +func (a Attribute) GetEnumKind() (id int) { + id = int(C.LLVMGetEnumAttributeKind(a.C)) + return +} + +func (a Attribute) GetEnumValue() (val uint64) { + val = uint64(C.LLVMGetEnumAttributeValue(a.C)) + return +} + +func (c Context) CreateStringAttribute(kind string, val string) (a Attribute) { + ckind := C.CString(kind) + defer C.free(unsafe.Pointer(ckind)) + cval := C.CString(val) + defer C.free(unsafe.Pointer(cval)) + a.C = C.LLVMCreateStringAttribute(c.C, + ckind, C.unsigned(len(kind)), + cval, C.unsigned(len(val))) + return +} + +func (a Attribute) GetStringKind() string { + length := C.unsigned(0) + ckind := C.LLVMGetStringAttributeKind(a.C, &length) + return C.GoStringN(ckind, C.int(length)) +} + +func (a Attribute) GetStringValue() string { + length := C.unsigned(0) + ckind := C.LLVMGetStringAttributeValue(a.C, &length) + return C.GoStringN(ckind, C.int(length)) +} + +func (a Attribute) IsEnum() bool { + return C.LLVMIsEnumAttribute(a.C) != 0; +} + +func (a Attribute) IsString() bool { + return C.LLVMIsStringAttribute(a.C) != 0; +} + +//------------------------------------------------------------------------- // llvm.Module //------------------------------------------------------------------------- @@ -1044,9 +1054,38 @@ defer C.free(unsafe.Pointer(cname)) C.LLVMSetGC(v.C, cname) } -func (v Value) AddFunctionAttr(a Attribute) { C.LLVMAddFunctionAttr2(v.C, C.uint64_t(a)) } -func (v Value) FunctionAttr() Attribute { return Attribute(C.LLVMGetFunctionAttr2(v.C)) } -func (v Value) RemoveFunctionAttr(a Attribute) { C.LLVMRemoveFunctionAttr2(v.C, C.uint64_t(a)) } +func (v Value) AddAttributeAtIndex(i int, a Attribute) { + C.LLVMAddAttributeAtIndex(v.C, C.LLVMAttributeIndex(i), a.C) +} +func (v Value) AddFunctionAttr(a Attribute) { + v.AddAttributeAtIndex(C.LLVMAttributeFunctionIndex, a); +} +func (v Value) GetEnumAttributeAtIndex(i int, kind uint) (a Attribute) { + a.C = C.LLVMGetEnumAttributeAtIndex(v.C, C.LLVMAttributeIndex(i), C.unsigned(kind)) + return +} +func (v Value) GetEnumFunctionAttribute(kind uint) Attribute { + return v.GetEnumAttributeAtIndex(C.LLVMAttributeFunctionIndex, kind) +} +func (v Value) GetStringAttributeAtIndex(i int, kind string) (a Attribute) { + ckind := C.CString(kind) + defer C.free(unsafe.Pointer(ckind)) + a.C = C.LLVMGetStringAttributeAtIndex(v.C, C.LLVMAttributeIndex(i), + ckind, C.unsigned(len(kind))) + return +} +func (v Value) RemoveEnumAttributeAtIndex(i int, kind uint) { + C.LLVMRemoveEnumAttributeAtIndex(v.C, C.LLVMAttributeIndex(i), C.unsigned(kind)) +} +func (v Value) RemoveEnumFunctionAttribute(kind uint) { + v.RemoveEnumAttributeAtIndex(C.LLVMAttributeFunctionIndex, kind); +} +func (v Value) RemoveStringAttributeAtIndex(i int, kind string) { + ckind := C.CString(kind) + defer C.free(unsafe.Pointer(ckind)) + C.LLVMRemoveStringAttributeAtIndex(v.C, C.LLVMAttributeIndex(i), + ckind, C.unsigned(len(kind))) +} func (v Value) AddTargetDependentFunctionAttr(attr, value string) { cattr := C.CString(attr) defer C.free(unsafe.Pointer(cattr)) @@ -1076,19 +1115,6 @@ func (v Value) LastParam() (rv Value) { rv.C = C.LLVMGetLastParam(v.C); return } func NextParam(v Value) (rv Value) { rv.C = C.LLVMGetNextParam(v.C); return } func PrevParam(v Value) (rv Value) { rv.C = C.LLVMGetPreviousParam(v.C); return } -func (v Value) AddAttribute(a Attribute) { - if a >= 1<<32 { - panic("attribute value currently unsupported") - } - C.LLVMAddAttribute(v.C, C.LLVMAttribute(a)) -} -func (v Value) RemoveAttribute(a Attribute) { - if a >= 1<<32 { - panic("attribute value currently unsupported") - } - C.LLVMRemoveAttribute(v.C, C.LLVMAttribute(a)) -} -func (v Value) Attribute() Attribute { return Attribute(C.LLVMGetAttribute(v.C)) } func (v Value) SetParamAlignment(align int) { C.LLVMSetParamAlignment(v.C, C.unsigned(align)) } // Operations on basic blocks @@ -1149,17 +1175,8 @@ func (v Value) InstructionCallConv() CallConv { return CallConv(C.LLVMCallConv(C.LLVMGetInstructionCallConv(v.C))) } -func (v Value) AddInstrAttribute(i int, a Attribute) { - if a >= 1<<32 { - panic("attribute value currently unsupported") - } - C.LLVMAddInstrAttribute(v.C, C.unsigned(i), C.LLVMAttribute(a)) -} -func (v Value) RemoveInstrAttribute(i int, a Attribute) { - if a >= 1<<32 { - panic("attribute value currently unsupported") - } - C.LLVMRemoveInstrAttribute(v.C, C.unsigned(i), C.LLVMAttribute(a)) +func (v Value) AddCallSiterAttribute(i int, a Attribute) { + C.LLVMAddCallSiteAttribute(v.C, C.LLVMAttributeIndex(i), a.C) } func (v Value) SetInstrParamAlignment(i int, align int) { C.LLVMSetInstrParamAlignment(v.C, C.unsigned(i), C.unsigned(align)) Index: bindings/go/llvm/ir_test.go =================================================================== --- bindings/go/llvm/ir_test.go +++ bindings/go/llvm/ir_test.go @@ -18,15 +18,18 @@ "testing" ) -func testAttribute(t *testing.T, attr Attribute, name string) { +func testAttribute(t *testing.T, name string) { mod := NewModule("") defer mod.Dispose() ftyp := FunctionType(VoidType(), nil, false) fn := AddFunction(mod, "foo", ftyp) + kind := AttributeKindID(name) + attr := mod.Context().CreateEnumAttribute(kind, 0) + fn.AddFunctionAttr(attr) - newattr := fn.FunctionAttr() + newattr := fn.GetEnumFunctionAttribute(kind) if attr != newattr { t.Errorf("got attribute mask %d, want %d", newattr, attr) } @@ -36,62 +39,59 @@ t.Errorf("expected attribute '%s', got:\n%s", name, text) } - fn.RemoveFunctionAttr(attr) - newattr = fn.FunctionAttr() - if newattr != 0 { + fn.RemoveEnumFunctionAttribute(kind) + newattr = fn.GetEnumFunctionAttribute(kind) + if !newattr.IsNil() { t.Errorf("got attribute mask %d, want 0", newattr) } } func TestAttributes(t *testing.T) { // Tests that our attribute constants haven't drifted from LLVM's. - attrTests := []struct { - attr Attribute - name string - }{ - {SanitizeAddressAttribute, "sanitize_address"}, - {AlwaysInlineAttribute, "alwaysinline"}, - {BuiltinAttribute, "builtin"}, - {ByValAttribute, "byval"}, - {ConvergentAttribute, "convergent"}, - {InAllocaAttribute, "inalloca"}, - {InlineHintAttribute, "inlinehint"}, - {InRegAttribute, "inreg"}, - {JumpTableAttribute, "jumptable"}, - {MinSizeAttribute, "minsize"}, - {NakedAttribute, "naked"}, - {NestAttribute, "nest"}, - {NoAliasAttribute, "noalias"}, - {NoBuiltinAttribute, "nobuiltin"}, - {NoCaptureAttribute, "nocapture"}, - {NoDuplicateAttribute, "noduplicate"}, - {NoImplicitFloatAttribute, "noimplicitfloat"}, - {NoInlineAttribute, "noinline"}, - {NonLazyBindAttribute, "nonlazybind"}, - {NonNullAttribute, "nonnull"}, - {NoRedZoneAttribute, "noredzone"}, - {NoReturnAttribute, "noreturn"}, - {NoUnwindAttribute, "nounwind"}, - {OptimizeNoneAttribute, "optnone"}, - {OptimizeForSizeAttribute, "optsize"}, - {ReadNoneAttribute, "readnone"}, - {ReadOnlyAttribute, "readonly"}, - {ReturnedAttribute, "returned"}, - {ReturnsTwiceAttribute, "returns_twice"}, - {SExtAttribute, "signext"}, - {SafeStackAttribute, "safestack"}, - {StackProtectAttribute, "ssp"}, - {StackProtectReqAttribute, "sspreq"}, - {StackProtectStrongAttribute, "sspstrong"}, - {StructRetAttribute, "sret"}, - {SanitizeThreadAttribute, "sanitize_thread"}, - {SanitizeMemoryAttribute, "sanitize_memory"}, - {UWTableAttribute, "uwtable"}, - {ZExtAttribute, "zeroext"}, - {ColdAttribute, "cold"}, + attrTests := []string{ + "sanitize_address", + "alwaysinline", + "builtin", + "byval", + "convergent", + "inalloca", + "inlinehint", + "inreg", + "jumptable", + "minsize", + "naked", + "nest", + "noalias", + "nobuiltin", + "nocapture", + "noduplicate", + "noimplicitfloat", + "noinline", + "nonlazybind", + "nonnull", + "noredzone", + "noreturn", + "nounwind", + "optnone", + "optsize", + "readnone", + "readonly", + "returned", + "returns_twice", + "signext", + "safestack", + "ssp", + "sspreq", + "sspstrong", + "sret", + "sanitize_thread", + "sanitize_memory", + "uwtable", + "zeroext", + "cold", } - for _, a := range attrTests { - testAttribute(t, a.attr, a.name) + for _, name := range attrTests { + testAttribute(t, name) } }