gollvm: handle unresolved placeholder in type_field_offset
Check for the presence of unresolved placeholder types as
part of Llvm_backend::type_field_offset, since this method
can be invoked on a struct type whose fields may incorporate
unresolved placeholder types.
Change-Id: I13e4ac860cc62cad0046df4fc70d5981f77e095c
Reviewed-on: https://go-review.googlesource.com/46730
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/llvm-gofrontend/go-llvm-typemanager.cpp b/llvm-gofrontend/go-llvm-typemanager.cpp
index 3d70607..f7f23c0 100644
--- a/llvm-gofrontend/go-llvm-typemanager.cpp
+++ b/llvm-gofrontend/go-llvm-typemanager.cpp
@@ -1285,6 +1285,21 @@
return nullptr;
}
+// Helper for use with typeSize() and typeFieldOffset methods.
+// Handles situations where we're asking about size/offset for
+// types that still incorporate placeholders.
+llvm::Type *TypeManager::getPlaceholderProxyIfNeeded(Btype *btype)
+{
+ llvm::Type *toget = btype->type();
+ llvm::SmallPtrSet<llvm::Type *, 32> vis;
+ if (!btype->type()->isSized(&vis)) {
+ pproxymap pmap;
+ toget = placeholderProxyType(btype, &pmap);
+ assert(toget);
+ }
+ return toget;
+}
+
// Return the size of a type.
// Note: frontend sometimes asks for the size of a placeholder
@@ -1296,15 +1311,7 @@
int64_t TypeManager::typeSize(Btype *btype) {
if (btype == errorType_)
return 1;
-
- llvm::Type *toget = btype->type();
- llvm::SmallPtrSet<llvm::Type *, 32> vis;
- if (!btype->type()->isSized(&vis)) {
- pproxymap pmap;
- toget = placeholderProxyType(btype, &pmap);
- assert(toget);
- }
-
+ llvm::Type *toget = getPlaceholderProxyIfNeeded(btype);
uint64_t uvalbytes = datalayout_->getTypeAllocSize(toget);
return static_cast<int64_t>(uvalbytes);
}
@@ -1365,8 +1372,10 @@
int64_t TypeManager::typeFieldOffset(Btype *btype, size_t index) {
if (btype == errorType_)
return 0;
- assert(btype->type()->isStructTy());
- llvm::StructType *llvm_st = llvm::cast<llvm::StructType>(btype->type());
+
+ llvm::Type *toget = getPlaceholderProxyIfNeeded(btype);
+ assert(toget->isStructTy());
+ llvm::StructType *llvm_st = llvm::cast<llvm::StructType>(toget);
return llvmTypeFieldOffset(llvm_st, index);
}
diff --git a/llvm-gofrontend/go-llvm-typemanager.h b/llvm-gofrontend/go-llvm-typemanager.h
index 8a2c3be..824849a 100644
--- a/llvm-gofrontend/go-llvm-typemanager.h
+++ b/llvm-gofrontend/go-llvm-typemanager.h
@@ -265,6 +265,10 @@
typedef std::unordered_map<Btype *, llvm::Type *> pproxymap;
llvm::Type *placeholderProxyType(Btype *typ, pproxymap *pmap);
+ // Checks for placeholder and invokes routine above if needed,
+ // otherwise returns the LLVM type for the specified Btype.
+ llvm::Type *getPlaceholderProxyIfNeeded(Btype *btype);
+
// Context information needed for the LLVM backend.
llvm::LLVMContext &context_;
const llvm::DataLayout *datalayout_;
diff --git a/unittests/BackendCore/BackendCoreTests.cpp b/unittests/BackendCore/BackendCoreTests.cpp
index dd27cac..039d7d5 100644
--- a/unittests/BackendCore/BackendCoreTests.cpp
+++ b/unittests/BackendCore/BackendCoreTests.cpp
@@ -305,6 +305,7 @@
be->set_placeholder_struct_type(phst, fields);
Btype *rst = mkTwoFieldStruct(be.get(), pvt, pvt);
EXPECT_EQ(be->type_size(rst), be->type_size(phst));
+ EXPECT_EQ(be->type_field_offset(rst,1), be->type_field_offset(phst,1));
// type field alignment
Btype *u32 = be->integer_type(true, 32);