Use nonnull and dereferenceable attributes for function params

This commit is contained in:
Martin 2015-12-14 00:58:25 +01:00
parent 956061c3c7
commit 7fc28d8143
3 changed files with 26 additions and 14 deletions

View file

@ -55,6 +55,11 @@ AttrBuilder &AttrBuilder::addByVal(unsigned alignment) {
return *this; return *this;
} }
AttrBuilder &AttrBuilder::addDereferenceable(unsigned size) {
builder.addDereferenceableAttr(size);
return *this;
}
AttrSet::AttrSet(const AttrSet &base, unsigned index, LLAttribute attribute) AttrSet::AttrSet(const AttrSet &base, unsigned index, LLAttribute attribute)
: set(base.set.addAttribute(gIR->context(), index, attribute)) {} : set(base.set.addAttribute(gIR->context(), index, attribute)) {}

View file

@ -30,6 +30,7 @@ public:
AttrBuilder &addAlignment(unsigned alignment); AttrBuilder &addAlignment(unsigned alignment);
AttrBuilder &addByVal(unsigned alignment); AttrBuilder &addByVal(unsigned alignment);
AttrBuilder &addDereferenceable(unsigned size);
operator llvm::AttrBuilder &() { return builder; } operator llvm::AttrBuilder &() { return builder; }
operator const llvm::AttrBuilder &() const { return builder; } operator const llvm::AttrBuilder &() const { return builder; }

View file

@ -70,7 +70,7 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
} else { } else {
Type *rt = f->next; Type *rt = f->next;
const bool byref = f->isref && rt->toBasetype()->ty != Tvoid; const bool byref = f->isref && rt->toBasetype()->ty != Tvoid;
AttrBuilder attrBuilder; AttrBuilder attrs;
if (abi->returnInArg(f)) { if (abi->returnInArg(f)) {
// sret return // sret return
@ -87,24 +87,27 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
++nextLLArgIdx; ++nextLLArgIdx;
} else { } else {
// sext/zext return // sext/zext return
attrBuilder.add(DtoShouldExtend(byref ? rt->pointerTo() : rt)); attrs.add(DtoShouldExtend(byref ? rt->pointerTo() : rt));
} }
newIrFty.ret = new IrFuncTyArg(rt, byref, attrBuilder); newIrFty.ret = new IrFuncTyArg(rt, byref, attrs);
} }
++nextLLArgIdx; ++nextLLArgIdx;
if (thistype) { if (thistype) {
// Add the this pointer for member functions // Add the this pointer for member functions
AttrBuilder attrBuilder; AttrBuilder attrs;
attrs.add(LLAttribute::NonNull);
if (isCtor) { if (isCtor) {
attrBuilder.add(LLAttribute::Returned); attrs.add(LLAttribute::Returned);
} }
newIrFty.arg_this = new IrFuncTyArg( newIrFty.arg_this =
thistype, thistype->toBasetype()->ty == Tstruct, attrBuilder); new IrFuncTyArg(thistype, thistype->toBasetype()->ty == Tstruct, attrs);
++nextLLArgIdx; ++nextLLArgIdx;
} else if (nesttype) { } else if (nesttype) {
// Add the context pointer for nested functions // Add the context pointer for nested functions
newIrFty.arg_nest = new IrFuncTyArg(nesttype, false); AttrBuilder attrs;
attrs.add(LLAttribute::NonNull);
newIrFty.arg_nest = new IrFuncTyArg(nesttype, false, attrs);
++nextLLArgIdx; ++nextLLArgIdx;
} }
@ -141,27 +144,30 @@ llvm::FunctionType *DtoFunctionType(Type *type, IrFuncTy &irFty, Type *thistype,
bool passPointer = arg->storageClass & (STCref | STCout); bool passPointer = arg->storageClass & (STCref | STCout);
Type *loweredDType = arg->type; Type *loweredDType = arg->type;
AttrBuilder attrBuilder; AttrBuilder attrs;
if (arg->storageClass & STClazy) { if (arg->storageClass & STClazy) {
// Lazy arguments are lowered to delegates. // Lazy arguments are lowered to delegates.
Logger::println("lazy param"); Logger::println("lazy param");
auto ltf = new TypeFunction(nullptr, arg->type, 0, LINKd); auto ltf = new TypeFunction(nullptr, arg->type, 0, LINKd);
auto ltd = new TypeDelegate(ltf); auto ltd = new TypeDelegate(ltf);
loweredDType = ltd; loweredDType = ltd;
} else if (!passPointer) { } else if (passPointer) {
// ref/out
attrs.addDereferenceable(loweredDType->size());
} else {
if (abi->passByVal(loweredDType)) { if (abi->passByVal(loweredDType)) {
// LLVM ByVal parameters are pointers to a copy in the function // LLVM ByVal parameters are pointers to a copy in the function
// parameters stack. The caller needs to provide a pointer to the // parameters stack. The caller needs to provide a pointer to the
// original argument. // original argument.
attrBuilder.addByVal(DtoAlignment(loweredDType)); attrs.addByVal(DtoAlignment(loweredDType));
passPointer = true; passPointer = true;
} else { } else {
// Add sext/zext as needed. // Add sext/zext as needed.
attrBuilder.add(DtoShouldExtend(loweredDType)); attrs.add(DtoShouldExtend(loweredDType));
} }
} }
newIrFty.args.push_back(
new IrFuncTyArg(loweredDType, passPointer, attrBuilder)); newIrFty.args.push_back(new IrFuncTyArg(loweredDType, passPointer, attrs));
newIrFty.args.back()->parametersIdx = i; newIrFty.args.back()->parametersIdx = i;
++nextLLArgIdx; ++nextLLArgIdx;
} }