From e8ba2bfd5d9715752c06a6b2a825b1aded3329ab Mon Sep 17 00:00:00 2001 From: Amaury Sechet Date: Wed, 17 Feb 2016 22:13:33 +0000 Subject: [PATCH] Add support for global variables in the C API echo test Summary: As per title Reviewers: bogner, chandlerc, echristo, dblaikie, joker.eph, Wallbraker Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D17249 llvm-svn: 261164 --- llvm/test/Bindings/llvm-c/echo.ll | 9 ++ llvm/tools/llvm-c-test/echo.cpp | 170 +++++++++++++++++++++++++++++++------- 2 files changed, 147 insertions(+), 32 deletions(-) diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll index 54d37dc..0b6cf0c 100644 --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -7,6 +7,15 @@ target triple = "x86_64-apple-macosx10.11.0" %S = type { i64, %S* } +@var = global i32 42 +@ext = external global i32* +@cst = constant %S { i64 1, %S* @cst } +@tl = thread_local global { i64, %S* } { i64 1, %S* @cst } +@hidden = hidden global i32 7 +@protected = protected global i32 23 +@section = global i32 27, section ".custom" +@align = global i32 31, align 4 + define { i64, %S* } @unpackrepack(%S %s) { %1 = extractvalue %S %s, 0 %2 = extractvalue %S %s, 1 diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp index 8ff75fb..b926c81 100644 --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -221,22 +221,57 @@ LLVMValueRef clone_constant(LLVMValueRef Cst, LLVMModuleRef M) { const char *Name = LLVMGetValueName(Cst); // Try function - if (LLVMIsAFunction(Cst)) - return LLVMGetNamedFunction(M, Name); + if (LLVMIsAFunction(Cst)) { + LLVMValueRef Dst = LLVMGetNamedFunction(M, Name); + if (Dst) + return Dst; + report_fatal_error("Could not find function"); + } // Try global variable - if (LLVMIsAGlobalVariable(Cst)) - return LLVMGetNamedGlobal(M, Name); + if (LLVMIsAGlobalVariable(Cst)) { + LLVMValueRef Dst = LLVMGetNamedGlobal(M, Name); + if (Dst) + return Dst; + report_fatal_error("Could not find function"); + } fprintf(stderr, "Could not find @%s\n", Name); exit(-1); } - // Try literal + // Try integer literal if (LLVMIsAConstantInt(Cst)) return LLVMConstInt(TypeCloner(M).Clone(Cst), LLVMConstIntGetZExtValue(Cst), false); + // Try zeroinitializer + if (LLVMIsAConstantAggregateZero(Cst)) + return LLVMConstNull(TypeCloner(M).Clone(Cst)); + + // Try constant array + if (LLVMIsAConstantArray(Cst)) { + LLVMTypeRef Ty = TypeCloner(M).Clone(Cst); + unsigned EltCount = LLVMGetArrayLength(Ty); + SmallVector Elts; + for (unsigned i = 0; i < EltCount; i++) + Elts.push_back(clone_constant(LLVMGetOperand(Cst, i), M)); + return LLVMConstArray(LLVMGetElementType(Ty), Elts.data(), EltCount); + } + + // Try constant struct + if (LLVMIsAConstantStruct(Cst)) { + LLVMTypeRef Ty = TypeCloner(M).Clone(Cst); + unsigned EltCount = LLVMCountStructElementTypes(Ty); + SmallVector Elts; + for (unsigned i = 0; i < EltCount; i++) + Elts.push_back(clone_constant(LLVMGetOperand(Cst, i), M)); + if (LLVMGetStructName(Ty)) + return LLVMConstNamedStruct(Ty, Elts.data(), EltCount); + return LLVMConstStructInContext(LLVMGetModuleContext(M), Elts.data(), + EltCount, LLVMIsPackedStruct(Ty)); + } + // Try undef if (LLVMIsUndef(Cst)) return LLVMGetUndef(TypeCloner(M).Clone(Cst)); @@ -587,40 +622,53 @@ struct FunCloner { } }; -static void clone_function(LLVMValueRef Src, LLVMModuleRef M) { - const char *Name = LLVMGetValueName(Src); - LLVMValueRef Fun = LLVMGetNamedFunction(M, Name); - if (!Fun) - report_fatal_error("Function must have been declared already"); +static void declare_symbols(LLVMModuleRef Src, LLVMModuleRef M) { + LLVMValueRef Begin = LLVMGetFirstGlobal(Src); + LLVMValueRef End = LLVMGetLastGlobal(Src); + if (!Begin) { + if (End != nullptr) + report_fatal_error("Range has an end but no begining"); + return; + } - FunCloner FC(Src, Fun); - FC.CloneBBs(Src); -} + LLVMValueRef Cur = Begin; + LLVMValueRef Next = nullptr; + while (true) { + const char *Name = LLVMGetValueName(Cur); + if (LLVMGetNamedGlobal(M, Name)) + report_fatal_error("GlobalVariable already cloned"); + LLVMAddGlobal(M, LLVMGetElementType(TypeCloner(M).Clone(Cur)), Name); -static void declare_function(LLVMValueRef Src, LLVMModuleRef M) { - const char *Name = LLVMGetValueName(Src); - LLVMValueRef Fun = LLVMGetNamedFunction(M, Name); - if (Fun != nullptr) - report_fatal_error("Function already cloned"); + Next = LLVMGetNextGlobal(Cur); + if (Next == nullptr) { + if (Cur != End) + report_fatal_error(""); + break; + } - LLVMTypeRef FunTy = LLVMGetElementType(TypeCloner(M).Clone(Src)); - LLVMAddFunction(M, Name, FunTy); -} + LLVMValueRef Prev = LLVMGetPreviousGlobal(Next); + if (Prev != Cur) + report_fatal_error("Next.Previous global is not Current"); + + Cur = Next; + } -static void clone_functions(LLVMModuleRef Src, LLVMModuleRef Dst) { - LLVMValueRef Begin = LLVMGetFirstFunction(Src); - LLVMValueRef End = LLVMGetLastFunction(Src); + Begin = LLVMGetFirstFunction(Src); + End = LLVMGetLastFunction(Src); if (!Begin) { if (End != nullptr) - report_fatal_error("Range has an end but no start"); + report_fatal_error("Range has an end but no begining"); return; } - // First pass, we declare all function - LLVMValueRef Cur = Begin; - LLVMValueRef Next = nullptr; + Cur = Begin; + Next = nullptr; while (true) { - declare_function(Cur, Dst); + const char *Name = LLVMGetValueName(Cur); + if (LLVMGetNamedFunction(M, Name)) + report_fatal_error("Function already cloned"); + LLVMAddFunction(M, Name, LLVMGetElementType(TypeCloner(M).Clone(Cur))); + Next = LLVMGetNextFunction(Cur); if (Next == nullptr) { if (Cur != End) @@ -634,12 +682,69 @@ static void clone_functions(LLVMModuleRef Src, LLVMModuleRef Dst) { Cur = Next; } +} + +static void clone_symbols(LLVMModuleRef Src, LLVMModuleRef M) { + LLVMValueRef Begin = LLVMGetFirstGlobal(Src); + LLVMValueRef End = LLVMGetLastGlobal(Src); + if (!Begin) { + if (End != nullptr) + report_fatal_error("Range has an end but no begining"); + return; + } + + LLVMValueRef Cur = Begin; + LLVMValueRef Next = nullptr; + while (true) { + const char *Name = LLVMGetValueName(Cur); + LLVMValueRef G = LLVMGetNamedGlobal(M, Name); + if (!G) + report_fatal_error("GlobalVariable must have been declared already"); + + if (auto I = LLVMGetInitializer(Cur)) + LLVMSetInitializer(G, clone_constant(I, M)); + + LLVMSetGlobalConstant(G, LLVMIsGlobalConstant(Cur)); + LLVMSetThreadLocal(G, LLVMIsThreadLocal(Cur)); + LLVMSetExternallyInitialized(G, LLVMIsExternallyInitialized(Cur)); + LLVMSetLinkage(G, LLVMGetLinkage(Cur)); + LLVMSetSection(G, LLVMGetSection(Cur)); + LLVMSetVisibility(G, LLVMGetVisibility(Cur)); + LLVMSetUnnamedAddr(G, LLVMHasUnnamedAddr(Cur)); + LLVMSetAlignment(G, LLVMGetAlignment(Cur)); + + Next = LLVMGetNextGlobal(Cur); + if (Next == nullptr) { + if (Cur != End) + report_fatal_error(""); + break; + } + + LLVMValueRef Prev = LLVMGetPreviousGlobal(Next); + if (Prev != Cur) + report_fatal_error("Next.Previous global is not Current"); + + Cur = Next; + } + + Begin = LLVMGetFirstFunction(Src); + End = LLVMGetLastFunction(Src); + if (!Begin) { + if (End != nullptr) + report_fatal_error("Range has an end but no begining"); + return; + } - // Second pass, we define them Cur = Begin; Next = nullptr; while (true) { - clone_function(Cur, Dst); + const char *Name = LLVMGetValueName(Cur); + LLVMValueRef Fun = LLVMGetNamedFunction(M, Name); + if (!Fun) + report_fatal_error("Function must have been declared already"); + FunCloner FC(Cur, Fun); + FC.CloneBBs(Cur); + Next = LLVMGetNextFunction(Cur); if (Next == nullptr) { if (Cur != End) @@ -668,7 +773,8 @@ int llvm_echo(void) { if (strcmp(LLVMGetDataLayoutStr(M), LLVMGetDataLayoutStr(Src))) report_fatal_error("Inconsistent DataLayout string representation"); - clone_functions(Src, M); + declare_symbols(Src, M); + clone_symbols(Src, M); char *Str = LLVMPrintModuleToString(M); fputs(Str, stdout); -- 2.7.4