Skip to content

Advanced IR Generation and IT Certification Exams

  • Contact Us
Close Menu

Throwing and catching exceptions – Advanced IR Generation-4

August 27, 2022August 27, 2022| Donna martinThrowing and catching exceptions – Advanced IR Generation-4| 0 Comment| 03:22

Categories :
  • Adding debug metadata
  • Adding line numbers
  • Catching an exception
  • Exams of IT
  • ITCertification Exams

With this, the exception handling facility is complete.
To use exception handling in the compiler for your programming language, the simplest strategy is to piggyback on the existing C++ runtime functions. This also has the advantage that your exceptions are interoperable with C++. The disadvantage is that you tie some of the C++ runtime into the runtime of your language, most notably memory management. If you want to avoid this, then you need to create your own equivalents of the cxa functions. Still, you will want to use libunwind, which provides the stack unwinding mechanism:

  1. Let’s look at how to create this IR. We created the calc expression compiler in Chapter 2, The Structure of a Compiler. Now, we will extend the code generator of the expression compiler to raise and handle an exception in case a division by zero is performed. The generated IR will check if the divisor of a division is 0. If true, then an exception will be raised. We will also add a landing pad to the function, which catches the exception and prints Divide by zero! to the console and ends the calculation. Using exception handling is not necessary in this simple case, but it allows us to concentrate on the code generation process. We must add all the code to the CodeGen.cpp file. We begin by adding the required new fields and some helper methods. First of all, we need to store the LLVM declaration of the __cxa_allocate_exception() and __cxa_throw() functions, which consist of the function type and the function itself. A GlobalVariable instance is needed to hold the type information. We also need references to the basic blocks holding the landing pad and a basic block containing just an unreachable instruction: GlobalVariable *TypeInfo = nullptr;
    FunctionType *AllocEHFty = nullptr;
    Function *AllocEHFn = nullptr;
    FunctionType *ThrowEHFty = nullptr;
    Function *ThrowEHFn = nullptr;
    BasicBlock *LPadBB = nullptr;
    BasicBlock *UnreachableBB = nullptr;
  2. We will also add a new helper function to create the IR for comparing two values. The createICmpEq() function takes the Left and Right values to compare as parameters. It creates a compare instruction testing for equality of the values, and a branch instruction to two basic blocks, for the equal and inequal cases. The two basic blocks are returned via references in the TrueDest and FalseDest parameters. Furthermore, a label for the new basic blocks can be given in the TrueLabel and FalseLabel parameters. The code is as follows: void createICmpEq(Value *Left, Value *Right,
    BasicBlock *&TrueDest,
    BasicBlock *&FalseDest,
    const Twine &TrueLabel = “”,
    const Twine &FalseLabel = “”) {
    Function *Fn =
    Builder.GetInsertBlock()->getParent();
    TrueDest = BasicBlock::Create(M->getContext(),
    TrueLabel, Fn);
    FalseDest = BasicBlock::Create(M->getContext(),
    FalseLabel, Fn);
    Value *Cmp = Builder.CreateCmp(CmpInst::ICMP_EQ,
    Left, Right);
    Builder.CreateCondBr(Cmp, TrueDest, FalseDest);
    }
  3. To use the functions from the runtime, we need to create several function declarations. In LLVM, a function type gives the signature, and the function itself must be constructed. We use the createFunc() method to create both objects. The functions need references to the FunctionType and Function pointers, the name of the newly declared function, and the result type. The parameter type list is optional, and the flag to indicate a variable parameter list is set to false, indicating that there is no variable part in the parameter list: void createFunc(FunctionType *&Fty, Function *&Fn,
    const Twine &N, Type *Result,
    ArrayRef Params = None,
    bool IsVarArgs = false) {
    Fty = FunctionType::get(Result, Params, IsVarArgs);
    Fn = Function::Create(
    Fty, GlobalValue::ExternalLinkage, N, M);
    }

With these preparations done, we can generate the IR to raise an exception.

Post navigation

Previous page Throwing and catching exceptions – Advanced IR Generation-3
Next page Raising an exception – Advanced IR Generation

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related Post

Creating TBAA metadata in LLVM – Advanced IR Generation

February 16, 2023February 16, 2023 Donna martinCreating TBAA metadata in LLVM – Advanced IR Generation

To create the metadata, we must use the llvm::MDBuilder class, which is declared in the [...]

Read MoreRead More

Adding line numbers – Advanced IR Generation

December 29, 2023December 29, 2023 Donna martinAdding line numbers – Advanced IR Generation

A debugger allows a programmer to step through an application line by line. For this, [...]

Read MoreRead More

Raising an exception – Advanced IR Generation

September 27, 2022September 27, 2022 Donna martinRaising an exception – Advanced IR Generation

To generate the IR code to raise an exception, we will add the addThrow() method. [...]

Read MoreRead More

Search

Dropdown Categories

Archives

  • August 2024
  • July 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • June 2022
  • May 2022
  • March 2022
  • February 2022
  • December 2021
  • November 2021

Meta

  • Log in

Tag Cloud

Back to Top

Cookie Policy | Terms | Privacy | About Us | © Sherrieland