Adding TBAA metadata to tinylang – Advanced IR Generation-1
To support TBAA, we must add a new CGTBAA class. This class is responsible for generating the metadata nodes. Furthermore, we make the CGTBAA class a member of the CGModule class, calling it TBAA.
Every load and store instruction must be annotated. A new function is created for this purpose in the CGModule class called decorateInst(). This function tries to create the tag access information. If this is successful, the metadata is attached to the respective load or store instruction. Moreover, this design also allows us to turn off the metadata generation process in case we do not need it, such as in builds with optimizations turned off:
void CGModule::decorateInst(llvm::Instruction *Inst,
TypeDeclaration *Type) {
if (auto *N = TBAA.getAccessTagInfo(Type))
Inst->setMetadata(llvm::LLVMContext::MD_tbaa, N);
}
We put the declaration of the new CGTBAA class in the include/tinylang/CodeGen/CGTBAA.h header file and the definition in the lib/CodeGen/CGTBAA.cpp file. Aside from the AST definitions, the header file needs to include the files for defining the metadata nodes and builder:
include “tinylang/AST/AST.h”
include “llvm/IR/MDBuilder.h”
include “llvm/IR/Metadata.h”
The CGTBAA class needs to store some data members. So, let’s see how to do this step by step:
- First of all, we need to cache the root of the type hierarchy: class CGTBAA {
llvm::MDNode *Root; - To construct the metadata nodes, we need an instance of the MDBuilder class: llvm::MDBuilder MDHelper;
- Lastly, we must store the metadata that’s been generated for a type for reuse: llvm::DenseMap MetadataCache;
// …
};
Now that we’ve defined the variables that are required for the construction, we must add the methods that are required to create the metadata:
- The constructor initializes the data members:
CGTBAA::CGTBAA(CGModule &CGM)
: CGM(CGM),
MDHelper(llvm::MDBuilder(CGM.getLLVMCtx())),
Root(nullptr) {}
- We must lazily instantiate the root of the type hierarchy, which we name Simple tinylang TBAA:
llvm::MDNode *CGTBAA::getRoot() {
if (!Root)
Root = MDHelper.createTBAARoot(“Simple tinylang TBAA”);
return Root;
}
- For a scalar type, we must create a metadata node with the help of the MDBuilder class based on the name of the type. The new metadata node is stored in the cache:
llvm::MDNode *
CGTBAA::createScalarTypeNode(TypeDeclaration *Ty,
StringRef Name,
llvm::MDNode *Parent) {
llvm::MDNode *N =
MDHelper.createTBAAScalarTypeNode(Name, Parent);
return MetadataCache[Ty] = N;
}
- The method to create the metadata for a record is more complicated as we have to enumerate all the fields of the record. Similar to scalar types, the new metadata node is stored in the cache:
llvm::MDNode *CGTBAA::createStructTypeNode(
TypeDeclaration *Ty, StringRef Name,
llvm::ArrayRef>
Fields) {
llvm::MDNode *N =
MDHelper.createTBAAStructTypeNode(Name, Fields);
return MetadataCache[Ty] = N;
}