Skip to content

[X86] Add support for MS inp functions. #93804

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

Merged
merged 5 commits into from
May 31, 2024
Merged

Conversation

MalaySanghi
Copy link
Contributor

@MalaySanghi MalaySanghi commented May 30, 2024

support _inp, _inpw, _inpd.
These functions were removed from the Windows runtime library, but aare still supported for kernel mode development.

support _inp, _inpw, _inpd, inp, inpw.
These functions were removed from the Windows runtime library, but aare still supported for kernel mode development.
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:X86 clang:headers Headers provided by Clang, e.g. for intrinsics labels May 30, 2024
@llvmbot
Copy link
Member

llvmbot commented May 30, 2024

@llvm/pr-subscribers-backend-x86

Author: Malay Sanghi (MalaySanghi)

Changes

support _inp, _inpw, _inpd, inp, inpw.
These functions were removed from the Windows runtime library, but aare still supported for kernel mode development.


Full diff: https://github.com/llvm/llvm-project/pull/93804.diff

2 Files Affected:

  • (modified) clang/lib/Headers/intrin.h (+22)
  • (modified) clang/test/CodeGen/X86/ms-x86-intrinsics.c (+76)
diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
index 5ceb986a1f652..67a062d2166b0 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -329,6 +329,28 @@ static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst,
 static __inline__ void __DEFAULT_FN_ATTRS __halt(void) {
   __asm__ volatile("hlt");
 }
+
+static inline int _inp(unsigned short port) {
+  int ret;
+  __asm__ volatile("inb %b1, %b0" : "=a"(ret) : "Nd"(port));
+  return ret;
+}
+
+static inline unsigned short _inpw(unsigned short port) {
+  unsigned short ret;
+  __asm__ volatile("inb %w1, %b0" : "=a"(ret) : "Nd"(port));
+  return ret;
+}
+
+static inline unsigned long _inpd(unsigned short port) {
+  unsigned long ret;
+  __asm__ volatile("inb %k1, %b0" : "=a"(ret) : "Nd"(port));
+  return ret;
+}
+
+#define inp(port) _inp((port))
+#define inpw(port) _inpw((port))
+
 #endif
 
 #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
