15
15
#ifndef LLVM_IR_INLINEASM_H
16
16
#define LLVM_IR_INLINEASM_H
17
17
18
+ #include " llvm/ADT/Bitfields.h"
18
19
#include " llvm/ADT/SmallVector.h"
19
20
#include " llvm/ADT/StringRef.h"
20
21
#include " llvm/IR/Value.h"
@@ -196,23 +197,6 @@ class InlineAsm final : public Value {
196
197
return V->getValueID () == Value::InlineAsmVal;
197
198
}
198
199
199
- // These are helper methods for dealing with flags in the INLINEASM SDNode
200
- // in the backend.
201
- //
202
- // The encoding of the flag word is currently:
203
- // Bits 2-0 - A Kind::* value indicating the kind of the operand.
204
- // Bits 15-3 - The number of SDNode operands associated with this inline
205
- // assembly operand.
206
- // If bit 31 is set:
207
- // Bit 30-16 - The operand number that this operand must match.
208
- // When bits 2-0 are Kind::Mem, the Constraint_* value must be
209
- // obtained from the flags for this operand number.
210
- // Else if bits 2-0 are Kind::Mem:
211
- // Bit 30-16 - A Constraint_* value indicating the original constraint
212
- // code.
213
- // Else:
214
- // Bit 30-16 - The register class ID to use for the operand.
215
-
216
200
enum : uint32_t {
217
201
// Fixed operands on an INLINEASM SDNode.
218
202
Op_InputChain = 0 ,
@@ -241,6 +225,7 @@ class InlineAsm final : public Value {
241
225
// Addresses are included here as they need to be treated the same by the
242
226
// backend, the only difference is that they are not used to actaully
243
227
// access memory by the instruction.
228
+ // TODO: convert to enum?
244
229
Constraint_Unknown = 0 ,
245
230
Constraint_es,
246
231
Constraint_i,
@@ -274,15 +259,12 @@ class InlineAsm final : public Value {
274
259
Constraint_ZT,
275
260
276
261
Constraints_Max = Constraint_ZT,
277
- Constraints_ShiftAmount = 16 ,
278
-
279
- Flag_MatchingOperand = 0x80000000
280
262
};
281
263
282
264
// Inline asm operands map to multiple SDNode / MachineInstr operands.
283
265
// The first operand is an immediate describing the asm operand, the low
284
266
// bits is the kind:
285
- enum class Kind {
267
+ enum class Kind : uint8_t {
286
268
RegUse = 1 , // Input register, "r".
287
269
RegDef = 2 , // Output register, "=r".
288
270
RegDefEarlyClobber = 3 , // Early-clobber output register, "=&r".
@@ -292,101 +274,149 @@ class InlineAsm final : public Value {
292
274
Func = 7 , // Address operand of function call
293
275
};
294
276
295
- static unsigned getFlagWord (Kind Kind, unsigned NumOps) {
296
- assert (((NumOps << 3 ) & ~0xffff ) == 0 && " Too many inline asm operands!" );
297
- return static_cast <unsigned >(Kind) | (NumOps << 3 );
298
- }
299
-
300
- static bool isRegDefKind (unsigned Flag) {
301
- return getKind (Flag) == Kind::RegDef;
302
- }
303
- static bool isImmKind (unsigned Flag) { return getKind (Flag) == Kind::Imm; }
304
- static bool isMemKind (unsigned Flag) { return getKind (Flag) == Kind::Mem; }
305
- static bool isFuncKind (unsigned Flag) { return getKind (Flag) == Kind::Func; }
306
- static bool isRegDefEarlyClobberKind (unsigned Flag) {
307
- return getKind (Flag) == Kind::RegDefEarlyClobber;
308
- }
309
- static bool isClobberKind (unsigned Flag) {
310
- return getKind (Flag) == Kind::Clobber;
311
- }
312
-
313
- // / getFlagWordForMatchingOp - Augment an existing flag word returned by
314
- // / getFlagWord with information indicating that this input operand is tied
315
- // / to a previous output operand.
316
- static unsigned getFlagWordForMatchingOp (unsigned InputFlag,
317
- unsigned MatchedOperandNo) {
318
- assert (MatchedOperandNo <= 0x7fff && " Too big matched operand" );
319
- assert ((InputFlag & ~0xffff ) == 0 && " High bits already contain data" );
320
- return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16 );
321
- }
322
-
323
- // / getFlagWordForRegClass - Augment an existing flag word returned by
324
- // / getFlagWord with the required register class for the following register
325
- // / operands.
326
- // / A tied use operand cannot have a register class, use the register class
327
- // / from the def operand instead.
328
- static unsigned getFlagWordForRegClass (unsigned InputFlag, unsigned RC) {
329
- // Store RC + 1, reserve the value 0 to mean 'no register class'.
330
- ++RC;
331
- assert (!isImmKind (InputFlag) && " Immediates cannot have a register class" );
332
- assert (!isMemKind (InputFlag) && " Memory operand cannot have a register class" );
333
- assert (RC <= 0x7fff && " Too large register class ID" );
334
- assert ((InputFlag & ~0xffff ) == 0 && " High bits already contain data" );
335
- return InputFlag | (RC << 16 );
336
- }
277
+ // These are helper methods for dealing with flags in the INLINEASM SDNode
278
+ // in the backend.
279
+ //
280
+ // The encoding of Flag is currently:
281
+ // Bits 2-0 - A Kind::* value indicating the kind of the operand.
282
+ // Bits 15-3 - The number of SDNode operands associated with this inline
283
+ // assembly operand.
284
+ // If bit 31 is set:
285
+ // Bit 30-16 - The operand number that this operand must match.
286
+ // When bits 2-0 are Kind::Mem, the Constraint_* value must be
287
+ // obtained from the flags for this operand number.
288
+ // Else if bits 2-0 are Kind::Mem:
289
+ // Bit 30-16 - A Constraint_* value indicating the original constraint
290
+ // code.
291
+ // Else:
292
+ // Bit 30-16 - The register class ID to use for the operand.
293
+ //
294
+ // Bits 30-16 are called "Data" for lack of a better name. The getter is
295
+ // intentionally private; the public methods that rely on that private method
296
+ // should be used to check invariants first before accessing Data.
297
+ class Flag {
298
+ uint32_t Storage;
299
+ using KindField = Bitfield::Element<Kind, 0 , 3 , Kind::Func>;
300
+ using NumOperands = Bitfield::Element<unsigned , 3 , 13 >;
301
+ using Data = Bitfield::Element<unsigned , 16 , 15 >;
302
+ using IsMatched = Bitfield::Element<bool , 31 , 1 >;
303
+
304
+ unsigned getData () const { return Bitfield::get<Data>(Storage); }
305
+ bool isMatched () const { return Bitfield::get<IsMatched>(Storage); }
306
+ void setKind (Kind K) { Bitfield::set<KindField>(Storage, K); }
307
+ void setNumOperands (unsigned N) { Bitfield::set<NumOperands>(Storage, N); }
308
+ void setData (unsigned D) { Bitfield::set<Data>(Storage, D); }
309
+ void setIsMatched (bool B) { Bitfield::set<IsMatched>(Storage, B); }
310
+
311
+ public:
312
+ Flag () : Storage(0 ) {}
313
+ explicit Flag (uint32_t F) : Storage(F) {}
314
+ Flag (enum Kind K, unsigned NumOps) {
315
+ setKind (K);
316
+ setNumOperands (NumOps);
317
+ setData (0 );
318
+ setIsMatched (false );
319
+ }
320
+ operator uint32_t () { return Storage; }
321
+ Kind getKind () const { return Bitfield::get<KindField>(Storage); }
322
+ bool isRegUseKind () const { return getKind () == Kind::RegUse; }
323
+ bool isRegDefKind () const { return getKind () == Kind::RegDef; }
324
+ bool isRegDefEarlyClobberKind () const {
325
+ return getKind () == Kind::RegDefEarlyClobber;
326
+ }
327
+ bool isClobberKind () const { return getKind () == Kind::Clobber; }
328
+ bool isImmKind () const { return getKind () == Kind::Imm; }
329
+ bool isMemKind () const { return getKind () == Kind::Mem; }
330
+ bool isFuncKind () const { return getKind () == Kind::Func; }
331
+ StringRef getKindName () const {
332
+ switch (getKind ()) {
333
+ case Kind::RegUse:
334
+ return " reguse" ;
335
+ case Kind::RegDef:
336
+ return " regdef" ;
337
+ case Kind::RegDefEarlyClobber:
338
+ return " regdef-ec" ;
339
+ case Kind::Clobber:
340
+ return " clobber" ;
341
+ case Kind::Imm:
342
+ return " imm" ;
343
+ case Kind::Mem:
344
+ case Kind::Func:
345
+ return " mem" ;
346
+ }
347
+ }
337
348
338
- // / Augment an existing flag word returned by getFlagWord with the constraint
339
- // / code for a memory constraint.
340
- static unsigned getFlagWordForMem (unsigned InputFlag, unsigned Constraint) {
341
- assert ((isMemKind (InputFlag) || isFuncKind (InputFlag)) &&
342
- " InputFlag is not a memory (include function) constraint!" );
343
- assert (Constraint <= 0x7fff && " Too large a memory constraint ID" );
344
- assert (Constraint <= Constraints_Max && " Unknown constraint ID" );
345
- assert ((InputFlag & ~0xffff ) == 0 && " High bits already contain data" );
346
- return InputFlag | (Constraint << Constraints_ShiftAmount);
347
- }
349
+ // / getNumOperandRegisters - Extract the number of registers field from the
350
+ // / inline asm operand flag.
351
+ unsigned getNumOperandRegisters () const {
352
+ return Bitfield::get<NumOperands>(Storage);
353
+ }
348
354
349
- static unsigned convertMemFlagWordToMatchingFlagWord (unsigned InputFlag) {
350
- assert (isMemKind (InputFlag));
351
- return InputFlag & ~(0x7fff << Constraints_ShiftAmount);
352
- }
355
+ // / isUseOperandTiedToDef - Return true if the flag of the inline asm
356
+ // / operand indicates it is an use operand that's matched to a def operand.
357
+ bool isUseOperandTiedToDef (unsigned &Idx) const {
358
+ if (!isMatched ())
359
+ return false ;
360
+ Idx = getData ();
361
+ return true ;
362
+ }
353
363
354
- static Kind getKind (unsigned Flags) { return static_cast <Kind>(Flags & 7 ); }
364
+ // / hasRegClassConstraint - Returns true if the flag contains a register
365
+ // / class constraint. Sets RC to the register class ID.
366
+ bool hasRegClassConstraint (unsigned &RC) const {
367
+ if (isMatched ())
368
+ return false ;
369
+ // setRegClass() uses 0 to mean no register class, and otherwise stores
370
+ // RC + 1.
371
+ if (!getData ())
372
+ return false ;
373
+ RC = getData () - 1 ;
374
+ return true ;
375
+ }
355
376
356
- static unsigned getMemoryConstraintID (unsigned Flag) {
357
- assert ((isMemKind (Flag) || isFuncKind (Flag)) &&
358
- " Not expected mem or function flang!" );
359
- return (Flag >> Constraints_ShiftAmount) & 0x7fff ;
360
- }
377
+ // TODO: convert to enum?
378
+ unsigned getMemoryConstraintID () const {
379
+ assert ((isMemKind () || isFuncKind ()) &&
380
+ " Not expected mem or function flag!" );
381
+ return getData ();
382
+ }
361
383
362
- // / getNumOperandRegisters - Extract the number of registers field from the
363
- // / inline asm operand flag.
364
- static unsigned getNumOperandRegisters (unsigned Flag) {
365
- return (Flag & 0xffff ) >> 3 ;
366
- }
384
+ // / setMatchingOp - Augment an existing flag with information indicating
385
+ // / that this input operand is tied to a previous output operand.
386
+ void setMatchingOp (unsigned MatchedOperandNo) {
387
+ assert (getData () == 0 && " Matching operand already set" );
388
+ setData (MatchedOperandNo);
389
+ setIsMatched (true );
390
+ }
367
391
368
- // / isUseOperandTiedToDef - Return true if the flag of the inline asm
369
- // / operand indicates it is an use operand that's matched to a def operand.
370
- static bool isUseOperandTiedToDef (unsigned Flag, unsigned &Idx) {
371
- if ((Flag & Flag_MatchingOperand) == 0 )
372
- return false ;
373
- Idx = (Flag & ~Flag_MatchingOperand) >> 16 ;
374
- return true ;
375
- }
392
+ // / setRegClass - Augment an existing flag with the required register class
393
+ // / for the following register operands. A tied use operand cannot have a
394
+ // / register class, use the register class from the def operand instead.
395
+ void setRegClass (unsigned RC) {
396
+ assert (!isImmKind () && " Immediates cannot have a register class" );
397
+ assert (!isMemKind () && " Memory operand cannot have a register class" );
398
+ assert (getData () == 0 && " Register class already set" );
399
+ // Store RC + 1, reserve the value 0 to mean 'no register class'.
400
+ setData (RC + 1 );
401
+ }
376
402
377
- // / hasRegClassConstraint - Returns true if the flag contains a register
378
- // / class constraint. Sets RC to the register class ID.
379
- static bool hasRegClassConstraint (unsigned Flag, unsigned &RC) {
380
- if (Flag & Flag_MatchingOperand)
381
- return false ;
382
- unsigned High = Flag >> 16 ;
383
- // getFlagWordForRegClass() uses 0 to mean no register class, and otherwise
384
- // stores RC + 1.
385
- if (!High)
386
- return false ;
387
- RC = High - 1 ;
388
- return true ;
389
- }
403
+ // / setMemConstraint - Augment an existing flag with the constraint code for
404
+ // / a memory constraint.
405
+ void setMemConstraint (unsigned Constraint) {
406
+ assert ((isMemKind () || isFuncKind ()) &&
407
+ " Flag is not a memory or function constraint!" );
408
+ assert (Constraint <= Constraints_Max && " Unknown constraint ID" );
409
+ assert (getData () == 0 && " Mem constraint already set" );
410
+ setData (Constraint);
411
+ }
412
+ // / clearMemConstraint - Similar to setMemConstraint(0), but without the
413
+ // / assertion checking that the constraint has not been set previously.
414
+ void clearMemConstraint () {
415
+ assert ((isMemKind () || isFuncKind ()) &&
416
+ " Flag is not a memory or function constraint!" );
417
+ setData (0 );
418
+ }
419
+ };
390
420
391
421
static std::vector<StringRef> getExtraInfoNames (unsigned ExtraInfo) {
392
422
std::vector<StringRef> Result;
@@ -412,25 +442,6 @@ class InlineAsm final : public Value {
412
442
return Result;
413
443
}
414
444
415
- static StringRef getKindName (Kind Kind) {
416
- switch (Kind) {
417
- case Kind::RegUse:
418
- return " reguse" ;
419
- case Kind::RegDef:
420
- return " regdef" ;
421
- case Kind::RegDefEarlyClobber:
422
- return " regdef-ec" ;
423
- case Kind::Clobber:
424
- return " clobber" ;
425
- case Kind::Imm:
426
- return " imm" ;
427
- case Kind::Mem:
428
- case Kind::Func:
429
- return " mem" ;
430
- }
431
- llvm_unreachable (" Unknown operand kind" );
432
- }
433
-
434
445
static StringRef getMemConstraintName (unsigned Constraint) {
435
446
switch (Constraint) {
436
447
case InlineAsm::Constraint_es:
0 commit comments