Skip to content

Commit 656bde0

Browse files
author
Dwight Guth
authored
disable tail call on return values of MInt of >192 bits (#1135)
On X86 architecture, LLVM can only return integers of size up to 192 bits in registers. Return values of greater size are subject to "sret demotion", which returns the value in memory. Due to the sret implied by this, tail calls cannot be performed on functions that return these large integer types. Thus, we need to delete the MustTail attribute or code generation will crash.
1 parent c202d7c commit 656bde0

File tree

5 files changed

+2443
-2
lines changed

5 files changed

+2443
-2
lines changed

include/kllvm/codegen/CreateTerm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ std::string make_side_condition_function(
124124
kore_axiom_declaration *axiom, kore_definition *definition,
125125
llvm::Module *module);
126126

127+
bool can_tail_call(llvm::Type *type);
128+
127129
extern std::string map_struct;
128130
extern std::string list_struct;
129131
extern std::string set_struct;

lib/codegen/CreateTerm.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,19 @@ void add_abort(llvm::BasicBlock *block, llvm::Module *module) {
10381038
new llvm::UnreachableInst(module->getContext(), block);
10391039
}
10401040

1041+
bool can_tail_call(llvm::Type *type) {
1042+
if (type->isVoidTy()) {
1043+
return false;
1044+
}
1045+
if (!type->isIntegerTy()) {
1046+
return true;
1047+
}
1048+
auto *int_type = dyn_cast<llvm::IntegerType>(type);
1049+
// integer types that cannot fit in 3 64-bit registers cannot be tail
1050+
// called on X86
1051+
return int_type->getBitWidth() <= 192;
1052+
}
1053+
10411054
bool make_function(
10421055
std::string const &name, kore_pattern *pattern, kore_definition *definition,
10431056
llvm::Module *module, bool tailcc, bool big_step, bool apply,
@@ -1142,8 +1155,9 @@ bool make_function(
11421155
// 2. Return returns return value of call (guaranteed)
11431156
// 3. Calling convention is tailcc
11441157
// 4. Function is not sret (here approximated by checking if return type is void)
1158+
// 5. Function is not "sret demoted" (here approximated by checking that it is not an MInt of size >192)
11451159
if (call->getCallingConv() == llvm::CallingConv::Tail
1146-
&& call->getType() != llvm::Type::getVoidTy(module->getContext())) {
1160+
&& can_tail_call(call->getType())) {
11471161
call->setTailCallKind(llvm::CallInst::TCK_MustTail);
11481162
}
11491163
}

lib/codegen/Decision.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,9 @@ void leaf_node::codegen(decision *d) {
621621
call->setCallingConv(llvm::CallingConv::Tail);
622622

623623
if (child_ == nullptr) {
624-
call->setTailCallKind(llvm::CallInst::TCK_MustTail);
624+
if (can_tail_call(call->getType())) {
625+
call->setTailCallKind(llvm::CallInst::TCK_MustTail);
626+
}
625627
llvm::ReturnInst::Create(d->ctx_, call, d->current_block_);
626628
} else {
627629
new llvm::StoreInst(

test/defn/k-files/sret-demotion.k

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module TEST
2+
imports MINT
3+
4+
syntax MInt{256}
5+
6+
endmodule

0 commit comments

Comments
 (0)