diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -904,12 +904,58 @@ * * @see InlineAsm::get() */ -LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, char *AsmString, - size_t AsmStringSize, char *Constraints, +LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, const char *AsmString, + size_t AsmStringSize, const char *Constraints, size_t ConstraintsSize, LLVMBool HasSideEffects, LLVMBool IsAlignStack, LLVMInlineAsmDialect Dialect, LLVMBool CanThrow); +/** + * Get the template string used for an inline assembly snippet + * + */ +const char *LLVMGetInlineAsmAsmString(LLVMValueRef InlineAsmVal, size_t *Len); + +/** + * Get the raw constraint string for an inline assembly snippet + * + */ +const char *LLVMGetInlineAsmConstraintString(LLVMValueRef InlineAsmVal, + size_t *Len); + +/** + * Get the dialect used by the inline asm snippet + * + */ +LLVMInlineAsmDialect LLVMGetInlineAsmDialect(LLVMValueRef InlineAsmVal); + +/** + * Get the function type of the inline assembly snippet. The same type that + * was passed into LLVMGetInlineAsm originally + * + * @see LLVMGetInlineAsm + * + */ +LLVMTypeRef LLVMGetInlineAsmFunctionType(LLVMValueRef InlineAsmVal); + +/** + * Get if the inline asm snippet has side effects + * + */ +LLVMBool LLVMGetInlineAsmHasSideEffects(LLVMValueRef InlineAsmVal); + +/** + * Get if the inline asm snippet needs an aligned stack + * + */ +LLVMBool LLVMGetInlineAsmNeedsAlignedStack(LLVMValueRef InlineAsmVal); + +/** + * Get if the inline asm snippet may unwind the stack + * + */ +LLVMBool LLVMGetInlineAsmCanUnwind(LLVMValueRef InlineAsmVal); + /** * Obtain the context to which this module is associated. * diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -460,8 +460,8 @@ return Str.c_str(); } -LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, char *AsmString, - size_t AsmStringSize, char *Constraints, +LLVMValueRef LLVMGetInlineAsm(LLVMTypeRef Ty, const char *AsmString, + size_t AsmStringSize, const char *Constraints, size_t ConstraintsSize, LLVMBool HasSideEffects, LLVMBool IsAlignStack, LLVMInlineAsmDialect Dialect, LLVMBool CanThrow) { @@ -480,6 +480,61 @@ HasSideEffects, IsAlignStack, AD, CanThrow)); } +const char *LLVMGetInlineAsmAsmString(LLVMValueRef InlineAsmVal, size_t *Len) { + + Value *Val = unwrap(InlineAsmVal); + const std::string &AsmString = cast(Val)->getAsmString(); + + *Len = AsmString.length(); + return AsmString.c_str(); +} + +const char *LLVMGetInlineAsmConstraintString(LLVMValueRef InlineAsmVal, + size_t *Len) { + Value *Val = unwrap(InlineAsmVal); + const std::string &ConstraintString = + cast(Val)->getConstraintString(); + + *Len = ConstraintString.length(); + return ConstraintString.c_str(); +} + +LLVMInlineAsmDialect LLVMGetInlineAsmDialect(LLVMValueRef InlineAsmVal) { + + Value *Val = unwrap(InlineAsmVal); + InlineAsm::AsmDialect Dialect = cast(Val)->getDialect(); + + switch (Dialect) { + case InlineAsm::AD_ATT: + return LLVMInlineAsmDialectATT; + case InlineAsm::AD_Intel: + return LLVMInlineAsmDialectIntel; + } + + llvm_unreachable("Unrecognized inline assembly dialect"); + return LLVMInlineAsmDialectATT; +} + +LLVMTypeRef LLVMGetInlineAsmFunctionType(LLVMValueRef InlineAsmVal) { + Value *Val = unwrap(InlineAsmVal); + return (LLVMTypeRef)cast(Val)->getFunctionType(); +} + +LLVMBool LLVMGetInlineAsmHasSideEffects(LLVMValueRef InlineAsmVal) { + Value *Val = unwrap(InlineAsmVal); + return cast(Val)->hasSideEffects(); +} + +LLVMBool LLVMGetInlineAsmNeedsAlignedStack(LLVMValueRef InlineAsmVal) { + Value *Val = unwrap(InlineAsmVal); + return cast(Val)->isAlignStack(); +} + +LLVMBool LLVMGetInlineAsmCanUnwind(LLVMValueRef InlineAsmVal) { + Value *Val = unwrap(InlineAsmVal); + return cast(Val)->canThrow(); +} + /*--.. Operations on module contexts ......................................--*/ LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M) { return wrap(&unwrap(M)->getContext()); diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll --- a/llvm/test/Bindings/llvm-c/echo.ll +++ b/llvm/test/Bindings/llvm-c/echo.ll @@ -113,6 +113,22 @@ ret i32 %1 } +define i32 @call_inline_asm(i32 %0) { + ; Test Intel syntax + %2 = tail call i32 asm sideeffect inteldialect "mov $0, $1", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0) + %3 = tail call i32 asm sideeffect inteldialect "lea $0, [$1+$2]", "=r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0, i32 %2) + %4 = tail call i32 asm inteldialect "mov $0, $1", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %3) + %5 = tail call i32 asm inteldialect unwind "mov $0, $1", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %4) + %6 = tail call i32 asm alignstack inteldialect "mov $0, $1", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %5) + + ; Test AT&T syntax + %7 = tail call i32 asm "mov $1, $0", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %6) + %8 = tail call i32 asm sideeffect "mov $1, $0", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %7) + %9 = tail call i32 asm alignstack "mov $1, $0", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %8) + %10 = tail call i32 asm alignstack unwind "mov $1, $0", "=r,r,~{dirflag},~{fpsr},~{flags}"(i32 %9) + ret i32 %10 +} + define i32 @cond(i32 %a, i32 %b) { br label %br unreachable: diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp --- a/llvm/tools/llvm-c-test/echo.cpp +++ b/llvm/tools/llvm-c-test/echo.cpp @@ -406,6 +406,32 @@ } } +static LLVMValueRef clone_inline_asm(LLVMValueRef Asm, LLVMModuleRef M) { + + if (!LLVMIsAInlineAsm(Asm)) + report_fatal_error("Expected inline assembly"); + + size_t AsmStringSize = 0; + const char *AsmString = LLVMGetInlineAsmAsmString(Asm, &AsmStringSize); + + size_t ConstraintStringSize = 0; + const char *ConstraintString = + LLVMGetInlineAsmConstraintString(Asm, &ConstraintStringSize); + + LLVMInlineAsmDialect AsmDialect = LLVMGetInlineAsmDialect(Asm); + + LLVMTypeRef AsmFunctionType = LLVMGetInlineAsmFunctionType(Asm); + + LLVMBool HasSideEffects = LLVMGetInlineAsmHasSideEffects(Asm); + LLVMBool NeedsAlignStack = LLVMGetInlineAsmNeedsAlignedStack(Asm); + LLVMBool CanUnwind = LLVMGetInlineAsmCanUnwind(Asm); + + return LLVMGetInlineAsm(AsmFunctionType, AsmString, AsmStringSize, + ConstraintString, ConstraintStringSize, + HasSideEffects, NeedsAlignStack, AsmDialect, + CanUnwind); +} + struct FunCloner { LLVMValueRef Fun; LLVMModuleRef M; @@ -435,6 +461,10 @@ if (i != VMap.end()) return i->second; + // Inline assembly is a Value, but not an Instruction + if (LLVMIsAInlineAsm(Src)) + return clone_inline_asm(Src, M); + if (!LLVMIsAInstruction(Src)) report_fatal_error("Expected an instruction");