Skip to content

Commit c142c06

Browse files
committed
Place the BlockAddress type in the address space of the containing function
While this should not matter for most architectures (where the program address space is 0), it is important for CHERI (and therefore Arm Morello). We use address space 200 for all of our code pointers and without this change we assert in the SelectionDAG handling of BlockAddress nodes. It is also useful for AVR: previously programs targeting AVR that attempt to read their own machine code via a pointer to a label would instead read from RAM using a pointer relative to the the start of program flash. Reviewed By: dylanmckay, theraven Differential Revision: https://reviews.llvm.org/D48803
1 parent 791ddb7 commit c142c06

File tree

7 files changed

+392
-25
lines changed

7 files changed

+392
-25
lines changed

llvm/docs/LangRef.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4078,7 +4078,11 @@ Addresses of Basic Blocks
40784078
``blockaddress(@function, %block)``
40794079

40804080
The '``blockaddress``' constant computes the address of the specified
4081-
basic block in the specified function, and always has an ``i8*`` type.
4081+
basic block in the specified function.
4082+
4083+
It always has an ``i8 addrspace(P)*`` type, where ``P`` is the address space
4084+
of the function containing ``%block`` (usually ``addrspace(0)``).
4085+
40824086
Taking the address of the entry block is illegal.
40834087

40844088
This value only has defined behavior when used as an operand to the

llvm/include/llvm/AsmParser/LLParser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,8 @@ namespace llvm {
507507
PerFunctionState &PFS);
508508

