Skip to content

Commit

Permalink
feat: exception handling rework: unwind argument as integer.
Browse files Browse the repository at this point in the history
Instead of using void* to represent the unwind argument, switch to using
an int. The argument was really just an int all along ,and we were
pretending it was a pointer to conform to the ABI.
Future changes related to Address Spaces will require changes to the ABI
anyway (the pointer would need an address space, probably multiple), so the
least painful option is to just use int.
  • Loading branch information
yuri91 committed Nov 22, 2024
1 parent 52e7fe4 commit 0a1fc66
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 80 deletions.
49 changes: 21 additions & 28 deletions clang/lib/CodeGen/CGException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,12 @@ static llvm::FunctionCallee getSehTryEndFn(CodeGenModule &CGM) {
static llvm::FunctionCallee getUnexpectedFn(CodeGenModule &CGM) {
// void __cxa_call_unexpected(void *thrown_exception);

llvm::Type* ArgTy = CGM.Int8PtrTy;
if (CGM.getLangOpts().Cheerp) {
ArgTy = CGM.Int32Ty;
}
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*isVarArg=*/false);
llvm::FunctionType::get(CGM.VoidTy, ArgTy, /*isVarArg=*/false);

return CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected");
}
Expand Down Expand Up @@ -96,8 +100,12 @@ llvm::FunctionCallee CodeGenModule::getTerminateFn() {

static llvm::FunctionCallee getCatchallRethrowFn(CodeGenModule &CGM,
StringRef Name) {
llvm::Type* ArgTy = CGM.Int8PtrTy;
if (CGM.getLangOpts().Cheerp) {
ArgTy = CGM.Int32Ty;
}
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*isVarArg=*/false);
llvm::FunctionType::get(CGM.VoidTy, ArgTy, /*isVarArg=*/false);

return CGM.CreateRuntimeFunction(FTy, Name);
}
Expand Down Expand Up @@ -460,9 +468,13 @@ void CodeGenFunction::EmitTypedPtrExprToExn(const Expr *e, Address addr) {


Address CodeGenFunction::getExceptionSlot() {
llvm::Type* Ty = Int8PtrTy;
if(CGM.getLangOpts().Cheerp) {
Ty = Int32Ty;
}
if (!ExceptionSlot)
ExceptionSlot = CreateTempAlloca(Int8PtrTy, "exn.slot");
return Address(ExceptionSlot, Int8PtrTy, getPointerAlign());
ExceptionSlot = CreateTempAlloca(Ty, "exn.slot");
return Address(ExceptionSlot, Ty, getPointerAlign());
}

Address CodeGenFunction::getEHSelectorSlot() {
Expand Down Expand Up @@ -878,14 +890,6 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
LPadInst = Builder.CreateLandingPad(LPadTy, 0);

llvm::Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0);
if(!CGM.getTarget().isByteAddressable()) {
if (CGM.getTarget().getTriple().isCheerpWasm()) {
LPadExn = Builder.CreateIntToPtr(LPadExn, Int8PtrTy);
} else {
llvm::Function *MakeReg = CGM.getIntrinsic(llvm::Intrinsic::cheerp_make_regular, {Int8PtrTy, Int8PtrTy});
LPadExn = Builder.CreateCall(MakeReg, {llvm::ConstantPointerNull::get(Int8PtrTy), LPadExn});
}
}
Builder.CreateStore(LPadExn, getExceptionSlot());
llvm::Value *LPadSel = Builder.CreateExtractValue(LPadInst, 1);
Builder.CreateStore(LPadSel, getEHSelectorSlot());
Expand Down Expand Up @@ -1538,6 +1542,11 @@ void CodeGenFunction::FinallyInfo::exit(CodeGenFunction &CGF) {
// If there's a begin-catch function, call it.
if (BeginCatchFn) {
exn = CGF.getExceptionFromSlot();
// In Cheerp Exn has type int, but the ObjC runtime expects void*.
// Just add an inttoptr here, we are doing it just to pass tests
if (CGF.getLangOpts().Cheerp && CGF.getLangOpts().ObjC) {
exn = CGF.Builder.CreateIntToPtr(exn, CGF.VoidPtrTy);
}
CGF.EmitNounwindRuntimeCall(BeginCatchFn, exn);
}

Expand Down Expand Up @@ -1584,14 +1593,6 @@ llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() {
llvm::Value *Exn = nullptr;
if (getLangOpts().CPlusPlus) {
Exn = Builder.CreateExtractValue(LPadInst, 0);
if(!CGM.getTarget().isByteAddressable()) {
if (CGM.getTarget().getTriple().isCheerpWasm()) {
Exn = Builder.CreateIntToPtr(Exn, Int8PtrTy);
} else {
llvm::Function *MakeReg = CGM.getIntrinsic(llvm::Intrinsic::cheerp_make_regular, {Int8PtrTy, Int8PtrTy});
Exn = Builder.CreateCall(MakeReg, {llvm::ConstantPointerNull::get(Int8PtrTy), Exn});
}
}
}
llvm::CallInst *terminateCall =
CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
Expand Down Expand Up @@ -1692,14 +1693,6 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) {

llvm::Type *LPadType = GetLandingPadTy();
llvm::Value *LPadVal = llvm::UndefValue::get(LPadType);
if (!CGM.getTarget().isByteAddressable()) {
if (CGM.getTarget().getTriple().isCheerpWasm()) {
Exn = Builder.CreatePtrToInt(Exn, Int32Ty);
} else {
llvm::Function *PtrOffset = CGM.getIntrinsic(llvm::Intrinsic::cheerp_pointer_offset, {Int8PtrTy});
Exn = Builder.CreateCall(PtrOffset, Exn);
}
}
LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val");
LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val");
Builder.CreateResume(LPadVal);
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/CGObjCRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,11 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
}

llvm::Value *RawExn = CGF.getExceptionFromSlot();
// In Cheerp Exn has type int, but the ObjC runtime expects void*.
// Just add an inttoptr here, we are doing it just to pass tests
if (CGM.getLangOpts().Cheerp) {
RawExn = CGF.Builder.CreateIntToPtr(RawExn, CGM.VoidPtrTy);
}

// Enter the catch.
llvm::Value *Exn = RawExn;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -2010,7 +2010,7 @@ class CodeGenFunction : public CodeGenTypeCache {

/// Get the named landingpad/resume type (Cheerp)
llvm::StructType* GetLandingPadTy() {
if (getTarget().isByteAddressable()) {
if(!getLangOpts().Cheerp) {
return llvm::StructType::get(Int8PtrTy, Int32Ty);
}
auto* Ret = llvm::StructType::getTypeByName(CGM.getLLVMContext(), "struct._ZN10__cxxabiv119__cheerp_landingpadE");
Expand Down
43 changes: 33 additions & 10 deletions clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4823,12 +4823,20 @@ void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) {
}
}

static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM) {
static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM, bool asmjs) {
llvm::Type* RetTy = CGM.Int8PtrTy;
llvm::Type* ArgTy = CGM.Int8PtrTy;
const char* name = "__cxa_begin_catch";
if (CGM.getLangOpts().Cheerp) {
ArgTy = CGM.Int32Ty;
if (asmjs)
name = "__cxa_begin_catch_wasm";
}
// void *__cxa_begin_catch(void*);
llvm::FunctionType *FTy = llvm::FunctionType::get(
CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
RetTy, ArgTy, /*isVarArg=*/false);

return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
return CGM.CreateRuntimeFunction(FTy, name);
}

static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) {
Expand All @@ -4839,12 +4847,20 @@ static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) {
return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch");
}

static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM) {
static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM, bool asmjs) {
llvm::Type* RetTy = CGM.Int8PtrTy;
llvm::Type* ArgTy = CGM.Int8PtrTy;
const char* name = "__cxa_get_exception_ptr";
if (CGM.getLangOpts().Cheerp) {
ArgTy = CGM.Int32Ty;
if (asmjs)
name = "__cxa_get_exception_ptr_wasm";
}
// void *__cxa_get_exception_ptr(void*);
llvm::FunctionType *FTy = llvm::FunctionType::get(
CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
RetTy, ArgTy, /*isVarArg=*/false);

return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");
return CGM.CreateRuntimeFunction(FTy, name);
}

