Skip to content

Commit 1412022

Browse files
authored
Target ABI: improve call parameters extensions handling (#100757)
For the purpose of verifying proper arguments extensions per the target's ABI, introduce the NoExt attribute that may be used by a target when neither sign- or zeroextension is required (e.g. with a struct in register). The purpose of doing so is to be able to verify that there is always one of these attributes present and by this detecting cases where sign/zero extension is actually missing. As a first step, this patch has the verification step done for the SystemZ backend only, but left off by default until all known issues have been addressed. Other targets/front-ends can now also add NoExt attribute where needed and do this check in the backend.
1 parent 9ca62c5 commit 1412022

File tree

28 files changed

+315
-43
lines changed

28 files changed

+315
-43
lines changed

clang/include/clang/CodeGen/CGFunctionInfo.h

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ class ABIArgInfo {
116116
bool InReg : 1; // isDirect() || isExtend() || isIndirect()
117117
bool CanBeFlattened: 1; // isDirect()
118118
bool SignExt : 1; // isExtend()
119+
bool ZeroExt : 1; // isExtend()
119120

120121
bool canHavePaddingType() const {
121122
return isDirect() || isExtend() || isIndirect() || isIndirectAliased() ||
@@ -137,7 +138,7 @@ class ABIArgInfo {
137138
PaddingInReg(false), InAllocaSRet(false),
138139
InAllocaIndirect(false), IndirectByVal(false), IndirectRealign(false),
139140
SRetAfterThis(false), InReg(false), CanBeFlattened(false),
140-
SignExt(false) {}
141+
SignExt(false), ZeroExt(false) {}
141142

142143
static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0,
143144
llvm::Type *Padding = nullptr,
@@ -174,19 +175,29 @@ class ABIArgInfo {
174175
AI.setPaddingType(nullptr);
175176
AI.setDirectOffset(0);
176177
AI.setDirectAlign(0);
177-
AI.setSignExt(false);
178+
AI.setZeroExt(true);
178179
return AI;
179180
}
180181

181182
// ABIArgInfo will record the argument as being extended based on the sign
182-
// of its type.
183+
// of its type. Produces a sign or zero extension.
183184
static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) {
184185
assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType");
185186
if (Ty->hasSignedIntegerRepresentation())
186187
return getSignExtend(Ty, T);
187188
return getZeroExtend(Ty, T);
188189
}
189190

191+
// Struct in register marked explicitly as not needing extension.
192+
static ABIArgInfo getNoExtend(llvm::IntegerType *T) {
193+
auto AI = ABIArgInfo(Extend);
194+
AI.setCoerceToType(T);
195+
AI.setPaddingType(nullptr);
196+
AI.setDirectOffset(0);
197+
AI.setDirectAlign(0);
198+
return AI;
199+
}
200+
190201
static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) {
191202
auto AI = getExtend(Ty, T);
192203
AI.setInReg(true);
@@ -326,14 +337,28 @@ class ABIArgInfo {
326337
}
327338

328339
bool isSignExt() const {
329-
assert(isExtend() && "Invalid kind!");
340+
assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
330341
return SignExt;
331342
}
332343
void setSignExt(bool SExt) {
333344
assert(isExtend() && "Invalid kind!");
334345
SignExt = SExt;
335346
}
336347

348+
bool isZeroExt() const {
349+
assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
350+
return ZeroExt;
351+
}
352+
void setZeroExt(bool ZExt) {
353+
assert(isExtend() && "Invalid kind!");
354+
ZeroExt = ZExt;
355+
}
356+
357+
bool isNoExt() const {
358+
assert(isExtend() && (SignExt + ZeroExt <= 1) && "Invalid kind / flags!");
359+
return !SignExt && !ZeroExt;
360+
}
361+
337362
llvm::Type *getPaddingType() const {
338363
return (canHavePaddingType() ? PaddingType : nullptr);
339364
}

clang/lib/CodeGen/CGCall.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,7 +2182,7 @@ static bool DetermineNoUndef(QualType QTy, CodeGenTypes &Types,
21822182
if (AI.getKind() == ABIArgInfo::Indirect ||
21832183
AI.getKind() == ABIArgInfo::IndirectAliased)
21842184
return true;
2185-
if (AI.getKind() == ABIArgInfo::Extend)
2185+
if (AI.getKind() == ABIArgInfo::Extend && !AI.isNoExt())
21862186
return true;
21872187
if (!DL.typeSizeEqualsStoreSize(Ty))
21882188
// TODO: This will result in a modest amount of values not marked noundef
@@ -2567,8 +2567,10 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
25672567
case ABIArgInfo::Extend:
25682568
if (RetAI.isSignExt())
25692569
RetAttrs.addAttribute(llvm::Attribute::SExt);
2570-
else
2570+
else if (RetAI.isZeroExt())
25712571
RetAttrs.addAttribute(llvm::Attribute::ZExt);
2572+
else
2573+
RetAttrs.addAttribute(llvm::Attribute::NoExt);
25722574
[[fallthrough]];
25732575
case ABIArgInfo::Direct:
25742576
if (RetAI.getInReg())
@@ -2708,8 +2710,10 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
27082710
case ABIArgInfo::Extend:
27092711
if (AI.isSignExt())
27102712
Attrs.addAttribute(llvm::Attribute::SExt);
2711-
else
2713+
else if (AI.isZeroExt())
27122714
Attrs.addAttribute(llvm::Attribute::ZExt);
2715+
else
2716+
Attrs.addAttribute(llvm::Attribute::NoExt);
27132717
[[fallthrough]];
27142718
case ABIArgInfo::Direct:
27152719
if (ArgNo == 0 && FI.isChainCall())

clang/lib/CodeGen/Targets/SystemZ.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -445,16 +445,16 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
445445
return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
446446

447447
// The structure is passed as an unextended integer, a float, or a double.
448-
llvm::Type *PassTy;
449448
if (isFPArgumentType(SingleElementTy)) {
450449
assert(Size == 32 || Size == 64);
451-
if (Size == 32)
452-
PassTy = llvm::Type::getFloatTy(getVMContext());
453-
else
454-
PassTy = llvm::Type::getDoubleTy(getVMContext());
455-
} else
456-
PassTy = llvm::IntegerType::get(getVMContext(), Size);
457-
return ABIArgInfo::getDirect(PassTy);
450+
return ABIArgInfo::getDirect(
451+
Size == 32 ? llvm::Type::getFloatTy(getVMContext())
452+
: llvm::Type::getDoubleTy(getVMContext()));
453+
} else {
454+
llvm::IntegerType *PassTy = llvm::IntegerType::get(getVMContext(), Size);
455+
return Size <= 32 ? ABIArgInfo::getNoExtend(PassTy)
456+
: ABIArgInfo::getDirect(PassTy);
457+
}
458458
}
459459

460460
// Non-structure compounds are passed indirectly.

clang/test/CodeGen/SystemZ/systemz-abi-vector.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,17 +146,17 @@ v1f128 pass_v1f128(v1f128 arg) { return arg; }
146146

147147
struct agg_v1i8 { v1i8 a; };
148148
struct agg_v1i8 pass_agg_v1i8(struct agg_v1i8 arg) { return arg; }
149-
// CHECK-LABEL: define{{.*}} void @pass_agg_v1i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v1i8) align 1 %{{.*}}, i8 %{{.*}})
149+
// CHECK-LABEL: define{{.*}} void @pass_agg_v1i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v1i8) align 1 %{{.*}}, i8 noext %{{.*}})
150150
// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v1i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v1i8) align 1 %{{.*}}, <1 x i8> %{{.*}})
151151

152152
struct agg_v2i8 { v2i8 a; };
153153
struct agg_v2i8 pass_agg_v2i8(struct agg_v2i8 arg) { return arg; }
154-
// CHECK-LABEL: define{{.*}} void @pass_agg_v2i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v2i8) align 2 %{{.*}}, i16 %{{.*}})
154+
// CHECK-LABEL: define{{.*}} void @pass_agg_v2i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v2i8) align 2 %{{.*}}, i16 noext %{{.*}})
155155
// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v2i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v2i8) align 2 %{{.*}}, <2 x i8> %{{.*}})
156156

157157
struct agg_v4i8 { v4i8 a; };
158158
struct agg_v4i8 pass_agg_v4i8(struct agg_v4i8 arg) { return arg; }
159-
// CHECK-LABEL: define{{.*}} void @pass_agg_v4i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v4i8) align 4 %{{.*}}, i32 %{{.*}})
159+
// CHECK-LABEL: define{{.*}} void @pass_agg_v4i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v4i8) align 4 %{{.*}}, i32 noext %{{.*}})
160160
// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_v4i8(ptr dead_on_unwind noalias writable sret(%struct.agg_v4i8) align 4 %{{.*}}, <4 x i8> %{{.*}})
161161

162162
struct agg_v8i8 { v8i8 a; };
@@ -189,8 +189,8 @@ struct agg_novector2 pass_agg_novector2(struct agg_novector2 arg) { return arg;
189189

190190
struct agg_novector3 { v4i8 a; int : 0; };
191191
struct agg_novector3 pass_agg_novector3(struct agg_novector3 arg) { return arg; }
192-
// CHECK-LABEL: define{{.*}} void @pass_agg_novector3(ptr dead_on_unwind noalias writable sret(%struct.agg_novector3) align 4 %{{.*}}, i32 %{{.*}})
193-
// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_novector3(ptr dead_on_unwind noalias writable sret(%struct.agg_novector3) align 4 %{{.*}}, i32 %{{.*}})
192+
// CHECK-LABEL: define{{.*}} void @pass_agg_novector3(ptr dead_on_unwind noalias writable sret(%struct.agg_novector3) align 4 %{{.*}}, i32 noext %{{.*}})
193+
// CHECK-VECTOR-LABEL: define{{.*}} void @pass_agg_novector3(ptr dead_on_unwind noalias writable sret(%struct.agg_novector3) align 4 %{{.*}}, i32 noext %{{.*}})
194194

195195
struct agg_novector4 { v4i8 a __attribute__((aligned (8))); };
196196
struct agg_novector4 pass_agg_novector4(struct agg_novector4 arg) { return arg; }

clang/test/CodeGen/SystemZ/systemz-abi.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,19 +86,19 @@ _Complex long double pass_complex_longdouble(_Complex long double arg) { return
8686

8787
struct agg_1byte { char a[1]; };
8888
struct agg_1byte pass_agg_1byte(struct agg_1byte arg) { return arg; }
89-
// CHECK-LABEL: define{{.*}} void @pass_agg_1byte(ptr dead_on_unwind noalias writable sret(%struct.agg_1byte) align 1 %{{.*}}, i8 %{{.*}})
89+
// CHECK-LABEL: define{{.*}} void @pass_agg_1byte(ptr dead_on_unwind noalias writable sret(%struct.agg_1byte) align 1 %{{.*}}, i8 noext %{{.*}})
9090

9191
struct agg_2byte { char a[2]; };
9292
struct agg_2byte pass_agg_2byte(struct agg_2byte arg) { return arg; }
93-
// CHECK-LABEL: define{{.*}} void @pass_agg_2byte(ptr dead_on_unwind noalias writable sret(%struct.agg_2byte) align 1 %{{.*}}, i16 %{{.*}})
93+
// CHECK-LABEL: define{{.*}} void @pass_agg_2byte(ptr dead_on_unwind noalias writable sret(%struct.agg_2byte) align 1 %{{.*}}, i16 noext %{{.*}})
9494

9595
struct agg_3byte { char a[3]; };
9696
struct agg_3byte pass_agg_3byte(struct agg_3byte arg) { return arg; }
9797
// CHECK-LABEL: define{{.*}} void @pass_agg_3byte(ptr dead_on_unwind noalias writable sret(%struct.agg_3byte) align 1 %{{.*}}, ptr %{{.*}})
9898

9999
struct agg_4byte { char a[4]; };
100100
struct agg_4byte pass_agg_4byte(struct agg_4byte arg) { return arg; }
101-
// CHECK-LABEL: define{{.*}} void @pass_agg_4byte(ptr dead_on_unwind noalias writable sret(%struct.agg_4byte) align 1 %{{.*}}, i32 %{{.*}})
101+
// CHECK-LABEL: define{{.*}} void @pass_agg_4byte(ptr dead_on_unwind noalias writable sret(%struct.agg_4byte) align 1 %{{.*}}, i32 noext %{{.*}})
102102

103103
struct agg_5byte { char a[5]; };
104104
struct agg_5byte pass_agg_5byte(struct agg_5byte arg) { return arg; }
@@ -126,7 +126,7 @@ struct agg_16byte pass_agg_16byte(struct agg_16byte arg) { return arg; }
126126
struct agg_float { float a; };
127127
struct agg_float pass_agg_float(struct agg_float arg) { return arg; }
128128
// HARD-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, float %{{.*}})
129-
// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, i32 %{{.*}})
129+
// SOFT-FLOAT-LABEL: define{{.*}} void @pass_agg_float(ptr dead_on_unwind noalias writable sret(%struct.agg_float) align 4 %{{.*}}, i32 noext %{{.*}})
130130

131131
struct agg_double { double a; };
132132
struct agg_double pass_agg_double(struct agg_double arg) { return arg; }
@@ -159,14 +159,14 @@ struct agg_nofloat2 pass_agg_nofloat2(struct agg_nofloat2 arg) { return arg; }
159159

160160
struct agg_nofloat3 { float a; int : 0; };
161161
struct agg_nofloat3 pass_agg_nofloat3(struct agg_nofloat3 arg) { return arg; }
162-
// CHECK-LABEL: define{{.*}} void @pass_agg_nofloat3(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat3) align 4 %{{.*}}, i32 %{{.*}})
162+
// CHECK-LABEL: define{{.*}} void @pass_agg_nofloat3(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat3) align 4 %{{.*}}, i32 noext %{{.*}})
163163

164164

165165
// Union types likewise are *not* float-like aggregate types
166166

167167
union union_float { float a; };
168168
union union_float pass_union_float(union union_float arg) { return arg; }
169-
// CHECK-LABEL: define{{.*}} void @pass_union_float(ptr dead_on_unwind noalias writable sret(%union.union_float) align 4 %{{.*}}, i32 %{{.*}})
169+
// CHECK-LABEL: define{{.*}} void @pass_union_float(ptr dead_on_unwind noalias writable sret(%union.union_float) align 4 %{{.*}}, i32 noext %{{.*}})
170170

171171
union union_double { double a; };
172172
union union_double pass_union_double(union union_double arg) { return arg; }

clang/test/CodeGen/SystemZ/systemz-abi.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
class agg_float_class { float a; };
88
class agg_float_class pass_agg_float_class(class agg_float_class arg) { return arg; }
99
// CHECK-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr dead_on_unwind noalias writable sret(%class.agg_float_class) align 4 %{{.*}}, float %{{.*}})
10-
// SOFT-FLOAT-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr dead_on_unwind noalias writable sret(%class.agg_float_class) align 4 %{{.*}}, i32 %{{.*}})
10+
// SOFT-FLOAT-LABEL: define{{.*}} void @_Z20pass_agg_float_class15agg_float_class(ptr dead_on_unwind noalias writable sret(%class.agg_float_class) align 4 %{{.*}}, i32 noext %{{.*}})
1111

1212
class agg_double_class { double a; };
1313
class agg_double_class pass_agg_double_class(class agg_double_class arg) { return arg; }
@@ -18,8 +18,8 @@ class agg_double_class pass_agg_double_class(class agg_double_class arg) { retur
1818
// This structure is passed in a GPR in C++ (and C, checked in systemz-abi.c).
1919
struct agg_float_cpp { float a; int : 0; };
2020
struct agg_float_cpp pass_agg_float_cpp(struct agg_float_cpp arg) { return arg; }
21-
// CHECK-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr dead_on_unwind noalias writable sret(%struct.agg_float_cpp) align 4 %{{.*}}, i32 %{{.*}})
22-
// SOFT-FLOAT-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr dead_on_unwind noalias writable sret(%struct.agg_float_cpp) align 4 %{{.*}}, i32 %{{.*}})
21+
// CHECK-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr dead_on_unwind noalias writable sret(%struct.agg_float_cpp) align 4 %{{.*}}, i32 noext %{{.*}})
22+
// SOFT-FLOAT-LABEL: define{{.*}} void @_Z18pass_agg_float_cpp13agg_float_cpp(ptr dead_on_unwind noalias writable sret(%struct.agg_float_cpp) align 4 %{{.*}}, i32 noext %{{.*}})
2323

2424

2525
// A field member of empty class type in C++ makes the record nonhomogeneous,
@@ -32,7 +32,7 @@ struct agg_nofloat_empty pass_agg_nofloat_empty(struct agg_nofloat_empty arg) {
3232
struct agg_float_empty { float a; [[no_unique_address]] empty dummy; };
3333
struct agg_float_empty pass_agg_float_empty(struct agg_float_empty arg) { return arg; }
3434
// CHECK-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_float_empty) align 4 %{{.*}}, float %{{.*}})
35-
// SOFT-FLOAT-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_float_empty) align 4 %{{.*}}, i32 %{{.*}})
35+
// SOFT-FLOAT-LABEL: define{{.*}} void @_Z20pass_agg_float_empty15agg_float_empty(ptr dead_on_unwind noalias writable sret(%struct.agg_float_empty) align 4 %{{.*}}, i32 noext %{{.*}})
3636
struct agg_nofloat_emptyarray { float a; [[no_unique_address]] empty dummy[3]; };
3737
struct agg_nofloat_emptyarray pass_agg_nofloat_emptyarray(struct agg_nofloat_emptyarray arg) { return arg; }
3838
// CHECK-LABEL: define{{.*}} void @_Z27pass_agg_nofloat_emptyarray22agg_nofloat_emptyarray(ptr dead_on_unwind noalias writable sret(%struct.agg_nofloat_emptyarray) align 4 %{{.*}}, i64 %{{.*}})
@@ -48,7 +48,7 @@ struct emptybase { [[no_unique_address]] empty dummy; };
4848
struct agg_float_emptybase : emptybase { float a; };
4949
struct agg_float_emptybase pass_agg_float_emptybase(struct agg_float_emptybase arg) { return arg; }
5050
// CHECK-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_float_emptybase) align 4 %{{.*}}, float %{{.*}})
51-
// SOFT-FLOAT-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_float_emptybase) align 4 %{{.*}}, i32 %{{.*}})
51+
// SOFT-FLOAT-LABEL: define{{.*}} void @_Z24pass_agg_float_emptybase19agg_float_emptybase(ptr dead_on_unwind noalias writable sret(%struct.agg_float_emptybase) align 4 %{{.*}}, i32 noext %{{.*}})
5252
struct noemptybasearray { [[no_unique_address]] empty dummy[3]; };
5353
struct agg_nofloat_emptybasearray : noemptybasearray { float a; };
5454
struct agg_nofloat_emptybasearray pass_agg_nofloat_emptybasearray(struct agg_nofloat_emptybasearray arg) { return arg; }

llvm/docs/LangRef.rst

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,10 @@ For example:
11741174
Note that any attributes for the function result (``nonnull``,
11751175
``signext``) come before the result type.
11761176

1177+
If an integer argument to a function is not marked signext/zeroext/noext, the
1178+
kind of extension used is target-specific. Some targets depend for
1179+
correctness on the kind of extension to be explicitly specified.
1180+
11771181
Currently, only the following parameter attributes are defined:
11781182

11791183
``zeroext``
@@ -1185,6 +1189,12 @@ Currently, only the following parameter attributes are defined:
11851189
value should be sign-extended to the extent required by the target's
11861190
ABI (which is usually 32-bits) by the caller (for a parameter) or
11871191
the callee (for a return value).
1192+
``noext``
1193+
This indicates to the code generator that the parameter or return
1194+
value has the high bits undefined, as for a struct in register, and
1195+
therefore does not need to be sign or zero extended. This is the same
1196+
as default behavior and is only actually used (by some targets) to
1197+
validate that one of the attributes is always present.
11881198
``inreg``
11891199
This indicates that this parameter or return value should be treated
11901200
in a special target-dependent fashion while emitting code for
@@ -9113,8 +9123,8 @@ This instruction requires several arguments:
91139123
convention <callingconv>` the call should use. If none is
91149124
specified, the call defaults to using C calling conventions.
91159125
#. The optional :ref:`Parameter Attributes <paramattrs>` list for return
9116-
values. Only '``zeroext``', '``signext``', and '``inreg``' attributes
9117-
are valid here.
9126+
values. Only '``zeroext``', '``signext``', '``noext``', and '``inreg``'
9127+
attributes are valid here.
91189128
#. The optional addrspace attribute can be used to indicate the address space
91199129
of the called function. If it is not specified, the program address space
91209130
from the :ref:`datalayout string<langref_datalayout>` will be used.
@@ -9209,8 +9219,8 @@ This instruction requires several arguments:
92099219
convention <callingconv>` the call should use. If none is
92109220
specified, the call defaults to using C calling conventions.
92119221
#. The optional :ref:`Parameter Attributes <paramattrs>` list for return
9212-
values. Only '``zeroext``', '``signext``', and '``inreg``' attributes
9213-
are valid here.
9222+
values. Only '``zeroext``', '``signext``', '``noext``', and '``inreg``'
9223+
attributes are valid here.
92149224
#. The optional addrspace attribute can be used to indicate the address space
92159225
of the called function. If it is not specified, the program address space
92169226
from the :ref:`datalayout string<langref_datalayout>` will be used.
@@ -12699,8 +12709,8 @@ This instruction requires several arguments:
1269912709
calling convention of the call must match the calling convention of
1270012710
the target function, or else the behavior is undefined.
1270112711
#. The optional :ref:`Parameter Attributes <paramattrs>` list for return
12702-
values. Only '``zeroext``', '``signext``', and '``inreg``' attributes
12703-
are valid here.
12712+
values. Only '``zeroext``', '``signext``', '``noext``', and '``inreg``'
12713+
attributes are valid here.
1270412714
#. The optional addrspace attribute can be used to indicate the address space
1270512715
of the called function. If it is not specified, the program address space
1270612716
from the :ref:`datalayout string<langref_datalayout>` will be used.

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ enum AttributeKindCodes {
763763
ATTR_KIND_SANITIZE_REALTIME = 96,
764764
ATTR_KIND_NO_SANITIZE_REALTIME = 97,
765765
ATTR_KIND_CORO_ELIDE_SAFE = 98,
766+
ATTR_KIND_NO_EXT = 99,
766767
};
767768

768769
enum ComdatSelectionKindCodes {

llvm/include/llvm/CodeGen/TargetCallingConv.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace ISD {
2828
private:
2929
unsigned IsZExt : 1; ///< Zero extended
3030
unsigned IsSExt : 1; ///< Sign extended
31+
unsigned IsNoExt : 1; ///< No extension
3132
unsigned IsInReg : 1; ///< Passed in register
3233
unsigned IsSRet : 1; ///< Hidden struct-ret ptr
3334
unsigned IsByVal : 1; ///< Struct passed by value
@@ -60,8 +61,8 @@ namespace ISD {
6061

6162
public:
6263
ArgFlagsTy()
63-
: IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0),
64-
IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0),
64+
: IsZExt(0), IsSExt(0), IsNoExt(0), IsInReg(0), IsSRet(0), IsByVal(0),
65+
IsByRef(0), IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0),
6566
IsPreallocated(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftAsync(0),
6667
IsSwiftError(0), IsCFGuardTarget(0), IsHva(0), IsHvaStart(0),
6768
IsSecArgPass(0), MemAlign(0), OrigAlign(0),
@@ -76,6 +77,9 @@ namespace ISD {
7677
bool isSExt() const { return IsSExt; }
7778
void setSExt() { IsSExt = 1; }
7879

80+
bool isNoExt() const { return IsNoExt; }
81+
void setNoExt() { IsNoExt = 1; }
82+
7983
bool isInReg() const { return IsInReg; }
8084
void setInReg() { IsInReg = 1; }
8185

0 commit comments

Comments
 (0)