[patch] Clarify and verify what llvm.used is

Duncan Sands baldrick at free.fr
Tue Apr 16 22:58:55 PDT 2013


Hi Rafael,

On 17/04/13 01:18, Rafael EspĂ­ndola wrote:
> When reviewing my previous patch to GlobalOpt Duncan raised some
> questions about the semantics of llvm.used. We should probably clarify
> the documentation and have the verifier check it before anything else.
>
> The attached patch makes it explicit that aliases can be put in
> llvm.used and changes the verifier to check llvm.used only has
> functions, variables and aliases.
>
> Duncan, are you OK with this definition? Is the patch OK?

I think the definition is fine.  However

>
> +++ b/lib/IR/Verifier.cpp
> @@ -446,6 +446,32 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
>      }
>    }
>
> +  if (GV.hasName() && (GV.getName() == "llvm.used")) {
> +    Assert1(!GV.hasInitializer() || GV.hasAppendingLinkage(),
> +            "invalid linkage for intrinsic global variable", &GV);

I don't think the verifier should be testing the linkage.  Using a different
kind of linkage does probably indicate that the user made a mistake, but as it
doesn't have any impact on LLVM itself (eg it doesn't make optimizations invalid
or something problematic like that) I don't think it should be illegal.  Maybe
this check could be moved into the "lint" pass.

> +    Type *GVType = cast<PointerType>(GV.getType())->getElementType();
> +    if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) {

Should it be allowed to not have array type?  If we decide to only allow array
type then all the places that work with llvm.used can probably be simplified a
bit, since I think they all bail out if the type is not an array type.

> +      PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType());
> +      Assert1(PTy, "wrong type for intrinsic global variable", &GV);
> +      IntegerType *IntTy = dyn_cast<IntegerType>(PTy->getElementType());
> +      Assert1(IntTy && IntTy->getBitWidth() == 8,
> +              "wrong type for intrinsic global variable", &GV);

I don't think we should test for a particular pointer type.  Traditionally
people use i8*, but as the pointer type doesn't have any semantic impact I
don't think using other types should be illegal.  For example, using {}*
would be perfectly reasonable IMO.

> +      if (GV.hasInitializer()) {
> +        Constant *Init = GV.getInitializer();
> +        ConstantArray *InitArray = dyn_cast<ConstantArray>(Init);
> +        Assert1(InitArray, "wrong initalizer for intrinsic global variable",
> +                Init);

This would reject a zero length array type initialized to null.  So maybe only
test this if the array length is non-zero?

> +        for (unsigned i = 0, e = InitArray->getNumOperands(); i != e; ++i) {
> +          Value *V = Init->getOperand(i)->stripPointerCasts();
> +          // stripPointerCasts strips aliases, so we only need to check for
> +          // variables and functions.
> +          Assert1(isa<GlobalVariable>(V) || isa<Function>(V),
> +                  "invalid llvm.used member", V);
> +        }
> +      }
> +    }
> +  }
> +
>    visitGlobalValue(GV);
>  }
>

Ciao, Duncan.



More information about the cfe-commits mailing list