llvm.org GIT mirror llvm / 03fe69e
[mips] Add CCValAssign::[ASZ]ExtUpper and CCPromoteToUpperBitsInType and handle struct's correctly on big-endian N32/N64 return values. Summary: The N32/N64 ABI's require that structs passed in registers are laid out such that spilling the register with 'sd' places the struct at the lowest address. For little endian this is trivial but for big-endian it requires that structs are shifted into the upper bits of the register. We also require that structs passed in registers have the 'inreg' attribute for big-endian N32/N64 to work correctly. This is because the tablegen-erated calling convention implementation only has access to the lowered form of struct arguments (one or more integers of up to 64-bits each) and is unable to determine the original type. Reviewers: vmedic Reviewed By: vmedic Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D5286 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218451 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Sanders 6 years ago
6 changed file(s) with 208 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
3030 class CCValAssign {
3131 public:
3232 enum LocInfo {
33 Full, // The value fills the full location.
34 SExt, // The value is sign extended in the location.
35 ZExt, // The value is zero extended in the location.
36 AExt, // The value is extended with undefined upper bits.
37 BCvt, // The value is bit-converted in the location.
38 VExt, // The value is vector-widened in the location.
39 // FIXME: Not implemented yet. Code that uses AExt to mean
40 // vector-widen should be fixed to use VExt instead.
41 FPExt, // The floating-point value is fp-extended in the location.
42 Indirect // The location contains pointer to the value.
33 Full, // The value fills the full location.
34 SExt, // The value is sign extended in the location.
35 ZExt, // The value is zero extended in the location.
36 AExt, // The value is extended with undefined upper bits.
37 SExtUpper, // The value is in the upper bits of the location and should be
38 // sign extended when retrieved.
39 ZExtUpper, // The value is in the upper bits of the location and should be
40 // zero extended when retrieved.
41 AExtUpper, // The value is in the upper bits of the location and should be
42 // extended with undefined upper bits when retrieved.
43 BCvt, // The value is bit-converted in the location.
44 VExt, // The value is vector-widened in the location.
45 // FIXME: Not implemented yet. Code that uses AExt to mean
46 // vector-widen should be fixed to use VExt instead.
47 FPExt, // The floating-point value is fp-extended in the location.
48 Indirect // The location contains pointer to the value.
4349 // TODO: a subset of the value is in the location.
4450 };
51
4552 private:
4653 /// ValNo - This is the value number begin assigned (e.g. an argument number).
4754 unsigned ValNo;
145152 return (HTP == AExt || HTP == SExt || HTP == ZExt);
146153 }
147154
155 bool isUpperBitsInLoc() const {
156 return HTP == AExtUpper || HTP == SExtUpper || HTP == ZExtUpper;
157 }
148158 };
149159
150160 /// CCAssignFn - This function assigns a location for Val, updating State to
118118 ValueType DestTy = destTy;
119119 }
120120
121 /// CCPromoteToUpperBitsInType - If applied, this promotes the specified current
122 /// value to the specified type and shifts the value into the upper bits.
123 class CCPromoteToUpperBitsInType : CCAction {
124 ValueType DestTy = destTy;
125 }
126
121127 /// CCBitConvertToType - If applied, this bitconverts the specified current
122128 /// value to the specified type.
123129 class CCBitConvertToType : CCAction {
9191 ]>;
9292
9393 def RetCC_MipsN : CallingConv<[
94 // Aggregate returns are positioned at the lowest address in the slot for
95 // both little and big-endian targets. When passing in registers, this
96 // requires that big-endian targets shift the value into the upper bits.
97 CCIfSubtarget<"isLittle()",
98 CCIfType<[i8, i16, i32], CCIfInReg>>>,
99 CCIfSubtargetNot<"isLittle()",
100 CCIfType<[i8, i16, i32], CCIfInReg>>>,
101
94102 // i32 are returned in registers V0, V1
95103 CCIfType<[i32], CCAssignToReg<[V0, V1]>>,
96104
26952695
26962696 // Copy all of the result registers out of their specified physreg.
26972697 for (unsigned i = 0; i != RVLocs.size(); ++i) {
2698 CCValAssign &VA = RVLocs[i];
2699 assert(VA.isRegLoc() && "Can only return in registers!");
2700
26982701 SDValue Val = DAG.getCopyFromReg(Chain, DL, RVLocs[i].getLocReg(),
26992702 RVLocs[i].getLocVT(), InFlag);
27002703 Chain = Val.getValue(1);
27012704 InFlag = Val.getValue(2);
27022705
2703 if (RVLocs[i].getValVT() != RVLocs[i].getLocVT())
2704 Val = DAG.getNode(ISD::BITCAST, DL, RVLocs[i].getValVT(), Val);
2706 if (VA.isUpperBitsInLoc()) {
2707 unsigned ValSizeInBits = Ins[i].ArgVT.getSizeInBits();
2708 unsigned LocSizeInBits = VA.getLocVT().getSizeInBits();
2709 unsigned Shift =
2710 VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA;
2711 Val = DAG.getNode(
2712 Shift, DL, VA.getLocVT(), Val,
2713 DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT()));
2714 }
2715
2716 switch (VA.getLocInfo()) {
2717 default:
2718 llvm_unreachable("Unknown loc info!");
2719 case CCValAssign::Full:
2720 break;
2721 case CCValAssign::BCvt:
2722 Val = DAG.getNode(ISD::BITCAST, DL, VA.getValVT(), Val);
2723 break;
2724 case CCValAssign::AExt:
2725 case CCValAssign::AExtUpper:
2726 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
2727 break;
2728 case CCValAssign::ZExt:
2729 case CCValAssign::ZExtUpper:
2730 Val = DAG.getNode(ISD::AssertZext, DL, VA.getLocVT(), Val,
2731 DAG.getValueType(VA.getValVT()));
2732 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
2733 break;
2734 case CCValAssign::SExt:
2735 case CCValAssign::SExtUpper:
2736 Val = DAG.getNode(ISD::AssertSext, DL, VA.getLocVT(), Val,
2737 DAG.getValueType(VA.getValVT()));
2738 Val = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), Val);
2739 break;
2740 }
27052741
27062742 InVals.push_back(Val);
27072743 }
29012937 SDValue Val = OutVals[i];
29022938 CCValAssign &VA = RVLocs[i];
29032939 assert(VA.isRegLoc() && "Can only return in registers!");
2904
2905 if (RVLocs[i].getValVT() != RVLocs[i].getLocVT())
2906 Val = DAG.getNode(ISD::BITCAST, DL, RVLocs[i].getLocVT(), Val);
2940 bool UseUpperBits = false;
2941
2942 switch (VA.getLocInfo()) {
2943 default:
2944 llvm_unreachable("Unknown loc info!");
2945 case CCValAssign::Full:
2946 break;
2947 case CCValAssign::BCvt:
2948 Val = DAG.getNode(ISD::BITCAST, DL, VA.getLocVT(), Val);
2949 break;
2950 case CCValAssign::AExtUpper:
2951 UseUpperBits = true;
2952 // Fallthrough
2953 case CCValAssign::AExt:
2954 Val = DAG.getNode(ISD::ANY_EXTEND, DL, VA.getLocVT(), Val);
2955 break;
2956 case CCValAssign::ZExtUpper:
2957 UseUpperBits = true;
2958 // Fallthrough
2959 case CCValAssign::ZExt:
2960 Val = DAG.getNode(ISD::ZERO_EXTEND, DL, VA.getLocVT(), Val);
2961 break;
2962 case CCValAssign::SExtUpper:
2963 UseUpperBits = true;
2964 // Fallthrough
2965 case CCValAssign::SExt:
2966 Val = DAG.getNode(ISD::SIGN_EXTEND, DL, VA.getLocVT(), Val);
2967 break;
2968 }
2969
2970 if (UseUpperBits) {
2971 unsigned ValSizeInBits = Outs[i].ArgVT.getSizeInBits();
2972 unsigned LocSizeInBits = VA.getLocVT().getSizeInBits();
2973 Val = DAG.getNode(
2974 ISD::SHL, DL, VA.getLocVT(), Val,
2975 DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT()));
2976 }
29072977
29082978 Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag);
29092979
0 ; RUN: llc -mtriple=mips-linux-gnu -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=O32 --check-prefix=O32-BE %s
1 ; RUN: llc -mtriple=mipsel-linux-gnu -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=O32 --check-prefix=O32-LE %s
2
3 ; RUN-TODO: llc -mtriple=mips64-linux-gnu -relocation-model=static -mattr=-n64,+o32 < %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s
4 ; RUN-TODO: llc -mtriple=mips64el-linux-gnu -relocation-model=static -mattr=-n64,+o32 < %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s
5
6 ; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=N32 --check-prefix=N32-BE %s
7 ; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -mattr=-n64,+n32 < %s | FileCheck --check-prefix=ALL --check-prefix=N32 --check-prefix=N32-LE %s
8
9 ; RUN: llc -mtriple=mips64-linux-gnu -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=N64 --check-prefix=N64-BE %s
10 ; RUN: llc -mtriple=mips64el-linux-gnu -relocation-model=static -mattr=-n64,+n64 < %s | FileCheck --check-prefix=ALL --check-prefix=N64 --check-prefix=N64-LE %s
11
12 ; Test struct returns for all ABI's and byte orders.
13
14 @struct_byte = global {i8} zeroinitializer
15 @struct_2byte = global {i8,i8} zeroinitializer
16
17 declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1)
18
19 define inreg {i8} @ret_struct_i8() nounwind {
20 entry:
21 %0 = load volatile {i8}* @struct_byte
22 ret {i8} %0
23 }
24
25 ; ALL-LABEL: ret_struct_i8:
26 ; O32-DAG: lui [[R1:\$[0-9]+]], %hi(struct_byte)
27 ; O32-DAG: lbu $2, %lo(struct_byte)([[R1]])
28
29 ; N32-LE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_byte)
30 ; N32-LE-DAG: lb $2, %lo(struct_byte)([[R1]])
31
32 ; N32-BE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_byte)
33 ; N32-BE-DAG: lb [[R2:\$[0-9]+]], %lo(struct_byte)([[R1]])
34 ; N32-BE-DAG: dsll $2, [[R2]], 56
35
36 ; N64-LE-DAG: ld [[R1:\$[0-9]+]], %got_disp(struct_byte)($1)
37 ; N64-LE-DAG: lb $2, 0([[R1]])
38
39 ; N64-BE-DAG: ld [[R1:\$[0-9]+]], %got_disp(struct_byte)($1)
40 ; N64-BE-DAG: lb [[R2:\$[0-9]+]], 0([[R1]])
41 ; N64-BE-DAG: dsll $2, [[R2]], 56
42
43 ; This test is based on the way clang currently lowers {i8,i8} to {i16}.
44 ; FIXME: It should probably work for without any lowering too but this doesn't
45 ; work as expected. Each member gets mapped to a register rather than
46 ; packed into a single register.
47 define inreg {i16} @ret_struct_i16() nounwind {
48 entry:
49 %retval = alloca {i8,i8}, align 1
50 %0 = bitcast {i8,i8}* %retval to i8*
51 call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* getelementptr inbounds ({i8,i8}* @struct_2byte, i32 0, i32 0), i64 2, i32 1, i1 false)
52 %1 = bitcast {i8,i8}* %retval to {i16}*
53 %2 = load volatile {i16}* %1
54 ret {i16} %2
55 }
56
57 ; ALL-LABEL: ret_struct_i16:
58 ; O32-DAG: lui [[R1:\$[0-9]+]], %hi(struct_2byte)
59 ; O32-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]])
60 ; O32-DAG: sh [[R2]], 0([[SP:\$sp]])
61 ; O32-DAG: lhu $2, 0([[SP:\$sp]])
62
63 ; N32-LE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_2byte)
64 ; N32-LE-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]])
65 ; N32-LE-DAG: sh [[R2]], 8([[SP:\$sp]])
66 ; N32-LE-DAG: lh $2, 8([[SP:\$sp]])
67
68 ; N32-BE-DAG: lui [[R1:\$[0-9]+]], %hi(struct_2byte)
69 ; N32-BE-DAG: lhu [[R2:\$[0-9]+]], %lo(struct_2byte)([[R1]])
70 ; N32-BE-DAG: sh [[R2]], 8([[SP:\$sp]])
71 ; N32-BE-DAG: lh [[R3:\$[0-9]+]], 8([[SP:\$sp]])
72 ; N32-BE-DAG: dsll $2, [[R3]], 48
73
74 ; N64-LE-DAG: ld [[R1:\$[0-9]+]], %got_disp(struct_2byte)($1)
75 ; N64-LE-DAG: lhu [[R2:\$[0-9]+]], 0([[R1]])
76 ; N64-LE-DAG: sh [[R2]], 8([[SP:\$sp]])
77 ; N64-LE-DAG: lh $2, 8([[SP:\$sp]])
78
79 ; N64-BE-DAG: ld [[R1:\$[0-9]+]], %got_disp(struct_2byte)($1)
80 ; N64-BE-DAG: lhu [[R2:\$[0-9]+]], 0([[R1]])
81 ; N64-BE-DAG: sh [[R2]], 8([[SP:\$sp]])
82 ; N64-BE-DAG: lh [[R3:\$[0-9]+]], 8([[SP:\$sp]])
83 ; N64-BE-DAG: dsll $2, [[R3]], 48
230230 << IndentStr << "else\n"
231231 << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
232232 }
233 } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) {
234 Record *DestTy = Action->getValueAsDef("DestTy");
235 MVT::SimpleValueType DestVT = getValueType(DestTy);
236 O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
237 if (MVT(DestVT).isFloatingPoint()) {
238 PrintFatalError("CCPromoteToUpperBitsInType does not handle floating "
239 "point");
240 } else {
241 O << IndentStr << "if (ArgFlags.isSExt())\n"
242 << IndentStr << IndentStr << "LocInfo = CCValAssign::SExtUpper;\n"
243 << IndentStr << "else if (ArgFlags.isZExt())\n"
244 << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExtUpper;\n"
245 << IndentStr << "else\n"
246 << IndentStr << IndentStr << "LocInfo = CCValAssign::AExtUpper;\n";
247 }
233248 } else if (Action->isSubClassOf("CCBitConvertToType")) {
234249 Record *DestTy = Action->getValueAsDef("DestTy");
235250 O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";