mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
[IR] Add verifier support for llvm.module.flags.
- Also, update the LangRef documentation on module flags to match the implementation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172498 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
096d617796
commit
8dd938ed17
@ -2462,14 +2462,16 @@ Each triplet has the following form:
|
||||
(or more) metadata with the same ID. The supported behaviors are
|
||||
described below.
|
||||
- The second element is a metadata string that is a unique ID for the
|
||||
metadata. How each ID is interpreted is documented below.
|
||||
metadata. Each module may only have one flag entry for each unique ID (not
|
||||
including entries with the **Require** behavior).
|
||||
- The third element is the value of the flag.
|
||||
|
||||
When two (or more) modules are merged together, the resulting
|
||||
``llvm.module.flags`` metadata is the union of the modules'
|
||||
``llvm.module.flags`` metadata. The only exception being a flag with the
|
||||
*Override* behavior, which may override another flag's value (see
|
||||
below).
|
||||
``llvm.module.flags`` metadata is the union of the modules' flags. That is, for
|
||||
each unique metadata ID string, there will be exactly one entry in the merged
|
||||
modules ``llvm.module.flags`` metadata table, and the value for that entry will
|
||||
be determined by the merge behavior flag, as described below. The only exception
|
||||
is that entries with the *Require* behavior are always preserved.
|
||||
|
||||
The following behaviors are supported:
|
||||
|
||||
@ -2482,25 +2484,33 @@ The following behaviors are supported:
|
||||
|
||||
* - 1
|
||||
- **Error**
|
||||
Emits an error if two values disagree. It is an error to have an
|
||||
ID with both an Error and a Warning behavior.
|
||||
Emits an error if two values disagree, otherwise the resulting value
|
||||
is that of the operands.
|
||||
|
||||
* - 2
|
||||
- **Warning**
|
||||
Emits a warning if two values disagree.
|
||||
Emits a warning if two values disagree. The result value will be the
|
||||
operand for the flag from the first module being linked.
|
||||
|
||||
* - 3
|
||||
- **Require**
|
||||
Emits an error when the specified value is not present or doesn't
|
||||
have the specified value. It is an error for two (or more)
|
||||
``llvm.module.flags`` with the same ID to have the Require behavior
|
||||
but different values. There may be multiple Require flags per ID.
|
||||
Adds a requirement that another module flag be present and have a
|
||||
specified value after linking is performed. The value must be a
|
||||
metadata pair, where the first element of the pair is the ID of the
|
||||
module flag to be restricted, and the second element of the pair is
|
||||
the value the module flag should be restricted to. This behavior can
|
||||
be used to restrict the allowable results (via triggering of an
|
||||
error) of linking IDs with the **Override** behavior.
|
||||
|
||||
* - 4
|
||||
- **Override**
|
||||
Uses the specified value if the two values disagree. It is an
|
||||
error for two (or more) ``llvm.module.flags`` with the same ID
|
||||
to have the Override behavior but different values.
|
||||
Uses the specified value, regardless of the behavior or value of the
|
||||
other module. If both modules specify **Override**, but the values
|
||||
differ, an error will be emitted.
|
||||
|
||||
It is an error for a particular unique flag ID to have multiple behaviors,
|
||||
except in the case of **Require** (which adds restrictions on another metadata
|
||||
value) or **Override**.
|
||||
|
||||
An example of module flags:
|
||||
|
||||
@ -2522,7 +2532,7 @@ An example of module flags:
|
||||
|
||||
- Metadata ``!1`` has the ID ``!"bar"`` and the value '37'. The
|
||||
behavior if two or more ``!"bar"`` flags are seen is to use the value
|
||||
'37' if their values are not equal.
|
||||
'37'.
|
||||
|
||||
- Metadata ``!2`` has the ID ``!"qux"`` and the value '42'. The
|
||||
behavior if two or more ``!"qux"`` flags are seen is to emit a
|
||||
@ -2534,10 +2544,9 @@ An example of module flags:
|
||||
|
||||
metadata !{ metadata !"foo", i32 1 }
|
||||
|
||||
The behavior is to emit an error if the ``llvm.module.flags`` does
|
||||
not contain a flag with the ID ``!"foo"`` that has the value '1'. If
|
||||
two or more ``!"qux"`` flags exist, then they must have the same
|
||||
value or an error will be issued.
|
||||
The behavior is to emit an error if the ``llvm.module.flags`` does not
|
||||
contain a flag with the ID ``!"foo"`` that has the value '1' after linking is
|
||||
performed.
|
||||
|
||||
Objective-C Garbage Collection Module Flags Metadata
|
||||
----------------------------------------------------
|
||||
|
@ -200,6 +200,8 @@ namespace {
|
||||
E = M.named_metadata_end(); I != E; ++I)
|
||||
visitNamedMDNode(*I);
|
||||
|
||||
visitModuleFlags(M);
|
||||
|
||||
// If the module is broken, abort at this time.
|
||||
return abortIfBroken();
|
||||
}
|
||||
@ -240,6 +242,8 @@ namespace {
|
||||
void visitGlobalAlias(GlobalAlias &GA);
|
||||
void visitNamedMDNode(NamedMDNode &NMD);
|
||||
void visitMDNode(MDNode &MD, Function *F);
|
||||
void visitModuleFlags(Module &M);
|
||||
void visitModuleFlag(MDNode *Op, SmallSetVector<MDString*, 16> &SeenIDs);
|
||||
void visitFunction(Function &F);
|
||||
void visitBasicBlock(BasicBlock &BB);
|
||||
using InstVisitor<Verifier>::visit;
|
||||
@ -521,6 +525,59 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) {
|
||||
}
|
||||
}
|
||||
|
||||
void Verifier::visitModuleFlags(Module &M) {
|
||||
const NamedMDNode *Flags = M.getModuleFlagsMetadata();
|
||||
if (!Flags) return;
|
||||
|
||||
// Scan each flag.
|
||||
SmallSetVector<MDString*, 16> SeenIDs;
|
||||
for (unsigned I = 0, E = Flags->getNumOperands(); I != E; ++I) {
|
||||
visitModuleFlag(Flags->getOperand(I), SeenIDs);
|
||||
}
|
||||
}
|
||||
|
||||
void Verifier::visitModuleFlag(MDNode *Op,
|
||||
SmallSetVector<MDString*, 16> &SeenIDs) {
|
||||
// Each module flag should have three arguments, the merge behavior (a
|
||||
// constant int), the flag ID (an MDString), and the value.
|
||||
Assert1(Op->getNumOperands() == 3,
|
||||
"incorrect number of operands in module flag", Op);
|
||||
ConstantInt *Behavior = dyn_cast<ConstantInt>(Op->getOperand(0));
|
||||
MDString *ID = dyn_cast<MDString>(Op->getOperand(1));
|
||||
Assert1(Behavior,
|
||||
"invalid behavior operand in module flag (expected constant integer)",
|
||||
Op->getOperand(0));
|
||||
unsigned BehaviorValue = Behavior->getZExtValue();
|
||||
Assert1((Module::Error <= BehaviorValue &&
|
||||
BehaviorValue <= Module::Override),
|
||||
"invalid behavior operand in module flag (unexpected constant)",
|
||||
Op->getOperand(0));
|
||||
Assert1(ID,
|
||||
"invalid ID operand in module flag (expected metadata string)",
|
||||
Op->getOperand(1));
|
||||
|
||||
// Unless this is a "requires" flag, check the ID is unique.
|
||||
if (BehaviorValue != Module::Require) {
|
||||
Assert1(SeenIDs.insert(ID),
|
||||
"module flag identifiers must be unique (or of 'require' type)",
|
||||
ID);
|
||||
}
|
||||
|
||||
// If this is a "requires" flag, sanity check the value.
|
||||
if (BehaviorValue == Module::Require) {
|
||||
// The value should itself be an MDNode with two operands, a flag ID (an
|
||||
// MDString), and a value.
|
||||
MDNode *Value = dyn_cast<MDNode>(Op->getOperand(2));
|
||||
Assert1(Value && Value->getNumOperands() == 2,
|
||||
"invalid value for 'require' module flag (expected metadata pair)",
|
||||
Op->getOperand(2));
|
||||
Assert1(isa<MDString>(Value->getOperand(0)),
|
||||
("invalid value for 'require' module flag "
|
||||
"(first value operand should be a string)"),
|
||||
Value->getOperand(0));
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyParameterAttrs - Check the given attributes for an argument or return
|
||||
// value of the specified type. The value V is printed in error messages.
|
||||
void Verifier::VerifyParameterAttrs(Attribute Attrs, Type *Ty,
|
||||
|
37
test/Verifier/module-flags-1.ll
Normal file
37
test/Verifier/module-flags-1.ll
Normal file
@ -0,0 +1,37 @@
|
||||
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
; Check that module flags are structurally correct.
|
||||
;
|
||||
; CHECK: incorrect number of operands in module flag
|
||||
; CHECK: metadata !0
|
||||
!0 = metadata !{ i32 1 }
|
||||
; CHECK: invalid behavior operand in module flag (expected constant integer)
|
||||
; CHECK: metadata !"foo"
|
||||
!1 = metadata !{ metadata !"foo", metadata !"foo", i32 42 }
|
||||
; CHECK: invalid behavior operand in module flag (unexpected constant)
|
||||
; CHECK: i32 999
|
||||
!2 = metadata !{ i32 999, metadata !"foo", i32 43 }
|
||||
; CHECK: invalid ID operand in module flag (expected metadata string)
|
||||
; CHECK: i32 1
|
||||
!3 = metadata !{ i32 1, i32 1, i32 44 }
|
||||
; CHECK: invalid value for 'require' module flag (expected metadata pair)
|
||||
; CHECK: i32 45
|
||||
!4 = metadata !{ i32 3, metadata !"bla", i32 45 }
|
||||
; CHECK: invalid value for 'require' module flag (expected metadata pair)
|
||||
; CHECK: metadata !
|
||||
!5 = metadata !{ i32 3, metadata !"bla", metadata !{ i32 46 } }
|
||||
; CHECK: invalid value for 'require' module flag (first value operand should be a string)
|
||||
; CHECK: i32 47
|
||||
!6 = metadata !{ i32 3, metadata !"bla", metadata !{ i32 47, i32 48 } }
|
||||
|
||||
; Check that module flags only have unique IDs.
|
||||
;
|
||||
; CHECK: module flag identifiers must be unique (or of 'require' type)
|
||||
!7 = metadata !{ i32 1, metadata !"foo", i32 49 }
|
||||
!8 = metadata !{ i32 2, metadata !"foo", i32 50 }
|
||||
; CHECK-NOT: module flag identifiers must be unique
|
||||
!9 = metadata !{ i32 2, metadata !"bar", i32 51 }
|
||||
!10 = metadata !{ i32 3, metadata !"bar", i32 51 }
|
||||
|
||||
!llvm.module.flags = !{
|
||||
!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10 }
|
Loading…
Reference in New Issue
Block a user