summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/IPO/ExtractGV.cpp30
-rw-r--r--test/Other/extract-alias.ll40
2 files changed, 70 insertions, 0 deletions
diff --git a/lib/Transforms/IPO/ExtractGV.cpp b/lib/Transforms/IPO/ExtractGV.cpp
index 4c7f0ed236..57c2f6d410 100644
--- a/lib/Transforms/IPO/ExtractGV.cpp
+++ b/lib/Transforms/IPO/ExtractGV.cpp
@@ -79,6 +79,36 @@ namespace {
I->setLinkage(GlobalValue::ExternalLinkage);
}
+ // Visit the Aliases.
+ for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
+ I != E;) {
+ Module::alias_iterator CurI = I;
+ ++I;
+
+ if (CurI->hasLocalLinkage())
+ CurI->setVisibility(GlobalValue::HiddenVisibility);
+ CurI->setLinkage(GlobalValue::ExternalLinkage);
+
+ if (deleteStuff == (bool)Named.count(CurI)) {
+ Type *Ty = CurI->getType()->getElementType();
+
+ CurI->removeFromParent();
+ llvm::Value *Declaration;
+ if (FunctionType *FTy = dyn_cast<FunctionType>(Ty)) {
+ Declaration = Function::Create(FTy, GlobalValue::ExternalLinkage,
+ CurI->getName(), &M);
+
+ } else {
+ Declaration =
+ new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage,
+ 0, CurI->getName());
+
+ }
+ CurI->replaceAllUsesWith(Declaration);
+ delete CurI;
+ }
+ }
+
return true;
}
};
diff --git a/test/Other/extract-alias.ll b/test/Other/extract-alias.ll
new file mode 100644
index 0000000000..85d1ae5b1b
--- /dev/null
+++ b/test/Other/extract-alias.ll
@@ -0,0 +1,40 @@
+; RUN: llvm-extract -func foo -S < %s | FileCheck %s
+; RUN: llvm-extract -delete -func foo -S < %s | FileCheck --check-prefix=DELETE %s
+
+; Both aliases should be converted to declarations
+; CHECK: @zeda0 = external global i32
+; CHECK: define i32* @foo() {
+; CHECK-NEXT: call void @a0bar()
+; CHECK-NEXT: ret i32* @zeda0
+; CHECK-NEXT: }
+; CHECK: declare void @a0bar()
+
+; DELETE: @zed = global i32 0
+; DELETE: @zeda0 = alias i32* @zed
+; DELETE-NEXT: @a0foo = alias i32* ()* @foo
+; DELETE-NEXT: @a0a0bar = alias void ()* @a0bar
+; DELETE-NEXT: @a0bar = alias void ()* @bar
+; DELETE: declare i32* @foo()
+; DELETE: define void @bar() {
+; DELETE-NEXT: %c = call i32* @foo()
+; DELETE-NEXT: ret void
+; DELETE-NEXT: }
+
+@zed = global i32 0
+@zeda0 = alias i32* @zed
+
+@a0foo = alias i32* ()* @foo
+
+define i32* @foo() {
+ call void @a0bar()
+ ret i32* @zeda0
+}
+
+@a0a0bar = alias void ()* @a0bar
+
+@a0bar = alias void ()* @bar
+
+define void @bar() {
+ %c = call i32* @foo()
+ ret void
+}