aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Seaborn <mseaborn@chromium.org>2013-09-05 09:41:53 -0700
committerMark Seaborn <mseaborn@chromium.org>2013-09-05 09:41:53 -0700
commitcd4a14419f49fb236d65e5b69d871d6fc61fcb99 (patch)
treeddb320f736845f4aa93ef3ab42400f1fbf69584e
parent1180f259c88b1eb1000d0aaf5753b3da9f8e4e51 (diff)
PNaCl bitcode: Indirect calls: Store return type instead of function type
For indirect call instructions (INST_CALL_INDIRECT), it's not necessary to store the full function type. The argument types are already known from the arguments in the instruction. We only need to store the return type to be able to reconstruct the full function type. Storing only the return type ID will make the bitcode a little more compact. Return type IDs will be frequently-used scalar types, which can be given smaller type IDs than function types, which are less frequently used. This potentially makes the writer simpler: In principle, the writer no longer needs to make a pass across all functions' bodies to determine which function types are used in order to build the type table. BUG=https://code.google.com/p/nativeclient/issues/detail?id=3544 TEST=*.ll tests Review URL: https://codereview.chromium.org/23521005
-rw-r--r--include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h2
-rw-r--r--lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp31
-rw-r--r--lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp6
-rw-r--r--test/NaCl/Bitcode/call-elide.ll18
4 files changed, 30 insertions, 27 deletions
diff --git a/include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h b/include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h
index 384b03661e..2e3cd21652 100644
--- a/include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h
+++ b/include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h
@@ -331,7 +331,7 @@ namespace naclbitc {
FUNC_CODE_INST_LOADATOMIC = 41, // Not used in PNaCl.
FUNC_CODE_INST_STOREATOMIC = 42, // Not used in PNaCl.
FUNC_CODE_INST_FORWARDTYPEREF = 43, // TYPE: [opval, ty]
- // PNaCl version 2+: CALL_INDIRECT: [cc, fnid, fnty, args...]
+ // PNaCl version 2+: CALL_INDIRECT: [cc, fnid, returnty, args...]
FUNC_CODE_INST_CALL_INDIRECT = 44
};
} // End naclbitc namespace
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
index eaaa85a164..29a842c948 100644
--- a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
+++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp
@@ -1626,16 +1626,11 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
// Build function type for call.
FunctionType *FTy = 0;
+ Type *ReturnType = 0;
if (BitCode == naclbitc::FUNC_CODE_INST_CALL_INDIRECT) {
// Callee type has been elided, add back in.
- Type *Type = getTypeByID(Record[2]);
+ ReturnType = getTypeByID(Record[2]);
++OpNum;
- if (FunctionType *FcnType = dyn_cast<FunctionType>(Type)) {
- FTy = FcnType;
- Callee = ConvertOpToType(Callee, FcnType->getPointerTo(), CurBBNo);
- } else {
- return Error("Invalid type for CALL_INDIRECT record");
- }
} else {
// Get type signature from callee.
if (PointerType *OpTy = dyn_cast<PointerType>(Callee->getType())) {
@@ -1646,7 +1641,7 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
}
unsigned NumParams = Record.size() - OpNum;
- if (NumParams != FTy->getNumParams())
+ if (FTy && NumParams != FTy->getNumParams())
return Error("Invalid CALL record");
// Process call arguments.
@@ -1655,14 +1650,26 @@ bool NaClBitcodeReader::ParseFunctionBody(Function *F) {
Value *Arg;
if (popValue(Record, &OpNum, NextValueNo, &Arg))
Error("Invalid argument in CALL record");
- if (BitCode == naclbitc::FUNC_CODE_INST_CALL_INDIRECT &&
- FTy->getParamType(Index)->isPointerTy()) {
- return Error("Pointer arguments not allowed for indirect calls");
+ if (FTy) {
+ // Add a cast, to a pointer type if necessary, in case this
+ // is an intrinsic call that takes a pointer argument.
+ Arg = ConvertOpToType(Arg, FTy->getParamType(Index), CurBBNo);
+ } else {
+ Arg = ConvertOpToScalar(Arg, CurBBNo);
}
- Arg = ConvertOpToType(Arg, FTy->getParamType(Index), CurBBNo);
Args.push_back(Arg);
}
+ if (FTy == 0) {
+ // Reconstruct the function type and cast the function pointer
+ // to it.
+ SmallVector<Type*, 6> ArgTypes;
+ for (unsigned Index = 0; Index < NumParams; ++Index)
+ ArgTypes.push_back(Args[Index]->getType());
+ FTy = FunctionType::get(ReturnType, ArgTypes, false);
+ Callee = ConvertOpToType(Callee, FTy->getPointerTo(), CurBBNo);
+ }
+
// Construct call.
I = CallInst::Create(Callee, Args);
cast<CallInst>(I)->setCallingConv(GetDecodedCallingConv(CCInfo>>1));
diff --git a/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp b/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
index 166a95bb23..4288aceb06 100644
--- a/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
+++ b/lib/Bitcode/NaCl/Writer/NaClBitcodeWriter.cpp
@@ -893,11 +893,7 @@ static bool WriteInstruction(const Instruction &I, unsigned InstID,
// not known. Hence, we must send the type signature to the
// reader.
Code = naclbitc::FUNC_CODE_INST_CALL_INDIRECT;
- PointerType *FcnPtrType =
- cast<PointerType>(Callee->getType());
- FunctionType *FcnType =
- cast<FunctionType>(FcnPtrType->getElementType());
- Vals.push_back(VE.getTypeID(FcnType));
+ Vals.push_back(VE.getTypeID(I.getType()));
}
}
diff --git a/test/NaCl/Bitcode/call-elide.ll b/test/NaCl/Bitcode/call-elide.ll
index adcd32a904..d7b93516cd 100644
--- a/test/NaCl/Bitcode/call-elide.ll
+++ b/test/NaCl/Bitcode/call-elide.ll
@@ -226,7 +226,7 @@ define void @IndirectCall(i32 %i) {
; PF2: <FUNCTION_BLOCK>
; PF2-NEXT: <DECLAREBLOCKS op0=1/>
-; PF2-NEXT: <INST_CALL_INDIRECT op0=0 op1=1 op2=2 op3=1/>
+; PF2-NEXT: <INST_CALL_INDIRECT op0=0 op1=1 op2=1 op3=1/>
; PF2-NEXT: <INST_RET/>
; PF2: </FUNCTION_BLOCK>
@@ -260,16 +260,16 @@ define void @IndirectCallPtrToIntArg(i32 %i) {
; TD2: define void @IndirectCallPtrToIntArg(i32 %i) {
; TD2-NEXT: %1 = alloca i8, i32 4, align 8
-; TD2-NEXT: %2 = inttoptr i32 %i to void (i32)*
-; TD2-NEXT: %3 = ptrtoint i8* %1 to i32
-; TD2-NEXT: call void %2(i32 %3)
+; TD2-NEXT: %2 = ptrtoint i8* %1 to i32
+; TD2-NEXT: %3 = inttoptr i32 %i to void (i32)*
+; TD2-NEXT: call void %3(i32 %2)
; TD2-NEXT: ret void
; TD2-NEXT: }
; PF2: <FUNCTION_BLOCK>
; PF2: </CONSTANTS_BLOCK>
; PF2-NEXT: <INST_ALLOCA op0=1 op1=4/>
-; PF2-NEXT: <INST_CALL_INDIRECT op0=0 op1=3 op2=2 op3=1/>
+; PF2-NEXT: <INST_CALL_INDIRECT op0=0 op1=3 op2=1 op3=1/>
; PF2-NEXT: <INST_RET/>
; PF2: </FUNCTION_BLOCK>
@@ -299,15 +299,15 @@ define void @IndirectCallScalarArg(i32 %i, i32* %ptr) {
; PF1: </FUNCTION_BLOCK>
; TD2: define void @IndirectCallScalarArg(i32 %i, i32* %ptr) {
-; TD2-NEXT: %1 = inttoptr i32 %i to void (i32)*
-; TD2-NEXT: %2 = ptrtoint [4 x i8]* @bytes to i32
-; TD2-NEXT: call void %1(i32 %2)
+; TD2-NEXT: %1 = ptrtoint [4 x i8]* @bytes to i32
+; TD2-NEXT: %2 = inttoptr i32 %i to void (i32)*
+; TD2-NEXT: call void %2(i32 %1)
; TD2-NEXT: ret void
; TD2-NEXT: }
; PF2: <FUNCTION_BLOCK>
; PF2-NEXT: <DECLAREBLOCKS op0=1/>
-; PF2-NEXT: <INST_CALL_INDIRECT op0=0 op1=2 op2=2 op3=3/>
+; PF2-NEXT: <INST_CALL_INDIRECT op0=0 op1=2 op2=1 op3=3/>
; PF2-NEXT: <INST_RET/>
; PF2: </FUNCTION_BLOCK>