Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -474,6 +474,8 @@ void visitModuleFlagCGProfileEntry(const MDOperand &MDO); void visitFunction(const Function &F); void visitBasicBlock(BasicBlock &BB); + void verifyRangeMetadata(const Value &V, const MDNode *Range, Type *Ty, + bool IsAbsoluteSymbol); void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty); void visitDereferenceableMetadata(Instruction &I, MDNode *MD); void visitProfMetadata(Instruction &I, MDNode *MD); @@ -682,7 +684,15 @@ Associated); } } + + // FIXME: Why is getMetadata on GlobalValue protected? + if (const MDNode *AbsoluteSymbol = + GO->getMetadata(LLVMContext::MD_absolute_symbol)) { + verifyRangeMetadata(*GO, AbsoluteSymbol, DL.getIntPtrType(GO->getType()), + true); + } } + Check(!GV.hasAppendingLinkage() || isa(GV), "Only global variables can have appending linkage!", &GV); @@ -3904,10 +3914,10 @@ return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); } -void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) { - assert(Range && Range == I.getMetadata(LLVMContext::MD_range) && - "precondition violation"); - +/// Verify !range and !absolute_symbol metadata. These have the same +/// restrictions, except !absolute_symbol allows the full set. +void Verifier::verifyRangeMetadata(const Value &I, const MDNode *Range, + Type *Ty, bool IsAbsoluteSymbol) { unsigned NumOperands = Range->getNumOperands(); Check(NumOperands % 2 == 0, "Unfinished range!", Range); unsigned NumRanges = NumOperands / 2; @@ -3934,7 +3944,7 @@ "The upper and lower limits cannot be the same value", &I); ConstantRange CurRange(LowV, HighV); - Check(!CurRange.isEmptySet() && !CurRange.isFullSet(), + Check(!CurRange.isEmptySet() && (IsAbsoluteSymbol || !CurRange.isFullSet()), "Range must not be empty!", Range); if (i != 0) { Check(CurRange.intersectWith(LastRange).isEmptySet(), @@ -3959,6 +3969,12 @@ } } +void Verifier::visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty) { + assert(Range && Range == I.getMetadata(LLVMContext::MD_range) && + "precondition violation"); + verifyRangeMetadata(I, Range, Ty, false); +} + void Verifier::checkAtomicMemAccessSize(Type *Ty, const Instruction *I) { unsigned Size = DL.getTypeSizeInBits(Ty); Check(Size >= 8, "atomic memory access' size must be byte-sized", Ty, I); Index: llvm/test/Assembler/absolute_symbol.ll =================================================================== --- /dev/null +++ llvm/test/Assembler/absolute_symbol.ll @@ -0,0 +1,20 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +; CHECK: @simple_range = external global i32, !absolute_symbol [[META0:![0-9]+]] +@simple_range = external global i32, !absolute_symbol !0 + +; Unlike !range, this accepts -1, -1 +; CHECK: @full_range = external global i32, !absolute_symbol [[META1:![0-9]+]] +@full_range = external global i32, !absolute_symbol !1 + +; CHECK: @multiple_ranges = external global i32, !absolute_symbol [[META2:![0-9]+]] +@multiple_ranges = external global i32, !absolute_symbol !2 + +!0 = !{i64 4096, i64 8192} +!1 = !{i64 -1, i64 -1} +!2 = !{i64 256, i64 512, i64 1024, i64 4096} +;. +; CHECK: [[META0]] = !{i64 4096, i64 8192} +; CHECK: [[META1]] = !{i64 -1, i64 -1} +; CHECK: [[META2]] = !{i64 256, i64 512, i64 1024, i64 4096} +;. Index: llvm/test/CodeGen/X86/absolute-constant.ll =================================================================== --- llvm/test/CodeGen/X86/absolute-constant.ll +++ llvm/test/CodeGen/X86/absolute-constant.ll @@ -44,4 +44,4 @@ declare void @xf(...) -!0 = !{i32 0, i32 256} +!0 = !{i64 0, i64 256} Index: llvm/test/Verifier/absolute_symbol.ll =================================================================== --- /dev/null +++ llvm/test/Verifier/absolute_symbol.ll @@ -0,0 +1,96 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s + +target datalayout = "p0:64:64-p1:32:32" + + +@absolute_empty_arguments = external global i32, !absolute_symbol !0 + +@absolute_one_argument = external global i32, !absolute_symbol !1 + +@absolute_three_arguments = external global i32, !absolute_symbol !2 + + + +@absolute_one_argument_wrong_width = external global i32, !absolute_symbol !3 +@absolute_two_arguments_wrong_width = external global i32, !absolute_symbol !4 + +@absolute_two_arguments_one_wrong_width0 = external global i32, !absolute_symbol !5 +@absolute_two_arguments_one_wrong_width1 = external global i32, !absolute_symbol !6 + +@absolute_zero_zero = external global i32, !absolute_symbol !7 + +@absolute_equal_other = external global i32, !absolute_symbol !8 + +@absolute_wrong_width_non0_as = external addrspace(1) global i32, !absolute_symbol !9 + +; Test other kinds of symbols besides GlobalVariable +define void @absolute_func_empty_arguments() !absolute_symbol !0 { + ret void +} + +@absolute_is_fp = external global i32, !absolute_symbol !10 +@absolute_is_vector = external global i32, !absolute_symbol !11 +@absolute_is_ptr = external global i32, !absolute_symbol !12 +@absolute_is_ptr0 = external global i32, !absolute_symbol !13 +@absolute_is_ptr1 = external global i32, !absolute_symbol !14 + +@absolute_wrong_order = external global i32, !absolute_symbol !15 + +; CHECK: It should have at least one range! +; CHECK-NEXT: !0 = !{} +; CHECK: It should have at least one range! +; CHECK-NEXT: !0 = !{} +!0 = !{} + +; CHECK-NEXT: Unfinished range! +; CHECK-NEXT: !1 = !{i64 128} +!1 = !{i64 128} + +; CHECK-NEXT: Unfinished range! +; CHECK-NEXT: !2 = !{i64 128, i64 256, i64 512} +!2 = !{i64 128, i64 256, i64 512} + +; CHECK-NEXT: Unfinished range! +; CHECK-NEXT: !3 = !{i32 256} +!3 = !{i32 256} + +; CHECK-NEXT: Range types must match instruction type! +; CHECK-NEXT: ptr @absolute_two_arguments_wrong_width +!4 = !{i32 256, i32 512} + +; CHECK-NEXT: Range types must match instruction type! +; CHECK-NEXT: ptr @absolute_two_arguments_one_wrong_width0 +!5 = !{i32 256, i64 512} + +; CHECK-NEXT: Range types must match instruction type! +; CHECK-NEXT: ptr @absolute_two_arguments_one_wrong_width1 +!6 = !{i64 256, i32 512} + +; CHECK-NEXT: Range must not be empty! +; CHECK-NEXT: !7 = !{i64 0, i64 0} +!7 = !{i64 0, i64 0} + +; CHECK-NEXT: The upper and lower limits cannot be the same value +; CHECK-NEXT: ptr @absolute_equal_other +!8 = !{i64 123, i64 123} + +; CHECK-NEXT: Range types must match instruction type! +; CHECK-NEXT: ptr addrspace(1) @absolute_wrong_width_non0_as +!9 = !{i64 512, i64 256} + +; CHECK-NEXT: The lower limit must be an integer! +!10 = !{float 0.0, float 256.0} + +; CHECK-NEXT: The lower limit must be an integer! +!11 = !{<2 x i64> zeroinitializer, <2 x i64> } + +; CHECK-NEXT: The lower limit must be an integer! +!12 = !{ptr null, ptr inttoptr (i64 256 to ptr)} + +; CHECK-NEXT: The lower limit must be an integer! +!13 = !{ptr null, i64 456} + +; CHECK-NEXT: The upper limit must be an integer! +!14 = !{i64 456, ptr inttoptr (i64 512 to ptr)} +!15 = !{i64 1024, i64 128} +