509509
// Constant Parsing.
510-
bool parseValID(ValID &ID, PerFunctionState *PFS = nullptr);
510+
bool parseValID(ValID &ID, PerFunctionState *PFS,
511+
Type *ExpectedTy = nullptr);
511512
bool parseGlobalValue(Type *Ty, Constant *&C);
512513
bool parseGlobalTypeAndValue(Constant *&V);
513514
bool parseGlobalValueVector(SmallVectorImpl<Constant *> &Elts,

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,7 @@ bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc,
970970
} else {
971971
// The bitcast dest type is not present, it is implied by the dest type.
972972
ValID ID;
973-
if (parseValID(ID))
973+
if (parseValID(ID, /*PFS=*/nullptr))
974974
return true;
975975
if (ID.Kind != ValID::t_Constant)
976976
return error(AliaseeLoc, "invalid aliasee");
@@ -3321,7 +3321,7 @@ BasicBlock *LLParser::PerFunctionState::defineBB(const std::string &Name,
33213321
/// sanity. PFS is used to convert function-local operands of metadata (since
33223322
/// metadata operands are not just parsed here but also converted to values).
33233323
/// PFS can be null when we are not parsing metadata values inside a function.
3324-
bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) {
3324+
bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
33253325
ID.Loc = Lex.getLoc();
33263326
switch (Lex.getKind()) {
33273327
default:
@@ -3493,10 +3493,10 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) {
34933493
ValID Fn, Label;
34943494

34953495
if (parseToken(lltok::lparen, "expected '(' in block address expression") ||
3496-
parseValID(Fn) ||
3496+
parseValID(Fn, PFS) ||
34973497
parseToken(lltok::comma,
34983498
"expected comma in block address expression") ||
3499-
parseValID(Label) ||
3499+
parseValID(Label, PFS) ||
35003500
parseToken(lltok::rparen, "expected ')' in block address expression"))
35013501
return true;
35023502

@@ -3531,9 +3531,27 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) {
35313531
std::map<ValID, GlobalValue *>()))
35323532
.first->second.insert(std::make_pair(std::move(Label), nullptr))
35333533
.first->second;
3534-
if (!FwdRef)
3535-
FwdRef = new GlobalVariable(*M, Type::getInt8Ty(Context), false,
3536-
GlobalValue::InternalLinkage, nullptr, "");
3534+
if (!FwdRef) {
3535+
unsigned FwdDeclAS;
3536+
if (ExpectedTy) {
3537+
// If we know the type that the blockaddress is being assigned to,
3538+
// we can use the address space of that type.
3539+
if (!ExpectedTy->isPointerTy())
3540+
return error(ID.Loc,
3541+
"type of blockaddress must be a pointer and not '" +
3542+
getTypeString(ExpectedTy) + "'");
3543+
FwdDeclAS = ExpectedTy->getPointerAddressSpace();
3544+
} else if (PFS) {
3545+
// Otherwise, we default the address space of the current function.
3546+
FwdDeclAS = PFS->getFunction().getAddressSpace();
3547+
} else {
3548+
llvm_unreachable("Unknown address space for blockaddress");
3549+
}
3550+
FwdRef = new GlobalVariable(
3551+
*M, Type::getInt8Ty(Context), false, GlobalValue::InternalLinkage,
3552+
nullptr, "", nullptr, GlobalValue::NotThreadLocal, FwdDeclAS);
3553+
}
3554+
35373555
ID.ConstantVal = FwdRef;
35383556
ID.Kind = ValID::t_Constant;
35393557
return false;
@@ -3570,7 +3588,7 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS) {
35703588

35713589
ValID Fn;
35723590

3573-
if (parseValID(Fn))
3591+
if (parseValID(Fn, PFS))
35743592
return true;
35753593

35763594
if (Fn.Kind != ValID::t_GlobalID && Fn.Kind != ValID::t_GlobalName)
@@ -3960,7 +3978,7 @@ bool LLParser::parseGlobalValue(Type *Ty, Constant *&C) {
39603978
C = nullptr;
39613979
ValID ID;
39623980
Value *V = nullptr;
3963-
bool Parsed = parseValID(ID) ||
3981+
bool Parsed = parseValID(ID, /*PFS=*/nullptr, Ty) ||
39643982
convertValIDToValue(Ty, ID, V, nullptr, /*IsCall=*/false);
39653983
if (V && !(C = dyn_cast<Constant>(V)))
39663984
return error(ID.Loc, "global values must be constants");
@@ -5679,7 +5697,9 @@ bool LLParser::convertValIDToValue(Type *Ty, ValID &ID, Value *&V,
56795697
return false;
56805698
case ValID::t_Constant:
56815699
if (ID.ConstantVal->getType() != Ty)
5682-
return error(ID.Loc, "constant expression type mismatch");
5700+
return error(ID.Loc, "constant expression type mismatch: got type '" +
5701+
getTypeString(ID.ConstantVal->getType()) +
5702+
"' but expected '" + getTypeString(Ty) + "'");
56835703
V = ID.ConstantVal;
56845704
return false;
56855705
case ValID::t_ConstantStruct:
@@ -5739,7 +5759,7 @@ bool LLParser::parseConstantValue(Type *Ty, Constant *&C) {
57395759
bool LLParser::parseValue(Type *Ty, Value *&V, PerFunctionState *PFS) {
57405760
V = nullptr;
57415761
ValID ID;
5742-
return parseValID(ID, PFS) ||
5762+
return parseValID(ID, PFS, Ty) ||
57435763
convertValIDToValue(Ty, ID, V, PFS, /*IsCall=*/false);
57445764
}
57455765

@@ -6033,7 +6053,12 @@ bool LLParser::PerFunctionState::resolveForwardRefBlockAddresses() {
60336053
if (!BB)
60346054
return P.error(BBID.Loc, "referenced value is not a basic block");
60356055

6036-
GV->replaceAllUsesWith(BlockAddress::get(&F, BB));
6056+
Value *ResolvedVal = BlockAddress::get(&F, BB);
6057+
ResolvedVal = P.checkValidVariableType(BBID.Loc, BBID.StrVal, GV->getType(),
6058+
ResolvedVal, false);
6059+
if (!ResolvedVal)
6060+
return true;
6061+
GV->replaceAllUsesWith(ResolvedVal);
60376062
GV->eraseFromParent();
60386063
}
60396064

@@ -6568,7 +6593,7 @@ bool LLParser::parseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
65686593
if (parseOptionalCallingConv(CC) || parseOptionalReturnAttrs(RetAttrs) ||
65696594
parseOptionalProgramAddrSpace(InvokeAddrSpace) ||
65706595
parseType(RetType, RetTypeLoc, true /*void allowed*/) ||
6571-
parseValID(CalleeID) || parseParameterList(ArgList, PFS) ||
6596+
parseValID(CalleeID, &PFS) || parseParameterList(ArgList, PFS) ||
65726597
parseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false,
65736598
NoBuiltinLoc) ||
65746599
parseOptionalOperandBundles(BundleList, PFS) ||
@@ -6876,7 +6901,7 @@ bool LLParser::parseCallBr(Instruction *&Inst, PerFunctionState &PFS) {
68766901
BasicBlock *DefaultDest;
68776902
if (parseOptionalCallingConv(CC) || parseOptionalReturnAttrs(RetAttrs) ||
68786903
parseType(RetType, RetTypeLoc, true /*void allowed*/) ||
6879-
parseValID(CalleeID) || parseParameterList(ArgList, PFS) ||
6904+
parseValID(CalleeID, &PFS) || parseParameterList(ArgList, PFS) ||
68806905
parseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false,
68816906
NoBuiltinLoc) ||
68826907
parseOptionalOperandBundles(BundleList, PFS) ||
@@ -7303,7 +7328,7 @@ bool LLParser::parseCall(Instruction *&Inst, PerFunctionState &PFS,
73037328
if (parseOptionalCallingConv(CC) || parseOptionalReturnAttrs(RetAttrs) ||
73047329
parseOptionalProgramAddrSpace(CallAddrSpace) ||
73057330
parseType(RetType, RetTypeLoc, true /*void allowed*/) ||
7306-
parseValID(CalleeID) ||
7331+
parseValID(CalleeID, &PFS) ||
73077332
parseParameterList(ArgList, PFS, TCK == CallInst::TCK_MustTail,
73087333
PFS.getFunction().isVarArg()) ||
73097334
parseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false, BuiltinLoc) ||
@@ -7979,9 +8004,9 @@ bool LLParser::parseUseListOrderBB() {
79798004

79808005
ValID Fn, Label;
79818006
SmallVector<unsigned, 16> Indexes;
7982-
if (parseValID(Fn) ||
8007+
if (parseValID(Fn, /*PFS=*/nullptr) ||
79838008
parseToken(lltok::comma, "expected comma in uselistorder_bb directive") ||
7984-
parseValID(Label) ||
8009+
parseValID(Label, /*PFS=*/nullptr) ||
79858010
parseToken(lltok::comma, "expected comma in uselistorder_bb directive") ||
79868011
parseUseListOrderIndexes(Indexes))
79878012
return true;

llvm/lib/IR/Constants.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,8 +1829,8 @@ BlockAddress *BlockAddress::get(Function *F, BasicBlock *BB) {
18291829
}
18301830

18311831
BlockAddress::BlockAddress(Function *F, BasicBlock *BB)
1832-
: Constant(Type::getInt8PtrTy(F->getContext()), Value::BlockAddressVal,
1833-
&Op<0>(), 2) {
1832+
: Constant(Type::getInt8PtrTy(F->getContext(), F->getAddressSpace()),
1833+
Value::BlockAddressVal, &Op<0>(), 2) {
18341834
setOperand(0, F);
18351835
setOperand(1, BB);
18361836
BB->AdjustBlockAddressRefCount(1);

0 commit comments

Comments
 (0)