add basic support for inline assembly
Let's see if this is sufficient for LLVM's optimizers..
fixes
MODIFY
ir/instr.cpp
ir/instr.cpp
@@ -1845,6 +1845,12 @@ unique_ptr<Instr> FnCall::dup(const string &suffix) const {
}
+InlineAsm::InlineAsm(Type &type, string &&name, const string &asm_str,
+ const string &constraints, FnAttrs &&attrs)
+ : FnCall(type, move(name), "asm " + asm_str + ", " + constraints,
+ move(attrs)) {}
+
+
ICmp::ICmp(Type &type, string &&name, Cond cond, Value &a, Value &b)
: Instr(type, move(name)), a(&a), b(&b), cond(cond), defined(cond != Any) {
if (!defined)

MODIFY
ir/instr.h
ir/instr.h
@@ -809,7 +809,7 @@ public:
};
-class FnCall final : public MemInstr {
+class FnCall : public MemInstr {
private:
std::string fnName;
std::vector<std::pair<Value*, ParamAttrs>> args;
@@ -842,6 +842,13 @@ public:
};
+class InlineAsm final : public FnCall {
+public:
+ InlineAsm(Type &type, std::string &&name, const std::string &asm_str,
+ const std::string &constraints, FnAttrs &&attrs = FnAttrs::None);
+};
+
+
class VaStart final : public Instr {
Value *ptr;
public:

MODIFY
llvm_util/llvm2alive.cpp
llvm_util/llvm2alive.cpp
#include "llvm/IR/CFG.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/Operator.h"
#include <unordered_map>
@@ -241,19 +242,30 @@ public:
approx = get<3>(known);
}
- auto fn = i.getCalledFunction();
- if (!fn) // TODO: support indirect calls
- return error(i);
-
auto ty = llvm_type2alive(i.getType());
if (!ty)
return error(i);
+ unique_ptr<FnCall> call;
+ auto fn = i.getCalledFunction();
+
+ if (auto *iasm = dyn_cast<llvm::InlineAsm>(i.getCalledOperand())) {
+ assert(!approx);
+ if (!iasm->canThrow())
+ attrs.set(FnAttrs::NoThrow);
+ call = make_unique<InlineAsm>(*ty, value_name(i), iasm->getAsmString(),
+ iasm->getConstraintString(), move(attrs));
+ } else {
+ if (!fn) // TODO: support indirect calls
+ return error(i);
+
if (fn->getName().substr(0, 15) == "__llvm_profile_")
return NOP(i);
+ }
llvm::AttributeList attrs_callsite = i.getAttributes();
- llvm::AttributeList attrs_fndef = fn->getAttributes();
+ llvm::AttributeList attrs_fndef = fn ? fn->getAttributes()
+ : llvm::AttributeList();
const auto &ret = llvm::AttributeList::ReturnIndex;
const auto &fnidx = llvm::AttributeList::FunctionIndex;
@@ -267,7 +279,8 @@ public:
attrs.set(FnAttrs::NNaN);
}
- auto call = make_unique<FnCall>(*ty, value_name(i),
+ if (fn)
+ call = make_unique<FnCall>(*ty, value_name(i),
'@' + fn->getName().str(), move(attrs));
unique_ptr<Instr> ret_val;
@@ -279,7 +292,7 @@ public:
unsigned attr_argidx = llvm::AttributeList::FirstArgIndex + argidx;
approx |= !handleParamAttrs(attrs_callsite.getAttributes(attr_argidx),
pattr, true);
- if (argidx < fn->arg_size())
+ if (fn && argidx < fn->arg_size())
approx |= !handleParamAttrs(attrs_fndef.getAttributes(attr_argidx),
pattr, true);

ADD
tests/alive-tv/inline-asm.srctgt.ll
+define i32 @src(i32 %Y, i1 %c) {
+ br i1 %c, label %then, label %else
+
+then:
+ %X = call i32 asm "bswap $0", "=r,r"(i32 %Y)
+ ret i32 %X
+
+else:
+ %Z = call i32 asm "bswap $0", "=r,r"(i32 %Y)
+ ret i32 %Z
+}
+
+define i32 @tgt(i32 %Y, i1 %c) {
+ %X = call i32 asm "bswap $0", "=r,r"(i32 %Y)
+ ret i32 %X
+}

add basic support for inline assembly
Let's see if this is sufficient for LLVM's optimizers..
fixes #628