aboutsummaryrefslogtreecommitdiff
path: root/include/cps/CABI.h
blob: ba776e907ecd4ad6f323ea25b066d99bbdd2d2d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

#pragma once
#include "llvm/ADT/ArrayRef.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
#include <cstdint>
#include <memory>
#include <string>
#include <vector>

namespace cps {

struct TypeInfo;
class TypeSystem;

// One EXTERN "C" parameter or result as clang's ABIArgInfo arranges it. Only
// the kinds our targets use exist here; ClangABI reports any other kind as an
// internal error.
struct CABIArg {
    enum class Kind { Direct, Extend, Indirect, Ignore };
    Kind K = Kind::Direct;
    llvm::Type *ValueType = nullptr;  // the pseudocode value; void for VOID
    llvm::Type *CoerceType = nullptr; // Direct, Extend: the IR type passed
    unsigned Offset = 0;              // Direct, Extend: byte offset of the coerced part
    bool Flatten = false;             // Direct: a struct CoerceType passed element by element
    unsigned DirectAlign = 0;         // Direct, Extend: stack alignment, if any
    llvm::Attribute::AttrKind Extension = llvm::Attribute::None; // Extend: SExt, ZExt or NoExt
    bool ByVal = false;               // Indirect: byval, otherwise a pointer to a copy
    uint64_t Align = 0;               // Indirect: alignment of the memory in bytes
    bool InReg = false;
};

// An arranged EXTERN signature. Args holds the Fixed prototype parameters and,
// for one variadic call, the promoted variadic arguments after them.
struct CABISignature {
    CABIArg Ret;
    std::vector<CABIArg> Args;
    size_t Fixed = 0;
    bool Variadic = false;
    unsigned CallingConv = 0;
};

// Arranges signatures for the host C ABI with clang's CodeGen. The clang
// context is created on the first call; ClangABI.cc is the only file that
// includes clang headers.
class ClangABI {
public:
    ClangABI(llvm::LLVMContext &Context, const TypeSystem &Types);
    ~ClangABI();
    // Ret is nullptr for VOID; the first Fixed of Args are the prototype's
    // parameters. On failure Err holds the reason for an internal error.
    bool arrange(const TypeInfo *Ret, const std::vector<const TypeInfo *> &Args, size_t Fixed,
                 bool Variadic, CABISignature &Sig, std::string &Err);

private:
    struct State;
    llvm::LLVMContext &Context;
    const TypeSystem &Types;
    std::unique_ptr<State> S;
};

// Generic lowering of an arranged signature (Lowering.cc), without
// per-architecture code.
// The declared function type, from the fixed parameters.
llvm::FunctionType *getCABIFunctionType(const CABISignature &Sig);
// The call attributes, for every argument in Sig.
llvm::AttributeList getCABIAttributes(llvm::LLVMContext &C, const CABISignature &Sig);
// The IR arguments for one pseudocode value per Sig.Args entry. SRet receives
// the result memory when the result is returned indirectly.
std::vector<llvm::Value *> lowerCABIArguments(llvm::IRBuilder<> &B, const CABISignature &Sig,
                                              llvm::ArrayRef<llvm::Value *> Args, llvm::Value *&SRet);
// The pseudocode result of Call; nullptr for VOID.
llvm::Value *lowerCABIResult(llvm::IRBuilder<> &B, const CABISignature &Sig, llvm::Value *Call,
                             llvm::Value *SRet);

} // namespace cps