diff --git a/clang/test/CodeGen/X86/ms-x86-intrinsics.c b/clang/test/CodeGen/X86/ms-x86-intrinsics.c
index aa557c8e19a83..c51f2d53ca771 100644
--- a/clang/test/CodeGen/X86/ms-x86-intrinsics.c
+++ b/clang/test/CodeGen/X86/ms-x86-intrinsics.c
@@ -63,6 +63,82 @@ unsigned __int64 test__emulu(unsigned int a, unsigned int b) {
 // CHECK: [[RES:%[0-9]+]] = mul nuw i64 [[Y]], [[X]]
 // CHECK: ret i64 [[RES]]
 
+
+int test_inp(unsigned short port) {
+  return _inp(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inp(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT:  entry:
+// CHECK-I386-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inp(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT:  entry:
+// CHECK-X64-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT:    ret i32 [[TMP0]]
+
+unsigned short test_inpw(unsigned short port) {
+  return _inpw(port);
+}
+// CHECK-I386-LABEL: define dso_local zeroext i16 @test_inpw(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT:  entry:
+// CHECK-I386-NEXT:    [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT:    ret i16 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i16 @test_inpw(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT:  entry:
+// CHECK-X64-NEXT:    [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT:    ret i16 [[TMP0]]
+
+unsigned long test_inpd(unsigned short port) {
+  return _inpd(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inpd(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT:  entry:
+// CHECK-I386-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:k}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inpd(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT:  entry:
+// CHECK-X64-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:k}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT:    ret i32 [[TMP0]]
+
+int test_inp2(unsigned short port) {
+  return inp(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inp2(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT:  entry:
+// CHECK-I386-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inp2(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT:  entry:
+// CHECK-X64-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT:    ret i32 [[TMP0]]
+
+unsigned short test_inpw2(unsigned short port) {
+  return inpw(port);
+}
+// CHECK-I386-LABEL: define dso_local zeroext i16 @test_inpw2(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT:  entry:
+// CHECK-I386-NEXT:    [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT:    ret i16 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i16 @test_inpw2(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT:  entry:
+// CHECK-X64-NEXT:    [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT:    ret i16 [[TMP0]]
+
 #if defined(__x86_64__)
 
 char test__readgsbyte(unsigned long Offset) {

@llvmbot
Copy link
Member

llvmbot commented May 30, 2024

@llvm/pr-subscribers-clang

Author: Malay Sanghi (MalaySanghi)

Changes

support _inp, _inpw, _inpd, inp, inpw.
These functions were removed from the Windows runtime library, but aare still supported for kernel mode development.


Full diff: https://github.com/llvm/llvm-project/pull/93804.diff

2 Files Affected:

  • (modified) clang/lib/Headers/intrin.h (+22)
  • (modified) clang/test/CodeGen/X86/ms-x86-intrinsics.c (+76)
diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h
index 5ceb986a1f652..67a062d2166b0 100644
--- a/clang/lib/Headers/intrin.h
+++ b/clang/lib/Headers/intrin.h
@@ -329,6 +329,28 @@ static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst,
 static __inline__ void __DEFAULT_FN_ATTRS __halt(void) {
   __asm__ volatile("hlt");
 }
+
+static inline int _inp(unsigned short port) {
+  int ret;
+  __asm__ volatile("inb %b1, %b0" : "=a"(ret) : "Nd"(port));
+  return ret;
+}
+
+static inline unsigned short _inpw(unsigned short port) {
+  unsigned short ret;
+  __asm__ volatile("inb %w1, %b0" : "=a"(ret) : "Nd"(port));
+  return ret;
+}
+
+static inline unsigned long _inpd(unsigned short port) {
+  unsigned long ret;
+  __asm__ volatile("inb %k1, %b0" : "=a"(ret) : "Nd"(port));
+  return ret;
+}
+
+#define inp(port) _inp((port))
+#define inpw(port) _inpw((port))
+
 #endif
 
 #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
diff --git a/clang/test/CodeGen/X86/ms-x86-intrinsics.c b/clang/test/CodeGen/X86/ms-x86-intrinsics.c
index aa557c8e19a83..c51f2d53ca771 100644
--- a/clang/test/CodeGen/X86/ms-x86-intrinsics.c
+++ b/clang/test/CodeGen/X86/ms-x86-intrinsics.c
@@ -63,6 +63,82 @@ unsigned __int64 test__emulu(unsigned int a, unsigned int b) {
 // CHECK: [[RES:%[0-9]+]] = mul nuw i64 [[Y]], [[X]]
 // CHECK: ret i64 [[RES]]
 
+
+int test_inp(unsigned short port) {
+  return _inp(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inp(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT:  entry:
+// CHECK-I386-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inp(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT:  entry:
+// CHECK-X64-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT:    ret i32 [[TMP0]]
+
+unsigned short test_inpw(unsigned short port) {
+  return _inpw(port);
+}
+// CHECK-I386-LABEL: define dso_local zeroext i16 @test_inpw(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT:  entry:
+// CHECK-I386-NEXT:    [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT:    ret i16 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i16 @test_inpw(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT:  entry:
+// CHECK-X64-NEXT:    [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT:    ret i16 [[TMP0]]
+
+unsigned long test_inpd(unsigned short port) {
+  return _inpd(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inpd(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT:  entry:
+// CHECK-I386-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:k}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inpd(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT:  entry:
+// CHECK-X64-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:k}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT:    ret i32 [[TMP0]]
+
+int test_inp2(unsigned short port) {
+  return inp(port);
+}
+// CHECK-I386-LABEL: define dso_local i32 @test_inp2(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT:  entry:
+// CHECK-I386-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT:    ret i32 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i32 @test_inp2(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT:  entry:
+// CHECK-X64-NEXT:    [[TMP0:%.*]] = tail call i32 asm sideeffect "inb ${1:b}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT:    ret i32 [[TMP0]]
+
+unsigned short test_inpw2(unsigned short port) {
+  return inpw(port);
+}
+// CHECK-I386-LABEL: define dso_local zeroext i16 @test_inpw2(
+// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
+// CHECK-I386-NEXT:  entry:
+// CHECK-I386-NEXT:    [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-I386-NEXT:    ret i16 [[TMP0]]
+//
+// CHECK-X64-LABEL: define dso_local i16 @test_inpw2(
+// CHECK-X64-SAME: i16 noundef [[PORT:%.*]])
+// CHECK-X64-NEXT:  entry:
+// CHECK-X64-NEXT:    [[TMP0:%.*]] = tail call i16 asm sideeffect "inb ${1:w}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
+// CHECK-X64-NEXT:    ret i16 [[TMP0]]
+
 #if defined(__x86_64__)
 
 char test__readgsbyte(unsigned long Offset) {

@MalaySanghi
Copy link
Contributor Author

This could probably have been a part of #93774 . If that's preferred, I'll add this change as a new commit to that PR.

@MalaySanghi
Copy link
Contributor Author

tag @phoebewang @FreddyLeaf @RKSimon for review

@MalaySanghi MalaySanghi changed the title Add support for MS inp functions. [X86] Add support for MS inp functions. May 30, 2024
Comment on lines 70 to 71
// CHECK-I386-LABEL: define dso_local i32 @test_inp(
// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can be put in one line now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I had tried that. A variable (PORT in this case) is not allowed in CHECK-LABEL

}
// CHECK-LABEL: i32 @test_inpd(i16 noundef
// CHECK-SAME: [[PORT:%.*]])
// CHECK: [[TMP0:%.*]] = tail call i32 asm sideeffect "inl ${1:k}, ${0:b}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 [[PORT]])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be ={eax} for 32-bit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In llvm-IR this remain ax.
There were other issues which I fixed. I had only tested the outp end-end and modelled this after the outp intrinsic. I've tested this end-end now.

_ind(port)

becomes

%0 = tail call i32 asm sideeffect "inl ${1:w}, ${0:k}", "={ax},N{dx},~{dirflag},~{fpsr},~{flags}"(i16 %port) #3, !srcloc !6

and eventually

inl	%dx, %eax

Copy link
Contributor

@phoebewang phoebewang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@phoebewang phoebewang merged commit 089dfee into llvm:main May 31, 2024
4 of 6 checks passed
Copy link
Collaborator

@RKSimon RKSimon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add this to ReleaseNotes?

MalaySanghi added a commit to MalaySanghi/llvm-project that referenced this pull request Jun 18, 2024
@MalaySanghi MalaySanghi deleted the ms_inp branch June 21, 2024 05:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:X86 clang:headers Headers provided by Clang, e.g. for intrinsics clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants