diff options
Diffstat (limited to 'llvm/tools/llvm-c-test/echo.cpp')
-rw-r--r-- | llvm/tools/llvm-c-test/echo.cpp | 78 |
1 files changed, 76 insertions, 2 deletions
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index 73da1ee8b21..8341b11aa45 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -939,7 +939,7 @@ AliasDecl: if (!Begin) { if (End != nullptr) report_fatal_error("Range has an end but no beginning"); - goto NamedMDDecl; + goto GlobalIFuncDecl; } Cur = Begin; @@ -967,6 +967,41 @@ AliasDecl: Cur = Next; } +GlobalIFuncDecl: + Begin = LLVMGetFirstGlobalIFunc(Src); + End = LLVMGetLastGlobalIFunc(Src); + if (!Begin) { + if (End != nullptr) + report_fatal_error("Range has an end but no beginning"); + goto NamedMDDecl; + } + + Cur = Begin; + Next = nullptr; + while (true) { + size_t NameLen; + const char *Name = LLVMGetValueName2(Cur, &NameLen); + if (LLVMGetNamedGlobalIFunc(M, Name, NameLen)) + report_fatal_error("Global ifunc already cloned"); + LLVMTypeRef CurType = TypeCloner(M).Clone(LLVMGlobalGetValueType(Cur)); + // FIXME: Allow NULL resolver. + LLVMAddGlobalIFunc(M, Name, NameLen, + CurType, /*addressSpace*/ 0, LLVMGetUndef(CurType)); + + Next = LLVMGetNextGlobalIFunc(Cur); + if (Next == nullptr) { + if (Cur != End) + report_fatal_error(""); + break; + } + + LLVMValueRef Prev = LLVMGetPreviousGlobalIFunc(Next); + if (Prev != Cur) + report_fatal_error("Next.Previous global is not Current"); + + Cur = Next; + } + NamedMDDecl: LLVMNamedMDNodeRef BeginMD = LLVMGetFirstNamedMetadata(Src); LLVMNamedMDNodeRef EndMD = LLVMGetLastNamedMetadata(Src); @@ -1114,7 +1149,7 @@ AliasClone: if (!Begin) { if (End != nullptr) report_fatal_error("Range has an end but no beginning"); - goto NamedMDClone; + goto GlobalIFuncClone; } Cur = Begin; @@ -1147,6 +1182,45 @@ AliasClone: Cur = Next; } +GlobalIFuncClone: + Begin = LLVMGetFirstGlobalIFunc(Src); + End = LLVMGetLastGlobalIFunc(Src); + if (!Begin) { + if (End != nullptr) + report_fatal_error("Range has an end but no beginning"); + goto NamedMDClone; + } + + Cur = Begin; + Next = nullptr; + while (true) { + size_t NameLen; + const char *Name = LLVMGetValueName2(Cur, &NameLen); + LLVMValueRef IFunc = LLVMGetNamedGlobalIFunc(M, Name, NameLen); + if (!IFunc) + report_fatal_error("Global ifunc must have been declared already"); + + if (LLVMValueRef Resolver = LLVMGetGlobalIFuncResolver(Cur)) { + LLVMSetGlobalIFuncResolver(IFunc, clone_constant(Resolver, M)); + } + + LLVMSetLinkage(IFunc, LLVMGetLinkage(Cur)); + LLVMSetUnnamedAddress(IFunc, LLVMGetUnnamedAddress(Cur)); + + Next = LLVMGetNextGlobalIFunc(Cur); + if (Next == nullptr) { + if (Cur != End) + report_fatal_error("Last global alias does not match End"); + break; + } + + LLVMValueRef Prev = LLVMGetPreviousGlobalIFunc(Next); + if (Prev != Cur) + report_fatal_error("Next.Previous global alias is not Current"); + + Cur = Next; + } + NamedMDClone: LLVMNamedMDNodeRef BeginMD = LLVMGetFirstNamedMetadata(Src); LLVMNamedMDNodeRef EndMD = LLVMGetLastNamedMetadata(Src); |