mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
Split clone value and instruction in the echo C API test
Summary: This is a bit of refactoring required to be able to generate instruction in forward basic block. This, for instance, is a requirement for phi in loops. Reviewers: bogner, chandlerc, echristo, dblaikie, joker.eph, Wallbraker Differential Revision: http://reviews.llvm.org/D17050 llvm-svn: 260324
This commit is contained in:
parent
352aef6336
commit
dfe90fdcf0
@ -125,46 +125,26 @@ static LLVMTypeRef clone_type(LLVMTypeRef Src, LLVMContextRef Ctx) {
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMValueRef clone_literal(LLVMValueRef Src, LLVMContextRef Ctx) {
|
|
||||||
LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);
|
|
||||||
|
|
||||||
LLVMTypeKind Kind = LLVMGetTypeKind(Ty);
|
|
||||||
switch (Kind) {
|
|
||||||
case LLVMIntegerTypeKind:
|
|
||||||
return LLVMConstInt(Ty, LLVMConstIntGetZExtValue(Src), false);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "%d is not a supported constant typekind\n", Kind);
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static LLVMModuleRef get_module(LLVMBuilderRef Builder) {
|
|
||||||
LLVMBasicBlockRef BB = LLVMGetInsertBlock(Builder);
|
|
||||||
LLVMValueRef Fn = LLVMGetBasicBlockParent(BB);
|
|
||||||
return LLVMGetGlobalParent(Fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst);
|
static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst);
|
||||||
|
|
||||||
struct FunCloner {
|
struct FunCloner {
|
||||||
LLVMValueRef Fun;
|
LLVMValueRef Fun;
|
||||||
|
LLVMModuleRef M;
|
||||||
|
LLVMContextRef Ctx;
|
||||||
|
|
||||||
ValueMap VMap;
|
ValueMap VMap;
|
||||||
BasicBlockMap BBMap;
|
BasicBlockMap BBMap;
|
||||||
|
|
||||||
FunCloner(LLVMValueRef Src, LLVMValueRef Dst)
|
FunCloner(LLVMValueRef Src, LLVMValueRef Dst)
|
||||||
: Fun(Dst), VMap(clone_params(Src, Dst)) {}
|
: Fun(Dst), M(LLVMGetGlobalParent(Fun)), Ctx(LLVMGetModuleContext(M)),
|
||||||
|
VMap(clone_params(Src, Dst)) {}
|
||||||
|
|
||||||
// Try to clone everything in the llvm::Value hierarchy.
|
// Try to clone everything in the llvm::Value hierarchy.
|
||||||
LLVMValueRef CloneValue(LLVMValueRef Src, LLVMBuilderRef Builder) {
|
LLVMValueRef CloneValue(LLVMValueRef Src) {
|
||||||
const char *Name = LLVMGetValueName(Src);
|
const char *Name = LLVMGetValueName(Src);
|
||||||
|
|
||||||
// First, the value may be constant.
|
// First, the value may be constant.
|
||||||
if (LLVMIsAConstant(Src)) {
|
if (LLVMIsAConstant(Src)) {
|
||||||
LLVMModuleRef M = get_module(Builder);
|
|
||||||
|
|
||||||
// Maybe it is a symbol
|
// Maybe it is a symbol
|
||||||
if (LLVMIsAGlobalValue(Src)) {
|
if (LLVMIsAGlobalValue(Src)) {
|
||||||
// Try function
|
// Try function
|
||||||
@ -182,17 +162,44 @@ struct FunCloner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try literal
|
// Try literal
|
||||||
LLVMContextRef Ctx = LLVMGetModuleContext(M);
|
if (LLVMIsAConstantInt(Src)) {
|
||||||
return clone_literal(Src, Ctx);
|
LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);
|
||||||
|
return LLVMConstInt(Ty, LLVMConstIntGetZExtValue(Src), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try undef
|
||||||
|
if (LLVMIsUndef(Src))
|
||||||
|
return LLVMGetUndef(clone_type(LLVMTypeOf(Src), Ctx));
|
||||||
|
|
||||||
|
// This kind of constant is not supported.
|
||||||
|
report_fatal_error("Unsupported contant type");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try undef
|
// Function argument should always be in the map already.
|
||||||
if (LLVMIsUndef(Src)) {
|
if (LLVMIsAArgument(Src)) {
|
||||||
LLVMContextRef Ctx = LLVMGetModuleContext(get_module(Builder));
|
auto i = VMap.find(Src);
|
||||||
LLVMTypeRef Ty = clone_type(LLVMTypeOf(Src), Ctx);
|
if (i != VMap.end())
|
||||||
return LLVMGetUndef(Ty);
|
return i->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LLVMIsAInstruction(Src)) {
|
||||||
|
auto Builder = LLVMCreateBuilderInContext(Ctx);
|
||||||
|
auto BB = DeclareBB(LLVMGetInstructionParent(Src));
|
||||||
|
LLVMPositionBuilderAtEnd(Builder, BB);
|
||||||
|
auto Dst = CloneInstruction(Src, Builder);
|
||||||
|
LLVMDisposeBuilder(Builder);
|
||||||
|
return Dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Could not determine the type of %s\n", Name);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMValueRef CloneInstruction(LLVMValueRef Src, LLVMBuilderRef Builder) {
|
||||||
|
const char *Name = LLVMGetValueName(Src);
|
||||||
|
if (!LLVMIsAInstruction(Src))
|
||||||
|
report_fatal_error("Expected an instruction");
|
||||||
|
|
||||||
// Check if this is something we already computed.
|
// Check if this is something we already computed.
|
||||||
{
|
{
|
||||||
auto i = VMap.find(Src);
|
auto i = VMap.find(Src);
|
||||||
@ -211,8 +218,7 @@ struct FunCloner {
|
|||||||
if (OpCount == 0)
|
if (OpCount == 0)
|
||||||
Dst = LLVMBuildRetVoid(Builder);
|
Dst = LLVMBuildRetVoid(Builder);
|
||||||
else
|
else
|
||||||
Dst = LLVMBuildRet(Builder, CloneValue(LLVMGetOperand(Src, 0),
|
Dst = LLVMBuildRet(Builder, CloneValue(LLVMGetOperand(Src, 0)));
|
||||||
Builder));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMBr: {
|
case LLVMBr: {
|
||||||
@ -239,102 +245,101 @@ struct FunCloner {
|
|||||||
Dst = LLVMBuildUnreachable(Builder);
|
Dst = LLVMBuildUnreachable(Builder);
|
||||||
break;
|
break;
|
||||||
case LLVMAdd: {
|
case LLVMAdd: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildAdd(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildAdd(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMSub: {
|
case LLVMSub: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildSub(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildSub(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMMul: {
|
case LLVMMul: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildMul(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildMul(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMUDiv: {
|
case LLVMUDiv: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildUDiv(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildUDiv(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMSDiv: {
|
case LLVMSDiv: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildSDiv(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildSDiv(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMURem: {
|
case LLVMURem: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildURem(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildURem(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMSRem: {
|
case LLVMSRem: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildSRem(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildSRem(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMShl: {
|
case LLVMShl: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildShl(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildShl(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMLShr: {
|
case LLVMLShr: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildLShr(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildLShr(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMAShr: {
|
case LLVMAShr: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildAShr(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildAShr(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMAnd: {
|
case LLVMAnd: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildAnd(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildAnd(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMOr: {
|
case LLVMOr: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildOr(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildOr(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMXor: {
|
case LLVMXor: {
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildXor(Builder, LHS, RHS, Name);
|
Dst = LLVMBuildXor(Builder, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMAlloca: {
|
case LLVMAlloca: {
|
||||||
LLVMContextRef Ctx = LLVMGetModuleContext(get_module(Builder));
|
|
||||||
LLVMTypeRef Ty = clone_type(LLVMGetAllocatedType(Src), Ctx);
|
LLVMTypeRef Ty = clone_type(LLVMGetAllocatedType(Src), Ctx);
|
||||||
Dst = LLVMBuildAlloca(Builder, Ty, Name);
|
Dst = LLVMBuildAlloca(Builder, Ty, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMICmp: {
|
case LLVMICmp: {
|
||||||
LLVMIntPredicate Pred = LLVMGetICmpPredicate(Src);
|
LLVMIntPredicate Pred = LLVMGetICmpPredicate(Src);
|
||||||
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0), Builder);
|
LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
|
||||||
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1), Builder);
|
LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
|
||||||
Dst = LLVMBuildICmp(Builder, Pred, LHS, RHS, Name);
|
Dst = LLVMBuildICmp(Builder, Pred, LHS, RHS, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LLVMCall: {
|
case LLVMCall: {
|
||||||
int ArgCount = LLVMGetNumOperands(Src) - 1;
|
|
||||||
SmallVector<LLVMValueRef, 8> Args;
|
SmallVector<LLVMValueRef, 8> Args;
|
||||||
|
int ArgCount = LLVMGetNumOperands(Src) - 1;
|
||||||
for (int i = 0; i < ArgCount; i++)
|
for (int i = 0; i < ArgCount; i++)
|
||||||
Args.push_back(CloneValue(LLVMGetOperand(Src, i), Builder));
|
Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
|
||||||
LLVMValueRef Fn = CloneValue(LLVMGetOperand(Src, ArgCount), Builder);
|
LLVMValueRef Fn = CloneValue(LLVMGetOperand(Src, ArgCount));
|
||||||
Dst = LLVMBuildCall(Builder, Fn, Args.data(), ArgCount, Name);
|
Dst = LLVMBuildCall(Builder, Fn, Args.data(), ArgCount, Name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -363,7 +368,7 @@ struct FunCloner {
|
|||||||
|
|
||||||
LLVMValueRef V = LLVMBasicBlockAsValue(Src);
|
LLVMValueRef V = LLVMBasicBlockAsValue(Src);
|
||||||
if (!LLVMValueIsBasicBlock(V) || LLVMValueAsBasicBlock(V) != Src)
|
if (!LLVMValueIsBasicBlock(V) || LLVMValueAsBasicBlock(V) != Src)
|
||||||
report_fatal_error("Basic block is not a basic block\n");
|
report_fatal_error("Basic block is not a basic block");
|
||||||
|
|
||||||
const char *VName = LLVMGetValueName(V);
|
const char *VName = LLVMGetValueName(V);
|
||||||
if (Name != VName)
|
if (Name != VName)
|
||||||
@ -393,14 +398,13 @@ struct FunCloner {
|
|||||||
return BB;
|
return BB;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLVMContextRef Ctx = LLVMGetModuleContext(LLVMGetGlobalParent(Fun));
|
|
||||||
LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);
|
LLVMBuilderRef Builder = LLVMCreateBuilderInContext(Ctx);
|
||||||
LLVMPositionBuilderAtEnd(Builder, BB);
|
LLVMPositionBuilderAtEnd(Builder, BB);
|
||||||
|
|
||||||
LLVMValueRef Cur = First;
|
LLVMValueRef Cur = First;
|
||||||
LLVMValueRef Next = nullptr;
|
LLVMValueRef Next = nullptr;
|
||||||
while(true) {
|
while(true) {
|
||||||
CloneValue(Cur, Builder);
|
CloneInstruction(Cur, Builder);
|
||||||
Next = LLVMGetNextInstruction(Cur);
|
Next = LLVMGetNextInstruction(Cur);
|
||||||
if (Next == nullptr) {
|
if (Next == nullptr) {
|
||||||
if (Cur != Last) {
|
if (Cur != Last) {
|
||||||
@ -540,17 +544,17 @@ static ValueMap clone_params(LLVMValueRef Src, LLVMValueRef Dst) {
|
|||||||
return VMap;
|
return VMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMValueRef clone_function(LLVMValueRef Src, LLVMModuleRef Dst) {
|
static LLVMValueRef clone_function(LLVMValueRef Src, LLVMModuleRef M) {
|
||||||
const char *Name = LLVMGetValueName(Src);
|
const char *Name = LLVMGetValueName(Src);
|
||||||
LLVMValueRef Fun = LLVMGetNamedFunction(Dst, Name);
|
LLVMValueRef Fun = LLVMGetNamedFunction(M, Name);
|
||||||
if (Fun != nullptr)
|
if (Fun != nullptr)
|
||||||
return Fun;
|
return Fun;
|
||||||
|
|
||||||
LLVMTypeRef SrcTy = LLVMTypeOf(Src);
|
LLVMTypeRef SrcTy = LLVMTypeOf(Src);
|
||||||
LLVMTypeRef DstTy = clone_type(SrcTy, LLVMGetModuleContext(Dst));
|
LLVMTypeRef DstTy = clone_type(SrcTy, LLVMGetModuleContext(M));
|
||||||
LLVMTypeRef FunTy = LLVMGetElementType(DstTy);
|
LLVMTypeRef FunTy = LLVMGetElementType(DstTy);
|
||||||
|
|
||||||
Fun = LLVMAddFunction(Dst, Name, FunTy);
|
Fun = LLVMAddFunction(M, Name, FunTy);
|
||||||
FunCloner FC(Src, Fun);
|
FunCloner FC(Src, Fun);
|
||||||
FC.CloneBBs(Src);
|
FC.CloneBBs(Src);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user