namespace {
Expand Down Expand Up @@ -4882,8 +4898,9 @@ namespace {
static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
llvm::Value *Exn,
bool EndMightThrow) {
bool asmjs = CGF.CurFn->getSection() == "asmjs";
llvm::CallInst *call =
CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);
CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM, asmjs), Exn);

CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);

Expand Down Expand Up @@ -5035,10 +5052,11 @@ static void InitCatchParam(CodeGenFunction &CGF,
return;
}

bool asmjs = CGF.CurFn->getSection() == "asmjs";
// We have to call __cxa_get_exception_ptr to get the adjusted
// pointer before copying.
llvm::CallInst *rawAdjustedExn =
CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);
CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM, asmjs), Exn);

// Cast that to the appropriate type.
Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
Expand Down Expand Up @@ -5116,8 +5134,13 @@ void ItaniumCXXABI::emitBeginCatch(CodeGenFunction &CGF,
/// This code is used only in C++.
static llvm::FunctionCallee getClangCallTerminateFn(CodeGenModule &CGM) {
ASTContext &C = CGM.getContext();
bool asmjs = CGM.getTriple().isCheerpWasm();
CanQualType ArgTy = C.getPointerType(C.CharTy);
if (CGM.getLangOpts().Cheerp) {
ArgTy = C.IntTy;
}
const CGFunctionInfo &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
C.VoidTy, {C.getPointerType(C.CharTy)});
C.VoidTy, {ArgTy});
llvm::FunctionType *fnTy = CGM.getTypes().GetFunctionType(FI);
llvm::FunctionCallee fnRef = CGM.CreateRuntimeFunction(
fnTy, "__clang_call_terminate", llvm::AttributeList(), /*Local=*/true);
Expand Down Expand Up @@ -5149,7 +5172,7 @@ static llvm::FunctionCallee getClangCallTerminateFn(CodeGenModule &CGM) {
llvm::Value *exn = &*fn->arg_begin();

// Call __cxa_begin_catch(exn).
llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn);
llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM, asmjs), exn);
catchCall->setDoesNotThrow();
catchCall->setCallingConv(CGM.getRuntimeCC());

