aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/LangRef.rst49
-rw-r--r--lib/IR/Verifier.cpp57
-rw-r--r--test/Verifier/module-flags-1.ll37
3 files changed, 123 insertions, 20 deletions
diff --git a/docs/LangRef.rst b/docs/LangRef.rst
index 3c49ed0..7d9fe41 100644
--- a/docs/LangRef.rst
+++ b/docs/LangRef.rst
@@ -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
----------------------------------------------------
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index 4252764..5a4a5a7 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -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,
diff --git a/test/Verifier/module-flags-1.ll b/test/Verifier/module-flags-1.ll
new file mode 100644
index 0000000..eafb113
--- /dev/null
+++ b/test/Verifier/module-flags-1.ll
@@ -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 }