Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] KValue base class #161

Merged
merged 4 commits into from
Dec 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/klee/Core/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class Context {

/// Returns width of the pointer in bits
Expr::Width getPointerWidth() const { return PointerWidth; }

Expr::ByteWidth getPointerWidthInBytes() const {
return (PointerWidth + CHAR_BIT - 1) / CHAR_BIT;
}
};

} // namespace klee
Expand Down
5 changes: 5 additions & 0 deletions include/klee/Expr/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ class Expr {
/// The type of an expression is simply its width, in bits.
typedef unsigned Width;

/// Width of an expression in bytes.
/// ByteWidth = (Width + CHAR_BIT - 1) / CHAR_BIT
typedef unsigned ByteWidth;

// NOTE: The prefix "Int" in no way implies the integer type of expression.
// For example, Int64 can indicate i64, double or <2 * i32> in different
// cases.
Expand Down Expand Up @@ -292,6 +296,7 @@ class Expr {

virtual Kind getKind() const = 0;
virtual Width getWidth() const = 0;
ByteWidth getByteWidth() const;

virtual unsigned getNumKids() const = 0;
virtual ref<Expr> getKid(unsigned i) const = 0;
Expand Down
13 changes: 10 additions & 3 deletions include/klee/Expr/SourceBuilder.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
#ifndef KLEE_SOURCEBUILDER_H
#define KLEE_SOURCEBUILDER_H

#include "klee/ADT/Ref.h"
#include "klee/ADT/SparseStorage.h"
#include "klee/Expr/SymbolicSource.h"
#include "klee/Module/KModule.h"

namespace klee {

class KInstruction;
class KGlobalVariable;

template <typename T, typename Eq> class SparseStorage;
template <typename T> class ref;

class SourceBuilder {
public:
SourceBuilder() = delete;
Expand All @@ -20,6 +23,10 @@ class SourceBuilder {
static ref<SymbolicSource>
symbolicSizeConstantAddress(unsigned version, const KInstruction *allocSite,
ref<Expr> size);
static ref<SymbolicSource>
symbolicSizeConstantAddress(unsigned version,
const KGlobalVariable *allocSite, ref<Expr> size);

static ref<SymbolicSource> makeSymbolic(const std::string &name,
unsigned version);
static ref<SymbolicSource> lazyInitializationAddress(ref<Expr> pointer);
Expand Down
8 changes: 5 additions & 3 deletions include/klee/Expr/SymbolicSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ namespace klee {
class Array;
class Expr;
class ConstantExpr;
struct KGlobalVariable;
class KModule;
struct KValue;
struct KInstruction;

class SymbolicSource {
Expand Down Expand Up @@ -125,10 +127,10 @@ class UninitializedSource : public SymbolicSource {
class SymbolicSizeConstantAddressSource : public SymbolicSource {
public:
const unsigned version;
const KInstruction *allocSite;
const KValue *allocSite;
ref<Expr> size;
SymbolicSizeConstantAddressSource(unsigned _version,
const KInstruction *_allocSite,

SymbolicSizeConstantAddressSource(unsigned _version, const KValue *_allocSite,
ref<Expr> _size)
: version(_version), allocSite(_allocSite), size(_size) {}

Expand Down
58 changes: 32 additions & 26 deletions include/klee/Module/KCallable.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,66 +10,72 @@
#ifndef KLEE_KCALLABLE_H
#define KLEE_KCALLABLE_H

#include <string>

#include "klee/Module/KValue.h"
#include "klee/Support/CompilerWarning.h"
DISABLE_WARNING_PUSH
DISABLE_WARNING_DEPRECATED_DECLARATIONS
#include "llvm/ADT/Twine.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/Casting.h"
DISABLE_WARNING_POP

#include <functional>
#include <string>

namespace klee {
/// Wrapper for callable objects passed in callExternalFunction
class KCallable {
public:
enum CallableKind { CK_Function, CK_InlineAsm };

private:
const CallableKind Kind;
struct KCallable : public KValue {
protected:
KCallable(llvm::Value *value, KValue::Kind kind) : KValue(value, kind) {}

public:
KCallable(CallableKind Kind) : Kind(Kind) {}

CallableKind getKind() const { return Kind; }

virtual llvm::StringRef getName() const = 0;
virtual llvm::FunctionType *getFunctionType() const = 0;
virtual llvm::Value *getValue() = 0;

virtual ~KCallable() = default;
static bool classof(const KValue *rhs) {
return rhs->getKind() == KValue::Kind::FUNCTION ||
rhs->getKind() == KValue::Kind::INLINE_ASM;
}
};

class KInlineAsm : public KCallable {
struct KInlineAsm : public KCallable {
private:
/* Prepared name of ASM code */
std::string name;

static unsigned getFreshAsmId() {
static unsigned globalId = 0;
return globalId++;
}

llvm::InlineAsm *value;
std::string name;

public:
KInlineAsm(llvm::InlineAsm *value)
: KCallable(CK_InlineAsm), value(value),
KInlineAsm(llvm::InlineAsm *inlineAsm)
: KCallable(inlineAsm, KValue::Kind::INLINE_ASM),
name("__asm__" + llvm::Twine(getFreshAsmId()).str()) {}

llvm::StringRef getName() const override { return name; }

llvm::FunctionType *getFunctionType() const override {
return value->getFunctionType();
return inlineAsm()->getFunctionType();
}

llvm::Value *getValue() override { return value; }
static bool classof(const KValue *rhs) {
return rhs->getKind() == KValue::Kind::INLINE_ASM;
}

static bool classof(const KCallable *callable) {
return callable->getKind() == CK_InlineAsm;
[[nodiscard]] llvm::InlineAsm *inlineAsm() const {
return llvm::dyn_cast<llvm::InlineAsm>(value);
}

llvm::InlineAsm *getInlineAsm() { return value; }
[[nodiscard]] bool operator<(const KValue &rhs) const override {
return getKind() == rhs.getKind()
? getName() < llvm::cast<KInlineAsm>(rhs).getName()
: getKind() < rhs.getKind();
}
[[nodiscard]] unsigned hash() const override {
return std::hash<std::string>{}(name);
}
};

} // namespace klee
Expand Down
24 changes: 19 additions & 5 deletions include/klee/Module/KInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#define KLEE_KINSTRUCTION_H

#include "KModule.h"
#include "KValue.h"

#include "klee/Config/Version.h"
#include "klee/Support/CompilerWarning.h"
#include "llvm/IR/Argument.h"
Expand All @@ -37,7 +39,7 @@ static const unsigned MAGIC_HASH_CONSTANT = 39;

/// KInstruction - Intermediate instruction representation used
/// during execution.
struct KInstruction {
struct KInstruction : public KValue {

struct Index {
unsigned long instID;
Expand Down Expand Up @@ -66,7 +68,9 @@ struct KInstruction {
}
};

llvm::Instruction *inst;
llvm::Instruction *inst() const {
return llvm::dyn_cast_or_null<llvm::Instruction>(value);
}

/// Value numbers for each operand. -1 is an invalid value,
/// otherwise negative numbers are indices (negated and offset by
Expand Down Expand Up @@ -113,14 +117,24 @@ struct KInstruction {
[[nodiscard]] inline KFunction *getKFunction() const {
return getKBlock()->parent;
}
bool operator<(const KInstruction &other) const {
return getID() < other.getID();

[[nodiscard]] bool operator<(const KValue &rhs) const override {
if (getKind() == rhs.getKind()) {
return getID() < cast<KInstruction>(rhs).getID();
} else {
return getKind() < rhs.getKind();
}
}

[[nodiscard]] inline KModule *getKModule() const {
return getKFunction()->parent;
}

unsigned hash() const { return getID().hash(); }
[[nodiscard]] unsigned hash() const override { return getID().hash(); }

static bool classof(const KValue *rhs) {
return rhs->getKind() == Kind::INSTRUCTION;
}
};

struct KGEPInstruction : KInstruction {
Expand Down
Loading
Loading