llvm.org GIT mirror llvm / b0c9b93
I noticed that the trampoline straightening transformation could drop attributes on varargs call arguments. Also, it could generate invalid IR if the transformed call already had the 'nest' attribute somewhere (this can never happen for code coming from llvm-gcc, but it's a theoretical possibility). Fix both problems. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45973 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan Sands 11 years ago
5 changed file(s) with 91 addition(s) and 23 deletion(s). Raw diff Collapse all Expand all
5252 const uint16_t ReturnOnly = NoReturn | NoUnwind | ReadNone | ReadOnly;
5353
5454 /// @brief Parameter attributes that do not apply to vararg call arguments.
55 const uint16_t VarArgsIncompatible = Nest | StructRet;
55 const uint16_t VarArgsIncompatible = StructRet;
5656
5757 /// @brief Attributes that are mutually incompatible.
5858 const uint16_t MutuallyIncompatible[3] = {
170170 return getParamAttrs(i) & attr;
171171 }
172172
173 /// This returns whether the given attribute is set for at least one
174 /// parameter or for the return value.
175 /// @returns true if the parameter attribute is set somewhere
176 /// @brief Determine if a ParameterAttributes is set somewhere
177 bool hasAttrSomewhere(ParameterAttributes attr) const;
178
173179 /// The set of ParameterAttributes set in Attributes is converted to a
174180 /// string of equivalent mnemonics. This is, presumably, for writing out
175181 /// the mnemonics for the assembly writer.
83848384 Value *Callee = CS.getCalledValue();
83858385 const PointerType *PTy = cast(Callee->getType());
83868386 const FunctionType *FTy = cast(PTy->getElementType());
8387 const ParamAttrsList *Attrs = CS.getParamAttrs();
8388
8389 // If the call already has the 'nest' attribute somewhere then give up -
8390 // otherwise 'nest' would occur twice after splicing in the chain.
8391 if (Attrs && Attrs->hasAttrSomewhere(ParamAttr::Nest))
8392 return 0;
83878393
83888394 IntrinsicInst *Tramp =
83898395 cast(cast(Callee)->getOperand(0));
84138419 std::vector NewArgs;
84148420 NewArgs.reserve(unsigned(CS.arg_end()-CS.arg_begin())+1);
84158421
8422 ParamAttrsVector NewAttrs;
8423 NewAttrs.reserve(Attrs ? Attrs->size() + 1 : 1);
8424
84168425 // Insert the nest argument into the call argument list, which may
8417 // mean appending it.
8426 // mean appending it. Likewise for attributes.
8427
8428 // Add any function result attributes.
8429 uint16_t Attr = Attrs ? Attrs->getParamAttrs(0) : 0;
8430 if (Attr)
8431 NewAttrs.push_back (ParamAttrsWithIndex::get(0, Attr));
8432
84188433 {
84198434 unsigned Idx = 1;
84208435 CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
84218436 do {
84228437 if (Idx == NestIdx) {
8423 // Add the chain argument.
8438 // Add the chain argument and attributes.
84248439 Value *NestVal = Tramp->getOperand(3);
84258440 if (NestVal->getType() != NestTy)
84268441 NestVal = new BitCastInst(NestVal, NestTy, "nest", Caller);
84278442 NewArgs.push_back(NestVal);
8443 NewAttrs.push_back(ParamAttrsWithIndex::get(NestIdx, NestAttr));
84288444 }
84298445
84308446 if (I == E)
84318447 break;
84328448
8433 // Add the original argument.
8449 // Add the original argument and attributes.
84348450 NewArgs.push_back(*I);
8451 Attr = Attrs ? Attrs->getParamAttrs(Idx) : 0;
8452 if (Attr)
8453 NewAttrs.push_back
8454 (ParamAttrsWithIndex::get(Idx + (Idx >= NestIdx), Attr));
84358455
84368456 ++Idx, ++I;
84378457 } while (1);
84398459
84408460 // The trampoline may have been bitcast to a bogus type (FTy).
84418461 // Handle this by synthesizing a new function type, equal to FTy
8442 // with the chain parameter inserted. Likewise for attributes.
8443
8444 const ParamAttrsList *Attrs = CS.getParamAttrs();
8462 // with the chain parameter inserted.
8463
84458464 std::vector NewTypes;
8446 ParamAttrsVector NewAttrs;
84478465 NewTypes.reserve(FTy->getNumParams()+1);
84488466
8449 // Add any function result attributes.
8450 uint16_t Attr = Attrs ? Attrs->getParamAttrs(0) : 0;
8451 if (Attr)
8452 NewAttrs.push_back (ParamAttrsWithIndex::get(0, Attr));
8453
84548467 // Insert the chain's type into the list of parameter types, which may
8455 // mean appending it. Likewise for the chain's attributes.
8468 // mean appending it.
84568469 {
84578470 unsigned Idx = 1;
84588471 FunctionType::param_iterator I = FTy->param_begin(),
84598472 E = FTy->param_end();
84608473
84618474 do {
8462 if (Idx == NestIdx) {
8463 // Add the chain's type and attributes.
8475 if (Idx == NestIdx)
8476 // Add the chain's type.
84648477 NewTypes.push_back(NestTy);
8465 NewAttrs.push_back(ParamAttrsWithIndex::get(NestIdx, NestAttr));
8466 }
84678478
84688479 if (I == E)
84698480 break;
84708481
8471 // Add the original type and attributes.
8482 // Add the original type.
84728483 NewTypes.push_back(*I);
8473 Attr = Attrs ? Attrs->getParamAttrs(Idx) : 0;
8474 if (Attr)
8475 NewAttrs.push_back
8476 (ParamAttrsWithIndex::get(Idx + (Idx >= NestIdx), Attr));
84778484
84788485 ++Idx, ++I;
84798486 } while (1);
3333 if (attrs[i].index == Index)
3434 return attrs[i].attrs;
3535 return ParamAttr::None;
36 }
37
38 bool ParamAttrsList::hasAttrSomewhere(ParameterAttributes attr) const {
39 for (unsigned i = 0, e = attrs.size(); i < e; ++i)
40 if (attrs[i].attrs & attr)
41 return true;
42 return false;
3643 }
3744
3845 std::string
0 ; RUN: llvm-as < %s | opt -instcombine -disable-output
1
2 %struct.FRAME.nest = type { i32, i32 (i32*)* }
3 %struct.__builtin_trampoline = type { [10 x i8] }
4
5 declare i8* @llvm.init.trampoline(i8*, i8*, i8*) nounwind
6
7 declare i32 @f(%struct.FRAME.nest* nest , i32*)
8
9 define i32 @nest(i32 %n) {
10 entry:
11 %FRAME.0 = alloca %struct.FRAME.nest, align 8 ; <%struct.FRAME.nest*> [#uses=3]
12 %TRAMP.216 = alloca [10 x i8], align 16 ; <[10 x i8]*> [#uses=1]
13 %TRAMP.216.sub = getelementptr [10 x i8]* %TRAMP.216, i32 0, i32 0 ; [#uses=1]
14 %tmp3 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 0 ; [#uses=1]
15 store i32 %n, i32* %tmp3, align 8
16 %FRAME.06 = bitcast %struct.FRAME.nest* %FRAME.0 to i8* ; [#uses=1]
17 %tramp = call i8* @llvm.init.trampoline( i8* %TRAMP.216.sub, i8* bitcast (i32 (%struct.FRAME.nest*, i32*)* @f to i8*), i8* %FRAME.06 ) ; [#uses=1]
18 %tmp7 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 1 ; [#uses=1]
19 %tmp89 = bitcast i8* %tramp to i32 (i32*)* ; [#uses=2]
20 store i32 (i32*)* %tmp89, i32 (i32*)** %tmp7, align 8
21 %tmp2.i = call i32 %tmp89( i32* nest null ) ; [#uses=1]
22 ret i32 %tmp2.i
23 }
0 ; RUN: llvm-as < %s | opt -instcombine | llvm-dis | grep zeroext
1
2 %struct.FRAME.nest = type { i32, i32 (...)* }
3 %struct.__builtin_trampoline = type { [10 x i8] }
4
5 declare i8* @llvm.init.trampoline(i8*, i8*, i8*) nounwind
6
7 declare i32 @f(%struct.FRAME.nest* nest , ...)
8
9 define i32 @nest(i32 %n) {
10 entry:
11 %FRAME.0 = alloca %struct.FRAME.nest, align 8 ; <%struct.FRAME.nest*> [#uses=3]
12 %TRAMP.216 = alloca [10 x i8], align 16 ; <[10 x i8]*> [#uses=1]
13 %TRAMP.216.sub = getelementptr [10 x i8]* %TRAMP.216, i32 0, i32 0 ; [#uses=1]
14 %tmp3 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 0 ; [#uses=1]
15 store i32 %n, i32* %tmp3, align 8
16 %FRAME.06 = bitcast %struct.FRAME.nest* %FRAME.0 to i8* ; [#uses=1]
17 %tramp = call i8* @llvm.init.trampoline( i8* %TRAMP.216.sub, i8* bitcast (i32 (%struct.FRAME.nest*, ...)* @f to i8*), i8* %FRAME.06 ) ; [#uses=1]
18 %tmp7 = getelementptr %struct.FRAME.nest* %FRAME.0, i32 0, i32 1 ; [#uses=1]
19 %tmp89 = bitcast i8* %tramp to i32 (...)* ; [#uses=2]
20 store i32 (...)* %tmp89, i32 (...)** %tmp7, align 8
21 %tmp2.i = call i32 (...)* %tmp89( i32 zeroext 0 ) ; [#uses=1]
22 ret i32 %tmp2.i
23 }