Index: test/Bindings/llvm-c/echo.ll =================================================================== --- test/Bindings/llvm-c/echo.ll +++ test/Bindings/llvm-c/echo.ll @@ -4,6 +4,11 @@ %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 } + define { i64, %S* } @unpackrepack(%S %s) { %1 = extractvalue %S %s, 0 %2 = extractvalue %S %s, 1 Index: tools/llvm-c-test/echo.cpp =================================================================== --- tools/llvm-c-test/echo.cpp +++ tools/llvm-c-test/echo.cpp @@ -233,16 +233,47 @@ 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)); - // This kind of constant is not supported. + // Try float literal + if (LLVMIsAConstantFP(Cst)) + report_fatal_error("How do I generate FP constant ?"); + + // This kind of constant is not supported report_fatal_error("Unsupported contant type"); } @@ -621,6 +652,43 @@ } } +static void clone_globals(LLVMModuleRef Src, LLVMModuleRef M) { + LLVMValueRef Begin = LLVMGetFirstGlobal(Src); + LLVMValueRef End = LLVMGetLastGlobal(Src); + + LLVMValueRef Cur = Begin; + LLVMValueRef Next = nullptr; + while (true) { + const char *Name = LLVMGetValueName(Cur); + if (LLVMGetNamedGlobal(M, Name)) + continue; + + LLVMTypeRef SrcTy = LLVMGetElementType(LLVMTypeOf(Cur)); + LLVMTypeRef DstTy = TypeCloner(M).Clone(SrcTy); + LLVMValueRef G = LLVMAddGlobal(M, DstTy, Name); + + if (auto I = LLVMGetInitializer(Cur)) + LLVMSetInitializer(G, clone_constant(I, M)); + + LLVMSetGlobalConstant(G, LLVMIsGlobalConstant(Cur)); + LLVMSetThreadLocal(G, LLVMIsThreadLocal(Cur)); + LLVMSetExternallyInitialized(G, LLVMIsExternallyInitialized(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; + } +} + int llvm_echo(void) { LLVMEnablePrettyStackTrace(); @@ -629,6 +697,7 @@ LLVMContextRef Ctx = LLVMContextCreate(); LLVMModuleRef M = LLVMModuleCreateWithNameInContext("", Ctx); + clone_globals(Src, M); clone_functions(Src, M); char *Str = LLVMPrintModuleToString(M); fputs(Str, stdout);