diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -3636,7 +3636,7 @@ /* Get the number of clauses on the landingpad instruction */ unsigned LLVMGetNumClauses(LLVMValueRef LandingPad); -/* Get the value of the clause at idnex Idx on the landingpad instruction */ +/* Get the value of the clause at index Idx on the landingpad instruction */ LLVMValueRef LLVMGetClause(LLVMValueRef LandingPad, unsigned Idx); /* Add a catch or filter clause to the landingpad instruction */ @@ -3937,6 +3937,19 @@ LLVMAtomicOrdering FailureOrdering, LLVMBool SingleThread); +/** + * Get the number of elements in the mask of a ShuffleVector instruction. + */ +unsigned LLVMGetNumMaskElements(LLVMValueRef ShuffleVectorInst); + +/** + * Get the mask value at position Elt in the mask of a ShuffleVector + * instruction. Return LLVMUndefMaskElem if the mask value is undef at that + * position. + */ +int LLVMGetMaskValue(LLVMValueRef ShuffleVectorInst, unsigned Elt); +extern const int LLVMUndefMaskElem; + LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst); void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool SingleThread); diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -3952,6 +3952,20 @@ singleThread ? SyncScope::SingleThread : SyncScope::System)); } +unsigned LLVMGetNumMaskElements(LLVMValueRef SVInst) { + Value *P = unwrap(SVInst); + ShuffleVectorInst *I = cast(P); + return I->getShuffleMask().size(); +} + +int LLVMGetMaskValue(LLVMValueRef SVInst, unsigned Elt) { + Value *P = unwrap(SVInst); + ShuffleVectorInst *I = cast(P); + return I->getMaskValue(Elt); +} +const int LLVMUndefMaskElem = + -1; // not actually accessible as ShuffleVectorInst::UndefMaskElem, so we + // hardcode it here LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) { Value *P = unwrap(AtomicInst); diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -156,6 +156,24 @@ ret void } +define i32 @vectorops(i32, i32) { + %a = insertelement <4 x i32> undef, i32 %0, i32 0 + %b = insertelement <4 x i32> %a, i32 %1, i32 2 + %c = shufflevector <4 x i32> %b, <4 x i32> undef, <4 x i32> zeroinitializer + %d = shufflevector <4 x i32> %c, <4 x i32> %b, <4 x i32> + %e = add <4 x i32> %d, %a + %f = mul <4 x i32> %e, %b + %g = xor <4 x i32> %f, %d + %h = or <4 x i32> %f, %e + %i = lshr <4 x i32> %h, + %j = shl <4 x i32> %i, + %k = shufflevector <4 x i32> %j, <4 x i32> %i, <4 x i32> + %m = shufflevector <4 x i32> %k, <4 x i32> undef, <1 x i32> + %n = shufflevector <4 x i32> %j, <4 x i32> undef, <8 x i32> + %p = extractelement <8 x i32> %n, i32 5 + ret i32 %p +} + declare void @personalityFn() define void @exn() personality void ()* @personalityFn { diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -30,7 +30,7 @@ struct CAPIDenseMap {}; // The default DenseMapInfo require to know about pointer alignment. -// Because the C API uses opaques pointer types, their alignment is unknown. +// Because the C API uses opaque pointer types, their alignment is unknown. // As a result, we need to roll out our own implementation. template struct CAPIDenseMap { @@ -306,7 +306,7 @@ return LLVMConstArray(LLVMGetElementType(Ty), Elts.data(), EltCount); } - // Try contant data array + // Try constant data array if (LLVMIsAConstantDataArray(Cst)) { check_value_kind(Cst, LLVMConstantDataArrayValueKind); LLVMTypeRef Ty = TypeCloner(M).Clone(Cst); @@ -357,9 +357,32 @@ report_fatal_error("ConstantFP is not supported"); } - // This kind of constant is not supported + // Try ConstantVector + if (LLVMIsAConstantVector(Cst)) { + check_value_kind(Cst, LLVMConstantVectorValueKind); + LLVMTypeRef Ty = TypeCloner(M).Clone(Cst); + unsigned EltCount = LLVMGetVectorSize(Ty); + SmallVector Elts; + for (unsigned i = 0; i < EltCount; i++) + Elts.push_back(clone_constant(LLVMGetOperand(Cst, i), M)); + return LLVMConstVector(Elts.data(), EltCount); + } + + // Try ConstantDataVector + if (LLVMIsAConstantDataVector(Cst)) { + check_value_kind(Cst, LLVMConstantDataVectorValueKind); + LLVMTypeRef Ty = TypeCloner(M).Clone(Cst); + unsigned EltCount = LLVMGetVectorSize(Ty); + SmallVector Elts; + for (unsigned i = 0; i < EltCount; i++) + Elts.push_back(clone_constant(LLVMGetElementAsConstant(Cst, i), M)); + return LLVMConstVector(Elts.data(), EltCount); + } + + // At this point, if it's not a constant expression, it's a kind of constant + // which is not supported if (!LLVMIsAConstantExpr(Cst)) - report_fatal_error("Expected a constant expression"); + report_fatal_error("Unsupported constant kind"); // At this point, it must be a constant expression check_value_kind(Cst, LLVMConstantExprValueKind); @@ -370,7 +393,8 @@ return LLVMConstBitCast(clone_constant(LLVMGetOperand(Cst, 0), M), TypeCloner(M).Clone(Cst)); default: - fprintf(stderr, "%d is not a supported opcode\n", Op); + fprintf(stderr, "%d is not a supported opcode for constant expressions\n", + Op); exit(-1); } } @@ -443,7 +467,7 @@ auto i = VMap.find(Src); if (i != VMap.end()) { // If we have a hit, it means we already generated the instruction - // as a dependancy to somethign else. We need to make sure + // as a dependency to something else. We need to make sure // it is ordered properly. auto I = i->second; LLVMInstructionRemoveFromParent(I); @@ -746,8 +770,10 @@ } case LLVMExtractValue: { LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0)); - if (LLVMGetNumIndices(Src) != 1) - report_fatal_error("Expected only one indice"); + if (LLVMGetNumIndices(Src) > 1) + report_fatal_error("ExtractValue: Expected only one index"); + else if (LLVMGetNumIndices(Src) < 1) + report_fatal_error("ExtractValue: Expected an index"); auto I = LLVMGetIndices(Src)[0]; Dst = LLVMBuildExtractValue(Builder, Agg, I, Name); break; @@ -755,12 +781,47 @@ case LLVMInsertValue: { LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0)); LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 1)); - if (LLVMGetNumIndices(Src) != 1) - report_fatal_error("Expected only one indice"); + if (LLVMGetNumIndices(Src) > 1) + report_fatal_error("InsertValue: Expected only one index"); + else if (LLVMGetNumIndices(Src) < 1) + report_fatal_error("InsertValue: Expected an index"); auto I = LLVMGetIndices(Src)[0]; Dst = LLVMBuildInsertValue(Builder, Agg, V, I, Name); break; } + case LLVMExtractElement: { + LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0)); + LLVMValueRef Index = CloneValue(LLVMGetOperand(Src, 1)); + Dst = LLVMBuildExtractElement(Builder, Agg, Index, Name); + break; + } + case LLVMInsertElement: { + LLVMValueRef Agg = CloneValue(LLVMGetOperand(Src, 0)); + LLVMValueRef V = CloneValue(LLVMGetOperand(Src, 1)); + LLVMValueRef Index = CloneValue(LLVMGetOperand(Src, 2)); + Dst = LLVMBuildInsertElement(Builder, Agg, V, Index, Name); + break; + } + case LLVMShuffleVector: { + LLVMValueRef Agg0 = CloneValue(LLVMGetOperand(Src, 0)); + LLVMValueRef Agg1 = CloneValue(LLVMGetOperand(Src, 1)); + unsigned NumMaskElts = LLVMGetNumMaskElements(Src); + if (NumMaskElts > 8) + report_fatal_error( + "ShuffleVector: Expected no more than 8 mask elements"); + LLVMValueRef MaskElts[8]; + for (unsigned i = 0; i < NumMaskElts; i++) { + int Val = LLVMGetMaskValue(Src, i); + if (Val == LLVMUndefMaskElem) { + MaskElts[i] = LLVMGetUndef(LLVMInt64Type()); + } else { + MaskElts[i] = LLVMConstInt(LLVMInt64Type(), Val, true); + } + } + LLVMValueRef Mask = LLVMConstVector(&MaskElts[0], NumMaskElts); + Dst = LLVMBuildShuffleVector(Builder, Agg0, Agg1, Mask, Name); + break; + } case LLVMFreeze: { LLVMValueRef Arg = CloneValue(LLVMGetOperand(Src, 0)); Dst = LLVMBuildFreeze(Builder, Arg, Name); @@ -1102,7 +1163,7 @@ LLVMGlobalSetMetadata(G, Kind, MD); } LLVMDisposeValueMetadataEntries(AllMetadata); - + LLVMSetGlobalConstant(G, LLVMIsGlobalConstant(Cur)); LLVMSetThreadLocal(G, LLVMIsThreadLocal(Cur)); LLVMSetExternallyInitialized(G, LLVMIsExternallyInitialized(Cur)); diff --git a/llvm/tools/llvm-c-test/main.c b/llvm/tools/llvm-c-test/main.c --- a/llvm/tools/llvm-c-test/main.c +++ b/llvm/tools/llvm-c-test/main.c @@ -36,10 +36,10 @@ fprintf(stderr, " * --targets-list\n"); fprintf(stderr, " List available targets\n\n"); fprintf(stderr, " * --object-list-sections\n"); - fprintf(stderr, " Read object file form stdin - list sections\n\n"); + fprintf(stderr, " Read object file from stdin - list sections\n\n"); fprintf(stderr, " * --object-list-symbols\n"); fprintf(stderr, - " Read object file form stdin - list symbols (like nm)\n\n"); + " Read object file from stdin - list symbols (like nm)\n\n"); fprintf(stderr, " * --disassemble\n"); fprintf(stderr, " Read lines of triple, hex ascii machine code from stdin " "- print disassembly\n\n"); @@ -48,11 +48,10 @@ stderr, " Read lines of name, rpn from stdin - print generated module\n\n"); fprintf(stderr, " * --echo\n"); - fprintf(stderr, - " Read bitcode file form stdin - print it back out\n\n"); + fprintf(stderr, " Read bitcode file from stdin - print it back out\n\n"); fprintf(stderr, " * --test-diagnostic-handler\n"); fprintf(stderr, - " Read bitcode file form stdin with a diagnostic handler set\n\n"); + " Read bitcode file from stdin with a diagnostic handler set\n\n"); fprintf(stderr, " * --test-dibuilder\n"); fprintf(stderr, " Run tests for the DIBuilder C API - print generated module\n\n");