diff options
Diffstat (limited to 'llvm/tools/llvm-c-test/echo.cpp')
-rw-r--r-- | llvm/tools/llvm-c-test/echo.cpp | 94 |
1 files changed, 88 insertions, 6 deletions
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index ca3a1be0684..a9cd4cf5cbb 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -248,10 +248,19 @@ static LLVMValueRef clone_constant_impl(LLVMValueRef Cst, LLVMModuleRef M) { // Try global variable if (LLVMIsAGlobalVariable(Cst)) { check_value_kind(Cst, LLVMGlobalVariableValueKind); - LLVMValueRef Dst = LLVMGetNamedGlobal(M, Name); + LLVMValueRef Dst = LLVMGetNamedGlobal(M, Name); if (Dst) return Dst; - report_fatal_error("Could not find function"); + report_fatal_error("Could not find variable"); + } + + // Try global alias + if (LLVMIsAGlobalAlias(Cst)) { + check_value_kind(Cst, LLVMGlobalAliasValueKind); + LLVMValueRef Dst = LLVMGetNamedGlobalAlias(M, Name, NameLen); + if (Dst) + return Dst; + report_fatal_error("Could not find alias"); } fprintf(stderr, "Could not find @%s\n", Name); @@ -822,6 +831,8 @@ struct FunCloner { }; static void declare_symbols(LLVMModuleRef Src, LLVMModuleRef M) { + auto Ctx = LLVMGetModuleContext(M); + LLVMValueRef Begin = LLVMGetFirstGlobal(Src); LLVMValueRef End = LLVMGetLastGlobal(Src); @@ -860,11 +871,9 @@ FunDecl: if (!Begin) { if (End != nullptr) report_fatal_error("Range has an end but no beginning"); - return; + goto AliasDecl; } - auto Ctx = LLVMGetModuleContext(M); - Cur = Begin; Next = nullptr; while (true) { @@ -900,6 +909,40 @@ FunDecl: Cur = Next; } + +AliasDecl: + Begin = LLVMGetFirstGlobalAlias(Src); + End = LLVMGetLastGlobalAlias(Src); + if (!Begin) { + if (End != nullptr) + report_fatal_error("Range has an end but no beginning"); + return; + } + + Cur = Begin; + Next = nullptr; + while (true) { + size_t NameLen; + const char *Name = LLVMGetValueName2(Cur, &NameLen); + if (LLVMGetNamedGlobalAlias(M, Name, NameLen)) + report_fatal_error("Global alias already cloned"); + LLVMTypeRef CurType = TypeCloner(M).Clone(Cur); + // FIXME: Allow NULL aliasee. + LLVMAddAlias(M, CurType, LLVMGetUndef(CurType), Name); + + Next = LLVMGetNextGlobalAlias(Cur); + if (Next == nullptr) { + if (Cur != End) + report_fatal_error(""); + break; + } + + LLVMValueRef Prev = LLVMGetPreviousGlobalAlias(Next); + if (Prev != Cur) + report_fatal_error("Next.Previous global is not Current"); + + Cur = Next; + } } static void clone_symbols(LLVMModuleRef Src, LLVMModuleRef M) { @@ -953,7 +996,7 @@ FunClone: if (!Begin) { if (End != nullptr) report_fatal_error("Range has an end but no beginning"); - return; + goto AliasClone; } Cur = Begin; @@ -991,6 +1034,45 @@ FunClone: Cur = Next; } + +AliasClone: + Begin = LLVMGetFirstGlobalAlias(Src); + End = LLVMGetLastGlobalAlias(Src); + if (!Begin) { + if (End != nullptr) + report_fatal_error("Range has an end but no beginning"); + return; + } + + Cur = Begin; + Next = nullptr; + while (true) { + size_t NameLen; + const char *Name = LLVMGetValueName2(Cur, &NameLen); + LLVMValueRef Alias = LLVMGetNamedGlobalAlias(M, Name, NameLen); + if (!Alias) + report_fatal_error("Global alias must have been declared already"); + + if (LLVMValueRef Aliasee = LLVMAliasGetAliasee(Cur)) { + LLVMAliasSetAliasee(Alias, clone_constant(Aliasee, M)); + } + + LLVMSetLinkage(Alias, LLVMGetLinkage(Cur)); + LLVMSetUnnamedAddress(Alias, LLVMGetUnnamedAddress(Cur)); + + Next = LLVMGetNextGlobalAlias(Cur); + if (Next == nullptr) { + if (Cur != End) + report_fatal_error("Last global alias does not match End"); + break; + } + + LLVMValueRef Prev = LLVMGetPreviousGlobalAlias(Next); + if (Prev != Cur) + report_fatal_error("Next.Previous global alias is not Current"); + + Cur = Next; + } } int llvm_echo(void) { |