go-llvm/llgo

llgo-build testing fails

quarnster opened this issue · 2 comments

17:38 ~/code/go/src/github.com/axw/llgo/cmd/llgo-dist $ llgo-build testing
2013/09/25 17:39:52 building testing
Verification failed: Referring to a basic block in another function!
  %0 = invoke { i8*, i64 }* @flag.String({ i8*, i64 } { i8* getelementptr inbounds ([17 x i8]* @137, i32 0, i32 0), i64 17 }, { i8*, i64 } zeroinitializer, { i8*, i64 } { i8* getelementptr inbounds ([58 x i8]* @138, i32 0, i32 0), i64 58 })
          to label %1 unwind label %unwind
Referring to a basic block in another function!
  %0 = invoke { i8*, i64 }* @flag.String({ i8*, i64 } { i8* getelementptr inbounds ([17 x i8]* @137, i32 0, i32 0), i64 17 }, { i8*, i64 } zeroinitializer, { i8*, i64 } { i8* getelementptr inbounds ([58 x i8]* @138, i32 0, i32 0), i64 58 })
          to label %1 unwind label %unwind
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Referring to a basic block in another function!
  %0 = invoke i1* @flag.Bool({ i8*, i64 } { i8* getelementptr inbounds ([6 x i8]* @173, i32 0, i32 0), i64 6 }, i1 false, { i8*, i64 } { i8* getelementptr inbounds ([32 x i8]* @174, i32 0, i32 0), i64 32 })
          to label %1 unwind label %unwind
Referring to a basic block in another function!
  %0 = invoke i1* @flag.Bool({ i8*, i64 } { i8* getelementptr inbounds ([6 x i8]* @173, i32 0, i32 0), i64 6 }, i1 false, { i8*, i64 } { i8* getelementptr inbounds ([32 x i8]* @174, i32 0, i32 0), i64 32 })
          to label %1 unwind label %unwind
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.

Minimal code repro:

// a.go
package main

import (
    "fmt"
)

func main() {
    fmt.Println(*something)
    defer func() {}()
}
// b.go
package main

import (
    "flag"
)

var (
    something = flag.Bool("hello", false, "world")
)

Running llgo -c a.go b.go gives me:

Verification failed: Referring to a basic block in another function!
  %0 = invoke i1* @flag.Bool({ i8*, i64 } { i8* getelementptr inbounds ([5 x i8]* @0, i32 0, i32 0), i64 5 }, i1 false, { i8*, i64 } { i8* getelementptr inbounds ([5 x i8]* @1, i32 0, i32 0), i64 5 })
          to label %1 unwind label %unwind
Referring to a basic block in another function!
  %0 = invoke i1* @flag.Bool({ i8*, i64 } { i8* getelementptr inbounds ([5 x i8]* @0, i32 0, i32 0), i64 5 }, i1 false, { i8*, i64 } { i8* getelementptr inbounds ([5 x i8]* @1, i32 0, i32 0), i64 5 })
          to label %1 unwind label %unwind
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.
Broken module found, compilation terminated.

The error message is because there's no unwind block created for the variable constructor:

define void @__llgo.ctor.main.0() {
entry:
  %0 = invoke i1* @flag.Bool({ i8*, i64 } { i8* getelementptr inbounds ([5 x i8]* @0, i32 0, i32 0), i64 5 }, i1 false, { i8*, i64 } { i8* getelementptr inbounds ([5 x i8]* @1, i32 0, i32 0), i64 5 })
          to label %1 unwind label %unwind

; <label>:1                                       ; preds = %entry
  store i1* %0, i1** @main.something
  ret void
}

But I believe the underlying error here is that the call to flag.Bool thinks it's called from main rather than the constructor which clearly isn't the case.

@axw, This appears to fix the issue, but I wanted to double check with you that it is indeed correct before creating a pull request:

diff --git a/decl.go b/decl.go
index 4c61892..6e3b93a 100644
--- a/decl.go
+++ b/decl.go
@@ -291,6 +291,8 @@ func (c *compiler) createGlobals(idents []*ast.Ident, values []ast.Expr, pkg str
    }
    llvmfntype := llvm.FunctionType(llvm.VoidType(), nil, false)
    fn := llvm.AddFunction(c.module.Module, "", llvmfntype)
+   // Pushing nil, children don't need access to a "real" init function handle
+   c.functions.push(nil)
    entry := llvm.AddBasicBlock(fn, "entry")
    c.builder.SetInsertPointAtEnd(entry)

@@ -320,6 +322,7 @@ func (c *compiler) createGlobals(idents []*ast.Ident, values []ast.Expr, pkg str
    }
    c.builder.CreateRetVoid()
    c.varinitfuncs = append(c.varinitfuncs, fn)
+   c.functions.pop()
 }

 func (c *compiler) VisitValueSpec(valspec *ast.ValueSpec) {
axw commented

@axw, This appears to fix the issue, but I wanted to double check with you that it is indeed correct before creating a pull request:

Yes, looks good. Thanks.