Parsing module from bitcode file fails

Hey, I have the following code that’s failing and I’m unsure why:

static LLVMContext TheContext;
static IRBuilder<> Builder(TheContext);

int main(int argc, char **argv){
    MemoryBufferRef file = *MemoryBuffer::getFile(argv[1]).get();
    Expected<std::unique_ptr<llvm::Module>> mod = llvm::parseBitcodeFile(file, TheContext);
    errs() << toString(std::move(mod.takeError())) << "\n";
    return 0;
}

The error being printed is:

Trying to materialize functions before seeing function blocks (Producer: 'LLVM14.0.4' Reader: 'LLVM 14.0.4')

And sometimes when the program is run it crashes with:

LLVM ERROR: Invalid abbrev number
Aborted

Can anyone tell me what’s wrong with my code? The input file is generated by llvm-as just fine so I don’t think the input is the problem, but I can post the .ll if need be.

You could try running llvm-dis on the bitcode file, and see if it gives any errors. If not, you can compare its output to your original .ll file that you ran through llvm-as.

Just tried this, no difference after running through llvm-dis again. The input is definitely fine - here it is:

; ModuleID = 'test.ll'
source_filename = "test.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"

; Function Attrs: nounwind uwtable
define dso_local i32* @test(i32* %0, i32* %1, i32 %2) #0 {
  br label %4

4:                                                ; preds = %16, %3
  %.0 = phi i32 [ 0, %3 ], [ %17, %16 ]
  %5 = icmp slt i32 %.0, %2
  br i1 %5, label %7, label %6

6:                                                ; preds = %4
  br label %18

7:                                                ; preds = %4
  %8 = sext i32 %.0 to i64
  %9 = getelementptr inbounds i32, i32* %0, i64 %8
  %10 = load i32, i32* %9, align 4, !tbaa !3
  %11 = add nsw i32 %10, 1
  store i32 %11, i32* %9, align 4, !tbaa !3
  %12 = sext i32 %.0 to i64
  %13 = getelementptr inbounds i32, i32* %1, i64 %12
  %14 = load i32, i32* %13, align 4, !tbaa !3
  %15 = add nsw i32 %14, 1
  store i32 %15, i32* %13, align 4, !tbaa !3
  br label %16

16:                                               ; preds = %7
  %17 = add nsw i32 %.0, 1
  br label %4, !llvm.loop !7

18:                                               ; preds = %6
  %19 = add nsw i32 %2, 1
  %20 = sext i32 %19 to i64
  %21 = getelementptr inbounds i32, i32* %0, i64 %20
  %22 = load i32, i32* %21, align 4, !tbaa !3
  %23 = add nsw i32 %22, 2
  store i32 %23, i32* %21, align 4, !tbaa !3
  ret i32* %0
}

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1

; Function Attrs: argmemonly nofree nosync nounwind willreturn
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1

attributes #0 = { nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { argmemonly nofree nosync nounwind willreturn }

!llvm.module.flags = !{!0, !1}
!llvm.ident = !{!2}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"uwtable", i32 1}
!2 = !{!"clang version 13.0.1"}
!3 = !{!4, !4, i64 0}
!4 = !{!"int", !5, i64 0}
!5 = !{!"omnipotent char", !6, i64 0}
!6 = !{!"Simple C/C++ TBAA"}
!7 = distinct !{!7, !8, !9}
!8 = !{!"llvm.loop.mustprogress"}
!9 = !{!"llvm.loop.unroll.disable"}

Sorry it didn’t turn out to be easy. I’m not familiar with these APIs, so all I can do at this point is notice the obvious, that llvm-dis doesn’t use parseBitcodeFile.

for anybody wondering, turns out the ‘solution’ is to use llvm::parseIRFile instead.