aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-10-24 16:32:37 +0100
committergingerBill <bill@gingerbill.org>2020-10-24 16:32:37 +0100
commit4629754f7ced5df477eb017872ef65539db64a27 (patch)
treefc2fc4b7a493c58adeb10bf54254fbbad66f2f67 /src/llvm_backend.cpp
parent0061e63db010cdb2043af63527b4c25f45652a51 (diff)
Inline asm expression (-llvm-api)
See https://llvm.org/docs/LangRef.html#inline-assembler-expressions Example: ``` x := asm(i32) -> i32 { "bswap $0", "=r,r", }(123); ``` Allowed directives `#side_effect`, `#align_stack`, `#att`, `#intel` e.g. `asm() #side_effect #intel {...}`
Diffstat (limited to 'src/llvm_backend.cpp')
-rw-r--r--src/llvm_backend.cpp37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 65586d3a6..4abc65ab4 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -9563,6 +9563,43 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
case_ast_node(ie, IndexExpr, expr);
return lb_addr_load(p, lb_build_addr(p, expr));
case_end;
+
+ case_ast_node(ia, InlineAsmExpr, expr);
+ Type *t = type_of_expr(expr);
+ GB_ASSERT(is_type_asm_proc(t));
+
+ String asm_string = {};
+ String constraints_string = {};
+
+ TypeAndValue tav;
+ tav = type_and_value_of_expr(ia->asm_string);
+ GB_ASSERT(is_type_string(tav.type));
+ GB_ASSERT(tav.value.kind == ExactValue_String);
+ asm_string = tav.value.value_string;
+
+ tav = type_and_value_of_expr(ia->constraints_string);
+ GB_ASSERT(is_type_string(tav.type));
+ GB_ASSERT(tav.value.kind == ExactValue_String);
+ constraints_string = tav.value.value_string;
+
+
+ LLVMInlineAsmDialect dialect = LLVMInlineAsmDialectATT;
+ switch (ia->dialect) {
+ case InlineAsmDialect_Default: dialect = LLVMInlineAsmDialectATT; break;
+ case InlineAsmDialect_ATT: dialect = LLVMInlineAsmDialectATT; break;
+ case InlineAsmDialect_Intel: dialect = LLVMInlineAsmDialectIntel; break;
+ default: GB_PANIC("Unhandled inline asm dialect"); break;
+ }
+
+ LLVMTypeRef func_type = LLVMGetElementType(lb_type(p->module, t));
+ LLVMValueRef the_asm = LLVMGetInlineAsm(func_type,
+ cast(char *)asm_string.text, cast(size_t)asm_string.len,
+ cast(char *)constraints_string.text, cast(size_t)constraints_string.len,
+ ia->has_side_effects, ia->is_align_stack, dialect
+ );
+ GB_ASSERT(the_asm != nullptr);
+ return {the_asm, t};
+ case_end;
}
GB_PANIC("lb_build_expr: %.*s", LIT(ast_strings[expr->kind]));