Expand Down
7 changes: 6 additions & 1 deletion compiler-rt/lib/asan/asan_interceptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,13 @@ extern "C" void __cxa_throw_wasm(void *a, void *b, void *c) {
#endif


#ifdef __CHEERP__
#define UNWIND_ARG_TYPE int
#else
#define UNWIND_ARG_TYPE void*
#endif
#if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION
INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) {
INTERCEPTOR(void, __cxa_rethrow_primary_exception, UNWIND_ARG_TYPE a) {
__asan_handle_no_return();
REAL(__cxa_rethrow_primary_exception)(a);
}
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/lib/asan/asan_interceptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ DECLARE_REAL(size_t, mbstowcs, wchar_t *dest, const char *src, size_t len);
DECLARE_REAL(size_t, mbsrtowcs, wchar_t *dest, const char **src, size_t len, void *ps);

extern "C" void __cheerp___cxa_throw(void *, void *, void *);
extern "C" void __cheerp___cxa_rethrow_primary_exception(void*);
extern "C" void __cheerp___cxa_rethrow_primary_exception(int);
#endif // SANITIZER_CHEERPWASM

# if !SANITIZER_APPLE
Expand Down
9 changes: 7 additions & 2 deletions libcxx/include/exception
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,12 @@ _LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);

class _LIBCPP_TYPE_VIS exception_ptr
{
void* __ptr_;
#ifdef __CHEERP__
unsigned
#else
void*
#endif
__ptr_;
public:
_LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {}
_LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
Expand All @@ -197,7 +202,7 @@ public:
~exception_ptr() _NOEXCEPT;

_LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT
{return __ptr_ != nullptr;}
{return __ptr_ != 0;}

friend _LIBCPP_INLINE_VISIBILITY
bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
Expand Down
2 changes: 1 addition & 1 deletion libcxx/src/support/runtime/exception_pointer_cxxabi.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ _LIBCPP_NORETURN
void
nested_exception::rethrow_nested() const
{
if (__ptr_ == nullptr)
if (__ptr_ == 0)
terminate();
rethrow_exception(__ptr_);
}
Expand Down
14 changes: 10 additions & 4 deletions libcxxabi/include/cxxabi.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,21 @@ extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name,
char *output_buffer,
size_t *length, int *status);

#ifdef __CHEERP__
#define UNWIND_TY int
#else
#define UNWIND_TY void*
#endif

// Apple additions to support C++ 0x exception_ptr class
// These are primitives to wrap a smart pointer around an exception object
extern _LIBCXXABI_FUNC_VIS void *__cxa_current_primary_exception() throw();
extern _LIBCXXABI_FUNC_VIS UNWIND_TY __cxa_current_primary_exception() throw();
extern _LIBCXXABI_FUNC_VIS void
__cxa_rethrow_primary_exception(void *primary_exception);
__cxa_rethrow_primary_exception(UNWIND_TY primary_exception);
extern _LIBCXXABI_FUNC_VIS void
__cxa_increment_exception_refcount(void *primary_exception) throw();
__cxa_increment_exception_refcount(UNWIND_TY primary_exception) throw();
extern _LIBCXXABI_FUNC_VIS void
__cxa_decrement_exception_refcount(void *primary_exception) throw();
__cxa_decrement_exception_refcount(UNWIND_TY primary_exception) throw();

// Apple extension to support std::uncaught_exception()
extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() throw();
Expand Down
Loading

0 comments on commit 0a1fc66

Please sign in to comment.